@hot-updater/react-native 1.0.0-rc.4 → 1.0.0-rc.40
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/build.gradle +13 -2
- package/android/proguard-rules.pro +8 -2
- package/android/src/bridge/BridgeReactInstance.kt +38 -0
- package/android/src/bridgeless/BridgeReactInstance.kt +24 -0
- package/android/src/main/java/com/hotupdater/ActivityStartGate.kt +94 -0
- package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +1064 -844
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +50 -11
- package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +287 -22
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +46 -30
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +75 -192
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryState.kt +64 -0
- package/android/src/main/java/com/hotupdater/InstallIdentityService.kt +37 -0
- package/android/src/main/java/com/hotupdater/KeyValueStorageService.kt +86 -0
- package/android/src/main/java/com/hotupdater/NetworkState.kt +31 -0
- package/android/src/main/java/com/hotupdater/NoBackupStorage.kt +17 -0
- package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +127 -50
- package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +34 -0
- package/android/src/main/java/com/hotupdater/TarArchiveInputStream.kt +214 -375
- package/android/src/main/java/com/hotupdater/TarBrArchiveExtractor.kt +119 -0
- package/android/src/newarch/HotUpdater.kt +7 -9
- package/android/src/newarch/HotUpdaterModule.kt +109 -84
- package/android/src/newarch/JavaScriptExceptionHooks.kt +48 -0
- package/android/src/newarch/ReactIntegrationManager.kt +6 -32
- package/android/src/oldarch/HotUpdater.kt +7 -9
- package/android/src/oldarch/HotUpdaterModule.kt +98 -74
- package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
- package/android/src/oldarch/JavaScriptExceptionHooks.kt +71 -0
- package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
- package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +1032 -1116
- package/ios/HotUpdater/Internal/BundleMetadata.swift +61 -54
- package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
- package/ios/HotUpdater/Internal/FileUtilities.swift +64 -0
- package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +0 -1
- package/ios/HotUpdater/Internal/HotUpdater.mm +32 -67
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +229 -73
- package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
- package/ios/HotUpdater/Internal/NotificationExtension.swift +0 -2
- package/ios/HotUpdater/Internal/TarArchiveExtractor.swift +182 -311
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +119 -71
- package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecovery.h +16 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecovery.mm +83 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecoveryHooks.mm +49 -0
- package/lib/commonjs/appReady.js +102 -0
- package/lib/commonjs/appReady.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +120 -68
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/clientPlugin.js +13 -0
- package/lib/commonjs/clientPlugin.js.map +1 -0
- package/lib/commonjs/error.js +4 -13
- package/lib/commonjs/error.js.map +1 -1
- package/lib/commonjs/fetchJSON.js +16 -27
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/fetchUpdateResponse.js +60 -0
- package/lib/commonjs/fetchUpdateResponse.js.map +1 -0
- package/lib/commonjs/httpClient.js +63 -94
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/index.js +71 -18
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js +74 -60
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/pluginHost.js +45 -0
- package/lib/commonjs/pluginHost.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +36 -87
- package/lib/commonjs/releaseCatalogCache.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/sdkVersion.js.map +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/store.js +3 -10
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/updateError.js +145 -0
- package/lib/commonjs/updateError.js.map +1 -0
- package/lib/commonjs/wrap.js +43 -26
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/module/appReady.js +95 -0
- package/lib/module/appReady.js.map +1 -0
- package/lib/module/checkForUpdate.js +113 -63
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/clientPlugin.js +4 -0
- package/lib/module/clientPlugin.js.map +1 -0
- package/lib/module/error.js +4 -13
- package/lib/module/error.js.map +1 -1
- package/lib/module/fetchJSON.js +14 -26
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/fetchUpdateResponse.js +55 -0
- package/lib/module/fetchUpdateResponse.js.map +1 -0
- package/lib/module/httpClient.js +62 -93
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/index.js +58 -20
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js +67 -53
- package/lib/module/native.js.map +1 -1
- package/lib/module/pluginHost.js +36 -0
- package/lib/module/pluginHost.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +32 -82
- package/lib/module/releaseCatalogCache.js.map +1 -1
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/sdkVersion.js.map +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/store.js +3 -10
- package/lib/module/store.js.map +1 -1
- package/lib/module/updateError.js +139 -0
- package/lib/module/updateError.js.map +1 -0
- package/lib/module/wrap.js +43 -26
- package/lib/module/wrap.js.map +1 -1
- package/lib/typescript/commonjs/appReady.d.ts +21 -0
- package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +16 -4
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/clientPlugin.d.ts +2 -0
- package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/commonjs/error.d.ts +4 -13
- package/lib/typescript/commonjs/error.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchJSON.d.ts +5 -5
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchUpdateResponse.d.ts +14 -0
- package/lib/typescript/commonjs/fetchUpdateResponse.d.ts.map +1 -0
- package/lib/typescript/commonjs/httpClient.d.ts +4 -33
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +4 -8
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +29 -22
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/pluginHost.d.ts +4 -0
- package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts +8 -14
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +35 -47
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/store.d.ts +1 -3
- package/lib/typescript/commonjs/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +1 -1
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/updateError.d.ts +26 -0
- package/lib/typescript/commonjs/updateError.d.ts.map +1 -0
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +6 -7
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/appReady.d.ts +21 -0
- package/lib/typescript/module/appReady.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +16 -4
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/clientPlugin.d.ts +2 -0
- package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/module/error.d.ts +4 -13
- package/lib/typescript/module/error.d.ts.map +1 -1
- package/lib/typescript/module/fetchJSON.d.ts +5 -5
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/fetchUpdateResponse.d.ts +14 -0
- package/lib/typescript/module/fetchUpdateResponse.d.ts.map +1 -0
- package/lib/typescript/module/httpClient.d.ts +4 -33
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +4 -8
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +29 -22
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/pluginHost.d.ts +4 -0
- package/lib/typescript/module/pluginHost.d.ts.map +1 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts +8 -14
- package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +35 -47
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/store.d.ts +1 -3
- package/lib/typescript/module/store.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +1 -1
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/updateError.d.ts +26 -0
- package/lib/typescript/module/updateError.d.ts.map +1 -0
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +6 -7
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +7 -4
- package/src/appReady.ts +141 -0
- package/src/checkForUpdate.ts +145 -86
- package/src/clientPlugin.ts +18 -0
- package/src/error.ts +4 -14
- package/src/fetchJSON.ts +14 -30
- package/src/fetchUpdateResponse.ts +60 -0
- package/src/httpClient.ts +88 -159
- package/src/index.ts +90 -24
- package/src/native.ts +98 -102
- package/src/pluginHost.ts +47 -0
- package/src/releaseCatalogCache.ts +43 -172
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +34 -48
- package/src/store.ts +2 -23
- package/src/types.ts +1 -1
- package/src/updateError.ts +167 -0
- package/src/wrap.tsx +57 -26
- package/src/wrap.types.ts +6 -7
- package/android/src/main/java/com/hotupdater/DecompressService.kt +0 -89
- package/android/src/main/java/com/hotupdater/DecompressionStrategy.kt +0 -26
- package/android/src/main/java/com/hotupdater/TarBrDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/TarGzDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/ZipDecompressionStrategy.kt +0 -192
- package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +0 -46
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +0 -799
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +0 -273
- package/android/src/test/java/com/hotupdater/NativeConfigUtilsTest.kt +0 -20
- package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +0 -111
- package/android/src/test/java/com/hotupdater/RelativePathResolverTest.kt +0 -41
- package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +0 -118
- package/android/src/test/java/com/hotupdater/TarArchiveInputStreamTest.kt +0 -68
- package/ios/HotUpdater/Internal/ArchiveExtractionUtilities.swift +0 -178
- package/ios/HotUpdater/Internal/DecompressService.swift +0 -112
- package/ios/HotUpdater/Internal/DecompressionStrategy.swift +0 -22
- package/ios/HotUpdater/Internal/StreamingTarArchiveExtractor.swift +0 -370
- package/ios/HotUpdater/Internal/TarBrDecompressionStrategy.swift +0 -39
- package/ios/HotUpdater/Internal/TarGzDecompressionStrategy.swift +0 -59
- package/ios/HotUpdater/Internal/ZipArchiveExtractor.swift +0 -482
- package/ios/HotUpdater/Internal/ZipDecompressionStrategy.swift +0 -56
- package/lib/commonjs/catalogCacheNative.spec.js +0 -31
- package/lib/commonjs/catalogCacheNative.spec.js.map +0 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +0 -616
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +0 -1
- package/lib/commonjs/httpClient.spec.js +0 -102
- package/lib/commonjs/httpClient.spec.js.map +0 -1
- package/lib/commonjs/index.spec.js +0 -302
- package/lib/commonjs/index.spec.js.map +0 -1
- package/lib/commonjs/iosInterop.spec.js +0 -18
- package/lib/commonjs/iosInterop.spec.js.map +0 -1
- package/lib/commonjs/native.spec.js +0 -883
- package/lib/commonjs/native.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -218
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.js +0 -133
- package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -246
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js +0 -24
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -117
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/commonjs/releaseCatalogCache.spec.js +0 -195
- package/lib/commonjs/releaseCatalogCache.spec.js.map +0 -1
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +0 -64
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +0 -1
- package/lib/commonjs/store.notification.spec.js +0 -76
- package/lib/commonjs/store.notification.spec.js.map +0 -1
- package/lib/commonjs/store.spec.js +0 -316
- package/lib/commonjs/store.spec.js.map +0 -1
- package/lib/commonjs/wrap.spec.js +0 -329
- package/lib/commonjs/wrap.spec.js.map +0 -1
- package/lib/module/catalogCacheNative.spec.js +0 -31
- package/lib/module/catalogCacheNative.spec.js.map +0 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +0 -615
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +0 -1
- package/lib/module/httpClient.spec.js +0 -102
- package/lib/module/httpClient.spec.js.map +0 -1
- package/lib/module/index.spec.js +0 -301
- package/lib/module/index.spec.js.map +0 -1
- package/lib/module/iosInterop.spec.js +0 -18
- package/lib/module/iosInterop.spec.js.map +0 -1
- package/lib/module/native.spec.js +0 -882
- package/lib/module/native.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -217
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.js +0 -128
- package/lib/module/notifyAppReadyInsights.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.spec.js +0 -245
- package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.test-utils.js +0 -18
- package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -116
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/module/releaseCatalogCache.spec.js +0 -195
- package/lib/module/releaseCatalogCache.spec.js.map +0 -1
- package/lib/module/releaseCatalogCacheNativeContract.spec.js +0 -64
- package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +0 -1
- package/lib/module/store.notification.spec.js +0 -77
- package/lib/module/store.notification.spec.js.map +0 -1
- package/lib/module/store.spec.js +0 -315
- package/lib/module/store.spec.js.map +0 -1
- package/lib/module/wrap.spec.js +0 -330
- package/lib/module/wrap.spec.js.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -13
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts +0 -13
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/src/catalogCacheNative.spec.ts +0 -63
- package/src/checkForUpdate.releaseCatalog.spec.ts +0 -612
- package/src/httpClient.spec.ts +0 -132
- package/src/index.spec.ts +0 -337
- package/src/iosInterop.spec.ts +0 -30
- package/src/native.spec.ts +0 -945
- package/src/notifyAppReadyInsights.boundary.spec.ts +0 -234
- package/src/notifyAppReadyInsights.spec.ts +0 -243
- package/src/notifyAppReadyInsights.test-utils.ts +0 -31
- package/src/notifyAppReadyInsights.transport.spec.ts +0 -130
- package/src/notifyAppReadyInsights.ts +0 -194
- package/src/releaseCatalogCache.spec.ts +0 -282
- package/src/releaseCatalogCacheNativeContract.spec.ts +0 -80
- package/src/store.notification.spec.ts +0 -92
- package/src/store.spec.ts +0 -372
- package/src/wrap.spec.ts +0 -406
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import com.hotupdater.vendor.brotli.dec.BrotliInputStream
|
|
4
|
+
import java.io.File
|
|
5
|
+
import java.io.FileInputStream
|
|
6
|
+
import java.io.IOException
|
|
7
|
+
import java.io.InputStream
|
|
8
|
+
|
|
9
|
+
internal object TarBrArchiveExtractor {
|
|
10
|
+
fun extract(
|
|
11
|
+
archiveFile: File,
|
|
12
|
+
destination: File,
|
|
13
|
+
expectedTarByteSize: Long,
|
|
14
|
+
expectedFiles: Map<String, Long>,
|
|
15
|
+
) {
|
|
16
|
+
require(expectedTarByteSize >= 0) { "Invalid TAR byte size" }
|
|
17
|
+
if (destination.exists() && !destination.deleteRecursively()) {
|
|
18
|
+
throw IOException("Cannot clear archive extraction directory")
|
|
19
|
+
}
|
|
20
|
+
if (!destination.mkdirs()) throw IOException("Cannot create archive extraction directory")
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
FileInputStream(archiveFile).use { compressedInput ->
|
|
24
|
+
BrotliInputStream(compressedInput).use { brotliInput ->
|
|
25
|
+
val boundedInput = ExactSizeInputStream(brotliInput, expectedTarByteSize)
|
|
26
|
+
TarArchiveInputStream(boundedInput).use { tarInput ->
|
|
27
|
+
val extractedPaths = linkedSetOf<String>()
|
|
28
|
+
var entry = tarInput.getNextEntry()
|
|
29
|
+
while (entry != null) {
|
|
30
|
+
if (!entry.isRegularFile) {
|
|
31
|
+
throw IOException("Unsupported TAR entry type for ${entry.name}")
|
|
32
|
+
}
|
|
33
|
+
val normalizedPath = RelativePathResolver.normalizeRelativePath(entry.name)
|
|
34
|
+
if (normalizedPath == null || normalizedPath != entry.name) {
|
|
35
|
+
throw IOException("Unsafe TAR entry path: ${entry.name}")
|
|
36
|
+
}
|
|
37
|
+
val expectedSize =
|
|
38
|
+
expectedFiles[normalizedPath]
|
|
39
|
+
?: throw IOException("Unexpected TAR entry: $normalizedPath")
|
|
40
|
+
if (!extractedPaths.add(normalizedPath)) {
|
|
41
|
+
throw IOException("Duplicate TAR entry: $normalizedPath")
|
|
42
|
+
}
|
|
43
|
+
if (entry.size != expectedSize) {
|
|
44
|
+
throw IOException("TAR entry size mismatch: $normalizedPath")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
val outputFile =
|
|
48
|
+
RelativePathResolver.resolveInside(destination, normalizedPath)
|
|
49
|
+
?: throw IOException("Unsafe TAR entry path: $normalizedPath")
|
|
50
|
+
if (outputFile.exists()) throw IOException("TAR output already exists: $normalizedPath")
|
|
51
|
+
val parentDirectory = outputFile.parentFile
|
|
52
|
+
if (parentDirectory != null && !parentDirectory.isDirectory && !parentDirectory.mkdirs()) {
|
|
53
|
+
throw IOException("Cannot create TAR output directory: $normalizedPath")
|
|
54
|
+
}
|
|
55
|
+
outputFile.outputStream().use { output ->
|
|
56
|
+
val buffer = ByteArray(8192)
|
|
57
|
+
var written = 0L
|
|
58
|
+
while (true) {
|
|
59
|
+
val count = tarInput.read(buffer)
|
|
60
|
+
if (count < 0) break
|
|
61
|
+
output.write(buffer, 0, count)
|
|
62
|
+
written += count
|
|
63
|
+
}
|
|
64
|
+
if (written != expectedSize) {
|
|
65
|
+
throw IOException("TAR entry was truncated: $normalizedPath")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
entry = tarInput.getNextEntry()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (extractedPaths != expectedFiles.keys) {
|
|
72
|
+
throw IOException("TAR file set does not match manifest")
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
boundedInput.requireExactSize()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch (error: Throwable) {
|
|
79
|
+
destination.deleteRecursively()
|
|
80
|
+
throw error
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private class ExactSizeInputStream(
|
|
85
|
+
private val input: InputStream,
|
|
86
|
+
private val expectedSize: Long,
|
|
87
|
+
) : InputStream() {
|
|
88
|
+
private var byteCount = 0L
|
|
89
|
+
|
|
90
|
+
override fun read(): Int {
|
|
91
|
+
val result = input.read()
|
|
92
|
+
if (result >= 0) recordRead(1)
|
|
93
|
+
return result
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
override fun read(
|
|
97
|
+
buffer: ByteArray,
|
|
98
|
+
offset: Int,
|
|
99
|
+
length: Int,
|
|
100
|
+
): Int {
|
|
101
|
+
val count = input.read(buffer, offset, length)
|
|
102
|
+
if (count > 0) recordRead(count.toLong())
|
|
103
|
+
return count
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fun requireExactSize() {
|
|
107
|
+
if (byteCount != expectedSize) {
|
|
108
|
+
throw IOException("TAR stream size mismatch: expected $expectedSize, got $byteCount")
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fun recordRead(count: Long) {
|
|
113
|
+
if (byteCount > expectedSize - count) {
|
|
114
|
+
throw IOException("TAR stream exceeds declared size")
|
|
115
|
+
}
|
|
116
|
+
byteCount += count
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -36,7 +36,7 @@ class HotUpdater {
|
|
|
36
36
|
* Updates the bundle using the default singleton instance
|
|
37
37
|
* @param context Application context
|
|
38
38
|
* @param bundleId ID of the bundle to update
|
|
39
|
-
* @param
|
|
39
|
+
* @param params Manifest and asset descriptors for the target bundle
|
|
40
40
|
* @param fileHash Combined hash string for verification (sig:<signature> or <hex_hash>)
|
|
41
41
|
* @param progressCallback Callback for download progress updates
|
|
42
42
|
* @throws HotUpdaterException if the update fails
|
|
@@ -44,22 +44,20 @@ class HotUpdater {
|
|
|
44
44
|
suspend fun updateBundle(
|
|
45
45
|
context: Context,
|
|
46
46
|
bundleId: String,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
manifestFileHash: String?,
|
|
51
|
-
changedAssets: Map<String, ChangedAssetDescriptor>?,
|
|
47
|
+
manifestUrl: String,
|
|
48
|
+
manifestFileHash: String,
|
|
49
|
+
assets: Map<String, ChangedAssetDescriptor>,
|
|
52
50
|
channel: String?,
|
|
51
|
+
archiveUrl: String? = null,
|
|
53
52
|
progressCallback: (UpdateProgressPayload) -> Unit,
|
|
54
53
|
) {
|
|
55
54
|
getInstance(context).updateBundle(
|
|
56
55
|
bundleId,
|
|
57
|
-
fileUrl,
|
|
58
|
-
fileHash,
|
|
59
56
|
manifestUrl,
|
|
60
57
|
manifestFileHash,
|
|
61
|
-
|
|
58
|
+
assets,
|
|
62
59
|
channel,
|
|
60
|
+
archiveUrl = archiveUrl,
|
|
63
61
|
progressCallback = progressCallback,
|
|
64
62
|
)
|
|
65
63
|
}
|
|
@@ -26,6 +26,16 @@ class HotUpdaterModule internal constructor(
|
|
|
26
26
|
|
|
27
27
|
override fun getName(): String = NAME
|
|
28
28
|
|
|
29
|
+
private fun readSafeInteger(
|
|
30
|
+
map: ReadableMap,
|
|
31
|
+
key: String,
|
|
32
|
+
): Long? {
|
|
33
|
+
if (!map.hasKey(key) || map.isNull(key)) return null
|
|
34
|
+
val value = runCatching { map.getDouble(key) }.getOrNull() ?: return null
|
|
35
|
+
if (!value.isFinite() || value % 1.0 != 0.0) return null
|
|
36
|
+
return value.toLong().takeIf { it in 0..9_007_199_254_740_991L }
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
override fun invalidate() {
|
|
30
40
|
super.invalidate()
|
|
31
41
|
// Cancel all ongoing coroutines when module is destroyed
|
|
@@ -37,12 +47,12 @@ class HotUpdaterModule internal constructor(
|
|
|
37
47
|
*/
|
|
38
48
|
private fun getInstance(): HotUpdaterImpl = HotUpdater.getInstance(mReactApplicationContext)
|
|
39
49
|
|
|
40
|
-
private fun
|
|
41
|
-
if (!params.hasKey("
|
|
50
|
+
private fun parseAssets(params: ReadableMap): Map<String, ChangedAssetDescriptor>? {
|
|
51
|
+
if (!params.hasKey("assets") || params.isNull("assets")) {
|
|
42
52
|
return null
|
|
43
53
|
}
|
|
44
54
|
|
|
45
|
-
val changedAssetsMap = params.getMap("
|
|
55
|
+
val changedAssetsMap = params.getMap("assets") ?: return null
|
|
46
56
|
val parsedAssets = linkedMapOf<String, ChangedAssetDescriptor>()
|
|
47
57
|
val iterator = changedAssetsMap.keySetIterator()
|
|
48
58
|
|
|
@@ -58,6 +68,7 @@ class HotUpdaterModule internal constructor(
|
|
|
58
68
|
val baseFileHash = patchMap.getString("baseFileHash")
|
|
59
69
|
val patchFileHash = patchMap.getString("patchFileHash")
|
|
60
70
|
val patchUrl = patchMap.getString("patchUrl")
|
|
71
|
+
val byteSize = readSafeInteger(patchMap, "byteSize")
|
|
61
72
|
|
|
62
73
|
if (
|
|
63
74
|
algorithm != null &&
|
|
@@ -72,6 +83,7 @@ class HotUpdaterModule internal constructor(
|
|
|
72
83
|
baseFileHash = baseFileHash,
|
|
73
84
|
patchFileHash = patchFileHash,
|
|
74
85
|
patchUrl = patchUrl,
|
|
86
|
+
byteSize = byteSize,
|
|
75
87
|
)
|
|
76
88
|
} else {
|
|
77
89
|
null
|
|
@@ -162,97 +174,112 @@ class HotUpdaterModule internal constructor(
|
|
|
162
174
|
try {
|
|
163
175
|
val bundleId = params.getString("bundleId")
|
|
164
176
|
if (bundleId == null || bundleId.isEmpty()) {
|
|
165
|
-
promise.
|
|
177
|
+
promise.rejectUpdateBundle(HotUpdaterException.missingBundleId())
|
|
166
178
|
return@launch
|
|
167
179
|
}
|
|
168
180
|
|
|
169
|
-
val
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (
|
|
181
|
+
val manifestUrl = params.getString("manifestUrl")
|
|
182
|
+
val manifestFileHash = params.getString("manifestFileHash")
|
|
183
|
+
val assets = parseAssets(params)
|
|
184
|
+
if (manifestUrl.isNullOrEmpty() || manifestFileHash.isNullOrEmpty() || assets == null) {
|
|
185
|
+
promise.rejectUpdateBundle(HotUpdaterException.invalidManifestParams())
|
|
186
|
+
return@launch
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
java.net.URL(manifestUrl)
|
|
190
|
+
} catch (e: java.net.MalformedURLException) {
|
|
191
|
+
promise.rejectUpdateBundle(
|
|
192
|
+
HotUpdaterException.invalidFileUrl("manifestUrl", manifestUrl, UpdateFailureResource.MANIFEST),
|
|
193
|
+
)
|
|
194
|
+
return@launch
|
|
195
|
+
}
|
|
196
|
+
val channel = params.getString("channel")
|
|
197
|
+
val archiveUrl =
|
|
198
|
+
if (params.hasKey("archiveUrl") && !params.isNull("archiveUrl")) {
|
|
199
|
+
params.getString("archiveUrl")
|
|
200
|
+
} else {
|
|
201
|
+
null
|
|
202
|
+
}
|
|
203
|
+
if (archiveUrl != null) {
|
|
173
204
|
try {
|
|
174
|
-
java.net.URL(
|
|
205
|
+
java.net.URL(archiveUrl)
|
|
175
206
|
} catch (e: java.net.MalformedURLException) {
|
|
176
|
-
promise.
|
|
207
|
+
promise.rejectUpdateBundle(
|
|
208
|
+
HotUpdaterException.invalidFileUrl("archiveUrl", archiveUrl, UpdateFailureResource.ARCHIVE),
|
|
209
|
+
)
|
|
177
210
|
return@launch
|
|
178
211
|
}
|
|
179
212
|
}
|
|
180
|
-
|
|
181
|
-
val fileHash = params.getString("fileHash")
|
|
182
|
-
val manifestUrl = params.getString("manifestUrl")
|
|
183
|
-
val manifestFileHash = params.getString("manifestFileHash")
|
|
184
|
-
val changedAssets = parseChangedAssets(params)
|
|
185
|
-
val channel = params.getString("channel")
|
|
186
213
|
val selection = parseSelection(params)
|
|
187
214
|
|
|
188
215
|
val impl = getInstance()
|
|
189
216
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
)
|
|
217
|
+
val result =
|
|
218
|
+
impl.updateBundle(
|
|
219
|
+
bundleId,
|
|
220
|
+
manifestUrl,
|
|
221
|
+
manifestFileHash,
|
|
222
|
+
assets,
|
|
223
|
+
channel,
|
|
224
|
+
selection,
|
|
225
|
+
archiveUrl,
|
|
226
|
+
) { progress ->
|
|
227
|
+
// Post to Main thread for React Native event emission
|
|
228
|
+
Handler(Looper.getMainLooper()).post {
|
|
229
|
+
try {
|
|
230
|
+
val progressParams =
|
|
231
|
+
WritableNativeMap().apply {
|
|
232
|
+
putDouble("progress", progress.progress)
|
|
233
|
+
putString("artifactType", progress.artifactType)
|
|
234
|
+
progress.details?.let { details ->
|
|
235
|
+
putMap(
|
|
236
|
+
"details",
|
|
237
|
+
WritableNativeMap().apply {
|
|
238
|
+
putInt("totalFilesCount", details.totalFilesCount)
|
|
239
|
+
putInt("completedFilesCount", details.completedFilesCount)
|
|
240
|
+
putArray(
|
|
241
|
+
"files",
|
|
242
|
+
WritableNativeArray().apply {
|
|
243
|
+
details.files.forEach { file ->
|
|
244
|
+
pushMap(
|
|
245
|
+
WritableNativeMap().apply {
|
|
246
|
+
putString("path", file.path)
|
|
247
|
+
putString("downloadPath", file.downloadPath)
|
|
248
|
+
putString("status", file.status)
|
|
249
|
+
putDouble("progress", file.progress)
|
|
250
|
+
putInt("order", file.order)
|
|
251
|
+
file.downloadedBytes?.let {
|
|
252
|
+
putDouble(
|
|
253
|
+
"downloadedBytes",
|
|
254
|
+
it.toDouble(),
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
file.totalBytes?.let { putDouble("totalBytes", it.toDouble()) }
|
|
258
|
+
},
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
)
|
|
263
|
+
},
|
|
264
|
+
)
|
|
265
|
+
}
|
|
240
266
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
267
|
+
|
|
268
|
+
this@HotUpdaterModule
|
|
269
|
+
.mReactApplicationContext
|
|
270
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
271
|
+
?.emit("onProgress", progressParams)
|
|
272
|
+
} catch (e: Exception) {
|
|
273
|
+
Log.w("HotUpdater", "Failed to emit progress (bridge may be unavailable): ${e.message}")
|
|
274
|
+
}
|
|
249
275
|
}
|
|
250
276
|
}
|
|
251
|
-
|
|
252
|
-
promise.resolve(true)
|
|
277
|
+
promise.resolve(result.toWritableMap())
|
|
253
278
|
} catch (e: HotUpdaterException) {
|
|
254
|
-
promise.
|
|
279
|
+
promise.rejectUpdateBundle(e)
|
|
255
280
|
} catch (e: Exception) {
|
|
281
|
+
// Not an update failure (a stale Release selection, for example),
|
|
282
|
+
// so the rejection carries no classification.
|
|
256
283
|
promise.reject("UNKNOWN_ERROR", e.message ?: "An unknown error occurred")
|
|
257
284
|
}
|
|
258
285
|
}
|
|
@@ -389,15 +416,13 @@ class HotUpdaterModule internal constructor(
|
|
|
389
416
|
|
|
390
417
|
override fun getInstallId(): String = getInstance().getInstallId()
|
|
391
418
|
|
|
392
|
-
override fun
|
|
393
|
-
|
|
394
|
-
override fun getUsername(): String? = getInstance().getUsername()
|
|
419
|
+
override fun getStorageItem(key: String): String? = getInstance().getStorageItem(key)
|
|
395
420
|
|
|
396
|
-
override fun
|
|
397
|
-
|
|
398
|
-
|
|
421
|
+
override fun setStorageItem(
|
|
422
|
+
key: String,
|
|
423
|
+
value: String?,
|
|
399
424
|
) {
|
|
400
|
-
getInstance().
|
|
425
|
+
getInstance().setStorageItem(key, value)
|
|
401
426
|
}
|
|
402
427
|
|
|
403
428
|
override fun resetChannel(promise: Promise) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactApplication
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Routes JavaScript errors of the running React instance to crash recovery.
|
|
7
|
+
* The New Architecture reaches the instance through ReactHost.
|
|
8
|
+
*/
|
|
9
|
+
internal object JavaScriptExceptionHooks {
|
|
10
|
+
private val patchedReactHostDelegateIds = mutableSetOf<Int>()
|
|
11
|
+
|
|
12
|
+
fun install(application: ReactApplication) {
|
|
13
|
+
val reactHost = application.reactHost ?: return
|
|
14
|
+
val reactHostDelegate =
|
|
15
|
+
HotUpdaterRecoveryManager.findField(reactHost.javaClass, "mReactHostDelegate")?.let { field ->
|
|
16
|
+
field.isAccessible = true
|
|
17
|
+
field.get(reactHost)
|
|
18
|
+
}
|
|
19
|
+
?: HotUpdaterRecoveryManager.findField(reactHost.javaClass, "reactHostDelegate")?.let { field ->
|
|
20
|
+
field.isAccessible = true
|
|
21
|
+
field.get(reactHost)
|
|
22
|
+
}
|
|
23
|
+
?: return
|
|
24
|
+
|
|
25
|
+
val delegateIdentity = System.identityHashCode(reactHostDelegate)
|
|
26
|
+
if (patchedReactHostDelegateIds.add(delegateIdentity)) {
|
|
27
|
+
val exceptionHandlerField =
|
|
28
|
+
HotUpdaterRecoveryManager.findField(reactHostDelegate.javaClass, "exceptionHandler")
|
|
29
|
+
if (exceptionHandlerField == null) {
|
|
30
|
+
patchedReactHostDelegateIds.remove(delegateIdentity)
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exceptionHandlerField.isAccessible = true
|
|
35
|
+
@Suppress("UNCHECKED_CAST")
|
|
36
|
+
val previousHandler =
|
|
37
|
+
exceptionHandlerField.get(reactHostDelegate) as? (Exception) -> Unit
|
|
38
|
+
|
|
39
|
+
exceptionHandlerField.set(reactHostDelegate) { exception: Exception ->
|
|
40
|
+
if (!HotUpdaterRecoveryManager.handleJavaScriptExceptionForRecovery(exception)) {
|
|
41
|
+
previousHandler?.invoke(exception) ?: throw exception
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
reactHost.currentReactContext?.let(HotUpdaterRecoveryManager::patchReactContextExceptionHandler)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -5,12 +5,10 @@ import android.util.Log
|
|
|
5
5
|
import com.facebook.react.ReactApplication
|
|
6
6
|
import com.facebook.react.ReactHost
|
|
7
7
|
import com.facebook.react.ReactInstanceEventListener
|
|
8
|
-
import com.facebook.react.bridge.JSBundleLoader
|
|
9
8
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
9
|
import com.facebook.react.bridge.ReactContext
|
|
11
10
|
import com.facebook.react.common.LifecycleState
|
|
12
11
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
13
|
-
import java.lang.reflect.Field
|
|
14
12
|
import kotlin.coroutines.resume
|
|
15
13
|
|
|
16
14
|
class ReactIntegrationManager(
|
|
@@ -89,7 +87,7 @@ class ReactIntegrationManager(
|
|
|
89
87
|
|
|
90
88
|
/**
|
|
91
89
|
* Sets the JS bundle.
|
|
92
|
-
* Priority: ReactHostHolder (if set) > application.reactHost >
|
|
90
|
+
* Priority: ReactHostHolder (if set) > application.reactHost > the bridge (React Native 0.81 and older)
|
|
93
91
|
* @param bundleURL The bundle URL to set
|
|
94
92
|
*/
|
|
95
93
|
public fun setJSBundle(bundleURL: String) {
|
|
@@ -115,19 +113,8 @@ class ReactIntegrationManager(
|
|
|
115
113
|
return
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
// 4.
|
|
119
|
-
|
|
120
|
-
val instanceManager = application.reactNativeHost.reactInstanceManager
|
|
121
|
-
val bundleLoader: JSBundleLoader? = this.getJSBundlerLoader(bundleURL)
|
|
122
|
-
val bundleLoaderField: Field =
|
|
123
|
-
instanceManager::class.java.getDeclaredField("mBundleLoader")
|
|
124
|
-
bundleLoaderField.isAccessible = true
|
|
125
|
-
|
|
126
|
-
if (bundleLoader != null) {
|
|
127
|
-
bundleLoaderField.set(instanceManager, bundleLoader)
|
|
128
|
-
} else {
|
|
129
|
-
bundleLoaderField.set(instanceManager, null)
|
|
130
|
-
}
|
|
116
|
+
// 4. Fall back to the bridge, which React Native 0.81 and older can run
|
|
117
|
+
BridgeReactInstance.setJSBundle(application, getJSBundlerLoader(bundleURL))
|
|
131
118
|
} catch (e: Exception) {
|
|
132
119
|
Log.d("HotUpdater", "Failed to setJSBundle: ${e.message}")
|
|
133
120
|
}
|
|
@@ -135,7 +122,7 @@ class ReactIntegrationManager(
|
|
|
135
122
|
|
|
136
123
|
/**
|
|
137
124
|
* Reload the React Native application.
|
|
138
|
-
* Priority: ReactHostHolder (if set) > application.reactHost >
|
|
125
|
+
* Priority: ReactHostHolder (if set) > application.reactHost > the bridge (React Native 0.81 and older)
|
|
139
126
|
*/
|
|
140
127
|
public suspend fun reload() {
|
|
141
128
|
try {
|
|
@@ -160,21 +147,8 @@ class ReactIntegrationManager(
|
|
|
160
147
|
return
|
|
161
148
|
}
|
|
162
149
|
|
|
163
|
-
// 4.
|
|
164
|
-
|
|
165
|
-
val reactNativeHost = application.reactNativeHost
|
|
166
|
-
try {
|
|
167
|
-
reactNativeHost.reactInstanceManager.recreateReactContextInBackground()
|
|
168
|
-
} catch (e: Exception) {
|
|
169
|
-
val currentActivity = reactNativeHost.reactInstanceManager.currentReactContext?.currentActivity
|
|
170
|
-
if (currentActivity == null) {
|
|
171
|
-
return
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
currentActivity.runOnUiThread {
|
|
175
|
-
currentActivity.recreate()
|
|
176
|
-
}
|
|
177
|
-
}
|
|
150
|
+
// 4. Fall back to the bridge, which React Native 0.81 and older can run
|
|
151
|
+
BridgeReactInstance.reload(application)
|
|
178
152
|
} catch (e: Exception) {
|
|
179
153
|
Log.d("HotUpdater", "Failed to reload: ${e.message}")
|
|
180
154
|
}
|
|
@@ -35,7 +35,7 @@ class HotUpdater {
|
|
|
35
35
|
* Updates the bundle using the default singleton instance
|
|
36
36
|
* @param context Application context
|
|
37
37
|
* @param bundleId ID of the bundle to update
|
|
38
|
-
* @param
|
|
38
|
+
* @param params Manifest and asset descriptors for the target bundle
|
|
39
39
|
* @param fileHash Combined hash string for verification (sig:<signature> or <hex_hash>)
|
|
40
40
|
* @param progressCallback Callback for download progress updates
|
|
41
41
|
* @throws HotUpdaterException if the update fails
|
|
@@ -43,22 +43,20 @@ class HotUpdater {
|
|
|
43
43
|
suspend fun updateBundle(
|
|
44
44
|
context: Context,
|
|
45
45
|
bundleId: String,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
manifestFileHash: String?,
|
|
50
|
-
changedAssets: Map<String, ChangedAssetDescriptor>?,
|
|
46
|
+
manifestUrl: String,
|
|
47
|
+
manifestFileHash: String,
|
|
48
|
+
assets: Map<String, ChangedAssetDescriptor>,
|
|
51
49
|
channel: String?,
|
|
50
|
+
archiveUrl: String? = null,
|
|
52
51
|
progressCallback: (UpdateProgressPayload) -> Unit,
|
|
53
52
|
) {
|
|
54
53
|
getInstance(context).updateBundle(
|
|
55
54
|
bundleId,
|
|
56
|
-
fileUrl,
|
|
57
|
-
fileHash,
|
|
58
55
|
manifestUrl,
|
|
59
56
|
manifestFileHash,
|
|
60
|
-
|
|
57
|
+
assets,
|
|
61
58
|
channel,
|
|
59
|
+
archiveUrl = archiveUrl,
|
|
62
60
|
progressCallback = progressCallback,
|
|
63
61
|
)
|
|
64
62
|
}
|