@capawesome/capacitor-live-update 7.5.0 → 7.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +84 -57
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +2 -1
- package/ios/Plugin/LiveUpdate.swift +39 -12
- package/ios/Plugin/LiveUpdateHttpClient.swift +6 -1
- package/ios/Plugin/LiveUpdatePlugin.swift +1 -1
- package/package.json +1 -1
|
@@ -7,9 +7,11 @@ import android.content.pm.PackageManager;
|
|
|
7
7
|
import android.content.res.AssetManager;
|
|
8
8
|
import android.os.Build;
|
|
9
9
|
import android.os.Handler;
|
|
10
|
+
import android.os.Looper;
|
|
10
11
|
import android.util.Base64;
|
|
11
12
|
import androidx.annotation.NonNull;
|
|
12
13
|
import androidx.annotation.Nullable;
|
|
14
|
+
import androidx.core.content.pm.PackageInfoCompat;
|
|
13
15
|
import com.getcapacitor.Bridge;
|
|
14
16
|
import com.getcapacitor.Logger;
|
|
15
17
|
import com.getcapacitor.plugin.WebView;
|
|
@@ -102,7 +104,8 @@ public class LiveUpdate {
|
|
|
102
104
|
private final SharedPreferences.Editor webViewSettingsEditor;
|
|
103
105
|
|
|
104
106
|
private final String bundlesDirectory = "_capacitor_live_update_bundles"; // DO NOT CHANGE!
|
|
105
|
-
private final
|
|
107
|
+
private final String downloadsDirectory = "capawesome_capacitor_live_update_downloads";
|
|
108
|
+
private final Handler rollbackHandler = new Handler(Looper.getMainLooper());
|
|
106
109
|
private final String manifestFileName = "capawesome-live-update-manifest.json"; // DO NOT CHANGE!
|
|
107
110
|
|
|
108
111
|
private boolean initialPageLoaded = false;
|
|
@@ -123,6 +126,9 @@ public class LiveUpdate {
|
|
|
123
126
|
// Set the device ID on the HTTP client (after any potential config reset)
|
|
124
127
|
this.httpClient.setDeviceId(getDeviceId());
|
|
125
128
|
|
|
129
|
+
// Delete the leftovers of downloads that were interrupted by a process kill
|
|
130
|
+
tryDeleteDownloadsDirectory();
|
|
131
|
+
|
|
126
132
|
// Start the rollback timer to rollback to the default bundle
|
|
127
133
|
// if the app is not ready after a certain time
|
|
128
134
|
startRollbackTimer();
|
|
@@ -530,7 +536,10 @@ public class LiveUpdate {
|
|
|
530
536
|
|
|
531
537
|
// Move the bundle directory to the bundles directory
|
|
532
538
|
File bundleDirectory = buildBundleDirectoryFor(bundleId);
|
|
533
|
-
indexHtmlFile.getParentFile().renameTo(bundleDirectory);
|
|
539
|
+
boolean moved = indexHtmlFile.getParentFile().renameTo(bundleDirectory);
|
|
540
|
+
if (!moved) {
|
|
541
|
+
throw new Exception(LiveUpdatePlugin.ERROR_BUNDLE_MOVE_FAILED);
|
|
542
|
+
}
|
|
534
543
|
}
|
|
535
544
|
|
|
536
545
|
private void addBundleOfTypeManifest(@NonNull String bundleId, @NonNull File directory) throws Exception {
|
|
@@ -539,7 +548,7 @@ public class LiveUpdate {
|
|
|
539
548
|
|
|
540
549
|
private void addBundleOfTypeZip(@NonNull String bundleId, @NonNull File zipFile) throws Exception {
|
|
541
550
|
// Unzip the file to the bundle directory
|
|
542
|
-
File unzippedDirectory =
|
|
551
|
+
File unzippedDirectory = unzipDownloadedBundle(zipFile);
|
|
543
552
|
// Add the bundle
|
|
544
553
|
addBundle(bundleId, unzippedDirectory);
|
|
545
554
|
}
|
|
@@ -552,14 +561,8 @@ public class LiveUpdate {
|
|
|
552
561
|
return new File(plugin.getContext().getFilesDir(), bundlesDirectory + "/" + bundleId);
|
|
553
562
|
}
|
|
554
563
|
|
|
555
|
-
private File
|
|
556
|
-
|
|
557
|
-
return new File(plugin.getContext().getCacheDir(), fileName);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
private File buildTemporaryZipFile() {
|
|
561
|
-
String fileName = UUID.randomUUID().toString() + ".zip";
|
|
562
|
-
return new File(plugin.getContext().getCacheDir(), fileName);
|
|
564
|
+
private File buildDownloadsDirectory() {
|
|
565
|
+
return new File(plugin.getContext().getCacheDir(), downloadsDirectory);
|
|
563
566
|
}
|
|
564
567
|
|
|
565
568
|
private void copyCurrentBundleFile(@NonNull ManifestItem fileToCopy, @NonNull File destinationDirectory) throws IOException {
|
|
@@ -646,10 +649,10 @@ public class LiveUpdate {
|
|
|
646
649
|
}
|
|
647
650
|
}
|
|
648
651
|
|
|
649
|
-
private File
|
|
650
|
-
File
|
|
651
|
-
|
|
652
|
-
return
|
|
652
|
+
private File createTemporaryDownloadDirectory() {
|
|
653
|
+
File temporaryDirectory = new File(buildDownloadsDirectory(), UUID.randomUUID().toString());
|
|
654
|
+
temporaryDirectory.mkdirs();
|
|
655
|
+
return temporaryDirectory;
|
|
653
656
|
}
|
|
654
657
|
|
|
655
658
|
private void deleteBundleById(@NonNull String bundleId) {
|
|
@@ -675,6 +678,23 @@ public class LiveUpdate {
|
|
|
675
678
|
file.delete();
|
|
676
679
|
}
|
|
677
680
|
|
|
681
|
+
@NonNull
|
|
682
|
+
private EmptyCallback deleteTemporaryDirectoryOnCompletion(@NonNull File temporaryDirectory, @NonNull EmptyCallback callback) {
|
|
683
|
+
return new EmptyCallback() {
|
|
684
|
+
@Override
|
|
685
|
+
public void success() {
|
|
686
|
+
deleteFileRecursively(temporaryDirectory);
|
|
687
|
+
callback.success();
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
@Override
|
|
691
|
+
public void error(@NonNull Exception exception) {
|
|
692
|
+
deleteFileRecursively(temporaryDirectory);
|
|
693
|
+
callback.error(exception);
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
|
|
678
698
|
private void deleteUnusedBundles() {
|
|
679
699
|
String[] bundleIds = getDownloadedBundleIds();
|
|
680
700
|
for (String bundleId : bundleIds) {
|
|
@@ -845,10 +865,10 @@ public class LiveUpdate {
|
|
|
845
865
|
@NonNull String downloadUrl,
|
|
846
866
|
@NonNull EmptyCallback completionCallback
|
|
847
867
|
) {
|
|
868
|
+
// Create a temporary directory that is deleted once the download completed or failed
|
|
869
|
+
File temporaryDirectory = createTemporaryDownloadDirectory();
|
|
870
|
+
EmptyCallback callback = deleteTemporaryDirectoryOnCompletion(temporaryDirectory, completionCallback);
|
|
848
871
|
try {
|
|
849
|
-
// Create a temporary directory
|
|
850
|
-
File temporaryDirectory = createTemporaryDirectory();
|
|
851
|
-
|
|
852
872
|
// Download the latest manifest
|
|
853
873
|
downloadBundleFile(
|
|
854
874
|
downloadUrl,
|
|
@@ -898,31 +918,31 @@ public class LiveUpdate {
|
|
|
898
918
|
try {
|
|
899
919
|
// Add the bundle
|
|
900
920
|
addBundleOfTypeManifest(bundleId, temporaryDirectory);
|
|
901
|
-
|
|
921
|
+
callback.success();
|
|
902
922
|
} catch (Exception e) {
|
|
903
|
-
|
|
923
|
+
callback.error(e);
|
|
904
924
|
}
|
|
905
925
|
}
|
|
906
926
|
|
|
907
927
|
@Override
|
|
908
928
|
public void error(@NonNull Exception exception) {
|
|
909
|
-
|
|
929
|
+
callback.error(exception);
|
|
910
930
|
}
|
|
911
931
|
}
|
|
912
932
|
);
|
|
913
933
|
} catch (Exception e) {
|
|
914
|
-
|
|
934
|
+
callback.error(e);
|
|
915
935
|
}
|
|
916
936
|
}
|
|
917
937
|
|
|
918
938
|
@Override
|
|
919
939
|
public void error(@NonNull Exception exception) {
|
|
920
|
-
|
|
940
|
+
callback.error(exception);
|
|
921
941
|
}
|
|
922
942
|
}
|
|
923
943
|
);
|
|
924
944
|
} catch (Exception e) {
|
|
925
|
-
|
|
945
|
+
callback.error(e);
|
|
926
946
|
}
|
|
927
947
|
}
|
|
928
948
|
|
|
@@ -933,39 +953,42 @@ public class LiveUpdate {
|
|
|
933
953
|
@NonNull String downloadUrl,
|
|
934
954
|
@NonNull EmptyCallback completionCallback
|
|
935
955
|
) {
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
956
|
+
// Create a temporary directory that is deleted once the download completed or failed
|
|
957
|
+
File temporaryDirectory = createTemporaryDownloadDirectory();
|
|
958
|
+
EmptyCallback callback = deleteTemporaryDirectoryOnCompletion(temporaryDirectory, completionCallback);
|
|
959
|
+
File zipFile = new File(temporaryDirectory, "bundle.zip");
|
|
960
|
+
try {
|
|
961
|
+
// Download the bundle
|
|
962
|
+
downloadAndVerifyFile(
|
|
963
|
+
downloadUrl,
|
|
964
|
+
zipFile,
|
|
965
|
+
checksum,
|
|
966
|
+
signature,
|
|
967
|
+
(downloadedBytes, totalBytes) -> {
|
|
968
|
+
DownloadBundleProgressEvent event = new DownloadBundleProgressEvent(bundleId, downloadedBytes, totalBytes);
|
|
969
|
+
notifyDownloadBundleProgressListeners(event);
|
|
970
|
+
},
|
|
971
|
+
new EmptyCallback() {
|
|
972
|
+
@Override
|
|
973
|
+
public void success() {
|
|
974
|
+
try {
|
|
975
|
+
// Add the bundle
|
|
976
|
+
addBundleOfTypeZip(bundleId, zipFile);
|
|
977
|
+
callback.success();
|
|
978
|
+
} catch (Exception e) {
|
|
979
|
+
callback.error(e);
|
|
980
|
+
}
|
|
958
981
|
}
|
|
959
|
-
}
|
|
960
982
|
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
completionCallback.error(exception);
|
|
983
|
+
@Override
|
|
984
|
+
public void error(@NonNull Exception exception) {
|
|
985
|
+
callback.error(exception);
|
|
986
|
+
}
|
|
966
987
|
}
|
|
967
|
-
|
|
968
|
-
)
|
|
988
|
+
);
|
|
989
|
+
} catch (Exception e) {
|
|
990
|
+
callback.error(e);
|
|
991
|
+
}
|
|
969
992
|
}
|
|
970
993
|
|
|
971
994
|
private void fetchLatestBundleInternal(
|
|
@@ -1169,7 +1192,7 @@ public class LiveUpdate {
|
|
|
1169
1192
|
}
|
|
1170
1193
|
|
|
1171
1194
|
private int getVersionCodeAsInt() throws PackageManager.NameNotFoundException {
|
|
1172
|
-
return getPackageInfo()
|
|
1195
|
+
return (int) PackageInfoCompat.getLongVersionCode(getPackageInfo());
|
|
1173
1196
|
}
|
|
1174
1197
|
|
|
1175
1198
|
private String getVersionCodeAsString() throws PackageManager.NameNotFoundException {
|
|
@@ -1431,8 +1454,12 @@ public class LiveUpdate {
|
|
|
1431
1454
|
}
|
|
1432
1455
|
}
|
|
1433
1456
|
|
|
1434
|
-
private
|
|
1435
|
-
|
|
1457
|
+
private void tryDeleteDownloadsDirectory() {
|
|
1458
|
+
deleteFileRecursively(buildDownloadsDirectory());
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
private File unzipDownloadedBundle(@NonNull File zipFile) throws IOException {
|
|
1462
|
+
File destination = new File(zipFile.getParentFile(), "bundle");
|
|
1436
1463
|
String destinationPath = destination.getPath();
|
|
1437
1464
|
ZipFile zip = new ZipFile(zipFile);
|
|
1438
1465
|
// Clear stored Unix permissions to prevent EACCES errors on newer Android versions
|
package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java
CHANGED
|
@@ -37,12 +37,13 @@ import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
|
|
|
37
37
|
public class LiveUpdatePlugin extends Plugin {
|
|
38
38
|
|
|
39
39
|
public static final String TAG = "LiveUpdate";
|
|
40
|
-
public static final String VERSION = "7.5.
|
|
40
|
+
public static final String VERSION = "7.5.2";
|
|
41
41
|
public static final String SHARED_PREFERENCES_NAME = "CapawesomeLiveUpdate"; // DO NOT CHANGE
|
|
42
42
|
public static final String ERROR_APP_ID_MISSING = "appId must be configured.";
|
|
43
43
|
public static final String ERROR_BUNDLE_EXISTS = "bundle already exists.";
|
|
44
44
|
public static final String ERROR_BUNDLE_ID_MISSING = "bundleId must be provided.";
|
|
45
45
|
public static final String ERROR_BUNDLE_INDEX_HTML_MISSING = "The bundle does not contain an index.html file.";
|
|
46
|
+
public static final String ERROR_BUNDLE_MOVE_FAILED = "Bundle could not be moved.";
|
|
46
47
|
public static final String ERROR_BUNDLE_NOT_FOUND = "bundle not found.";
|
|
47
48
|
public static final String ERROR_CHECKSUM_CALCULATION_FAILED = "Failed to calculate checksum.";
|
|
48
49
|
public static final String ERROR_CHECKSUM_MISMATCH = "Checksum mismatch.";
|
|
@@ -13,6 +13,7 @@ import CommonCrypto
|
|
|
13
13
|
private let config: LiveUpdateConfig
|
|
14
14
|
private let defaultWebAssetDir = "public" // DO NOT CHANGE! (See https://dub.sh/Buvz4yj)
|
|
15
15
|
private let defaultServerPathKey = "serverBasePath" // DO NOT CHANGE! (See https://dub.sh/ceDl0zT)
|
|
16
|
+
private let downloadsDirectory = "capawesome_capacitor_live_update_downloads"
|
|
16
17
|
private let httpClient: LiveUpdateHttpClient
|
|
17
18
|
private let libraryDirectoryUrl = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
|
|
18
19
|
private let manifestFileName = "capawesome-live-update-manifest.json" // DO NOT CHANGE!
|
|
@@ -37,6 +38,9 @@ import CommonCrypto
|
|
|
37
38
|
// Set the device ID on the HTTP client (after any potential config reset)
|
|
38
39
|
self.httpClient.setDeviceId(getDeviceId())
|
|
39
40
|
|
|
41
|
+
// Delete the leftovers of downloads that were interrupted by a process kill
|
|
42
|
+
tryDeleteDownloadsDirectory()
|
|
43
|
+
|
|
40
44
|
// Start the rollback timer to rollback to the default bundle
|
|
41
45
|
// if the app is not ready after a certain time
|
|
42
46
|
startRollbackTimer()
|
|
@@ -352,7 +356,7 @@ import CommonCrypto
|
|
|
352
356
|
|
|
353
357
|
private func addBundleOfTypeZip(bundleId: String, zipFile: URL) async throws {
|
|
354
358
|
// Unzip the bundle
|
|
355
|
-
let unzippedDirectory = try self.
|
|
359
|
+
let unzippedDirectory = try self.unzipDownloadedBundle(zipFile: zipFile)
|
|
356
360
|
// Add the bundle
|
|
357
361
|
try self.addBundle(bundleId: bundleId, directory: unzippedDirectory)
|
|
358
362
|
}
|
|
@@ -376,6 +380,10 @@ import CommonCrypto
|
|
|
376
380
|
return url
|
|
377
381
|
}
|
|
378
382
|
|
|
383
|
+
private func buildDownloadsDirectoryUrl() -> URL {
|
|
384
|
+
return cachesDirectoryUrl.appendingPathComponent(downloadsDirectory)
|
|
385
|
+
}
|
|
386
|
+
|
|
379
387
|
private func copyCurrentBundleFile(fileToCopy: ManifestItem, toDirectory: URL) throws {
|
|
380
388
|
let currentBundleId = getCurrentBundleId()
|
|
381
389
|
let destination = toDirectory.appendingPathComponent(fileToCopy.href)
|
|
@@ -425,8 +433,8 @@ import CommonCrypto
|
|
|
425
433
|
}
|
|
426
434
|
}
|
|
427
435
|
|
|
428
|
-
private func
|
|
429
|
-
let temporaryDirectory =
|
|
436
|
+
private func createTemporaryDownloadDirectory() throws -> URL {
|
|
437
|
+
let temporaryDirectory = buildDownloadsDirectoryUrl().appendingPathComponent(UUID().uuidString)
|
|
430
438
|
try FileManager.default.createDirectory(at: temporaryDirectory, withIntermediateDirectories: true, attributes: nil)
|
|
431
439
|
return temporaryDirectory
|
|
432
440
|
}
|
|
@@ -460,7 +468,8 @@ import CommonCrypto
|
|
|
460
468
|
|
|
461
469
|
private func downloadAndVerifyFile(url: String, file: URL, checksum: String?, signature: String?, callback: ((Progress) -> Void)?) async throws {
|
|
462
470
|
let destination: DownloadRequest.Destination = { _, _ in
|
|
463
|
-
|
|
471
|
+
// `removePreviousFile` ensures that a leftover file from a failed attempt does not fail the download
|
|
472
|
+
return (file, [.createIntermediateDirectories, .removePreviousFile])
|
|
464
473
|
}
|
|
465
474
|
let urlComponents = URLComponents(string: url)!
|
|
466
475
|
let result = try await httpClient.download(url: urlComponents.asURL(), destination: destination, callback: callback)
|
|
@@ -533,8 +542,9 @@ import CommonCrypto
|
|
|
533
542
|
}
|
|
534
543
|
|
|
535
544
|
private func downloadBundleOfTypeManifest(bundleId: String, url: String) async throws {
|
|
536
|
-
// Create a temporary directory
|
|
537
|
-
let temporaryDirectory = try
|
|
545
|
+
// Create a temporary directory that is deleted once the download completed or failed
|
|
546
|
+
let temporaryDirectory = try createTemporaryDownloadDirectory()
|
|
547
|
+
defer { tryDeleteDirectory(temporaryDirectory) }
|
|
538
548
|
// Download the latest manifest
|
|
539
549
|
let latestManifestFile = try await downloadBundleFile(baseUrl: url, href: manifestFileName, directory: temporaryDirectory, callback: nil)
|
|
540
550
|
let latestManifest = try loadManifest(file: latestManifestFile)
|
|
@@ -565,15 +575,17 @@ import CommonCrypto
|
|
|
565
575
|
}
|
|
566
576
|
|
|
567
577
|
private func downloadBundleOfTypeZip(bundleId: String, checksum: String?, signature: String?, url: String) async throws {
|
|
568
|
-
|
|
569
|
-
let
|
|
578
|
+
// Create a temporary directory that is deleted once the download completed or failed
|
|
579
|
+
let temporaryDirectory = try createTemporaryDownloadDirectory()
|
|
580
|
+
defer { tryDeleteDirectory(temporaryDirectory) }
|
|
581
|
+
let zipFile = temporaryDirectory.appendingPathComponent("bundle.zip")
|
|
570
582
|
// Download the bundle
|
|
571
|
-
try await downloadAndVerifyFile(url: url, file:
|
|
583
|
+
try await downloadAndVerifyFile(url: url, file: zipFile, checksum: checksum, signature: signature, callback: { progress in
|
|
572
584
|
let event = DownloadBundleProgressEvent(bundleId: bundleId, downloadedBytes: progress.completedUnitCount, totalBytes: progress.totalUnitCount)
|
|
573
585
|
self.notifyDownloadBundleProgressListeners(event)
|
|
574
586
|
})
|
|
575
587
|
// Add the bundle
|
|
576
|
-
try await addBundleOfTypeZip(bundleId: bundleId, zipFile:
|
|
588
|
+
try await addBundleOfTypeZip(bundleId: bundleId, zipFile: zipFile)
|
|
577
589
|
}
|
|
578
590
|
|
|
579
591
|
private func fetchLatestBundle(_ options: FetchLatestBundleOptions) async throws -> GetLatestBundleResponse? {
|
|
@@ -959,8 +971,23 @@ import CommonCrypto
|
|
|
959
971
|
}
|
|
960
972
|
}
|
|
961
973
|
|
|
962
|
-
private func
|
|
963
|
-
|
|
974
|
+
private func tryDeleteDirectory(_ url: URL) {
|
|
975
|
+
guard FileManager.default.fileExists(atPath: url.path) else {
|
|
976
|
+
return
|
|
977
|
+
}
|
|
978
|
+
do {
|
|
979
|
+
try FileManager.default.removeItem(at: url)
|
|
980
|
+
} catch {
|
|
981
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "Failed to delete directory: \(url.path)")
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
private func tryDeleteDownloadsDirectory() {
|
|
986
|
+
tryDeleteDirectory(buildDownloadsDirectoryUrl())
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
private func unzipDownloadedBundle(zipFile: URL) throws -> URL {
|
|
990
|
+
let destinationDirectory = zipFile.deletingLastPathComponent().appendingPathComponent("bundle")
|
|
964
991
|
try FileManager.default.createDirectory(at: destinationDirectory, withIntermediateDirectories: true, attributes: nil)
|
|
965
992
|
try FileManager.default.unzipItem(at: zipFile, to: destinationDirectory)
|
|
966
993
|
return destinationDirectory
|
|
@@ -27,13 +27,16 @@ public class LiveUpdateHttpClient: NSObject {
|
|
|
27
27
|
|
|
28
28
|
public func download(url: URL, destination: @escaping DownloadRequest.Destination, callback: ((Progress) -> Void)?) async throws -> AFDownloadResponse<Data> {
|
|
29
29
|
var request = URLRequest(url: url)
|
|
30
|
+
// Ignore the URL cache so that a cached response is never replayed for a deterministic request URL
|
|
31
|
+
request.cachePolicy = .reloadIgnoringLocalCacheData
|
|
30
32
|
request.httpMethod = HTTPMethod.get.rawValue
|
|
31
33
|
request.timeoutInterval = Double(config.httpTimeout) / 1000.0
|
|
32
34
|
if let deviceId = deviceId, !deviceId.isEmpty {
|
|
33
35
|
request.setValue(deviceId, forHTTPHeaderField: "X-Device-Id")
|
|
34
36
|
}
|
|
35
37
|
return try await withCheckedThrowingContinuation { continuation in
|
|
36
|
-
|
|
38
|
+
// `validate()` treats non-2xx responses as errors so that an error body is never saved as a bundle file
|
|
39
|
+
AF.download(request, to: destination).validate().downloadProgress { progress in
|
|
37
40
|
if let callback = callback {
|
|
38
41
|
callback(progress)
|
|
39
42
|
}
|
|
@@ -45,6 +48,8 @@ public class LiveUpdateHttpClient: NSObject {
|
|
|
45
48
|
|
|
46
49
|
public func request<T: Decodable>(url: URL, type: T.Type) async throws -> AFDataResponse<T> {
|
|
47
50
|
var request = URLRequest(url: url)
|
|
51
|
+
// Ignore the URL cache so that a cached response is never replayed for a deterministic request URL
|
|
52
|
+
request.cachePolicy = .reloadIgnoringLocalCacheData
|
|
48
53
|
request.httpMethod = HTTPMethod.get.rawValue
|
|
49
54
|
request.timeoutInterval = Double(config.httpTimeout) / 1000.0
|
|
50
55
|
if let deviceId = deviceId, !deviceId.isEmpty {
|
|
@@ -8,7 +8,7 @@ import Capacitor
|
|
|
8
8
|
@objc(LiveUpdatePlugin)
|
|
9
9
|
public class LiveUpdatePlugin: CAPPlugin, CAPBridgedPlugin {
|
|
10
10
|
public static let tag = "LiveUpdate"
|
|
11
|
-
public static let version = "7.5.
|
|
11
|
+
public static let version = "7.5.2"
|
|
12
12
|
public static let userDefaultsPrefix = "CapawesomeLiveUpdate" // DO NOT CHANGE
|
|
13
13
|
|
|
14
14
|
public let identifier = "LiveUpdatePlugin"
|