@capawesome/capacitor-live-update 7.3.0 → 7.4.0
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/README.md +216 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +519 -246
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdateHttpClient.java +33 -5
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +134 -3
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePreferences.java +25 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/api/GetLatestBundleResponse.java +2 -2
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/options/SetConfigOptions.java +19 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/GetBlockedBundlesResult.java +27 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/GetConfigResult.java +40 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/GetDownloadedBundlesResult.java +27 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/IsSyncingResult.java +26 -0
- package/dist/docs.json +319 -0
- package/dist/esm/definitions.d.ts +165 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +8 -1
- package/dist/esm/web.js +21 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +21 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +21 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/Classes/Options/SetConfigOptions.swift +14 -0
- package/ios/Plugin/Classes/Results/GetBlockedBundlesResult.swift +16 -0
- package/ios/Plugin/Classes/Results/GetConfigResult.swift +19 -0
- package/ios/Plugin/Classes/Results/GetDownloadedBundlesResult.swift +16 -0
- package/ios/Plugin/Classes/Results/IsSyncingResult.swift +16 -0
- package/ios/Plugin/LiveUpdate.swift +77 -4
- package/ios/Plugin/LiveUpdatePlugin.swift +78 -1
- package/ios/Plugin/LiveUpdatePreferences.swift +44 -2
- package/package.json +1 -1
|
@@ -22,18 +22,23 @@ import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.DeleteBundle
|
|
|
22
22
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.DownloadBundleOptions;
|
|
23
23
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.FetchLatestBundleOptions;
|
|
24
24
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.SetChannelOptions;
|
|
25
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.SetConfigOptions;
|
|
25
26
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.SetCustomIdOptions;
|
|
26
27
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.SetNextBundleOptions;
|
|
27
28
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.options.SyncOptions;
|
|
28
29
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.FetchLatestBundleResult;
|
|
30
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetBlockedBundlesResult;
|
|
29
31
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetBundlesResult;
|
|
30
32
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetChannelResult;
|
|
33
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetConfigResult;
|
|
31
34
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetCurrentBundleResult;
|
|
32
35
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetCustomIdResult;
|
|
33
36
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetDeviceIdResult;
|
|
37
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetDownloadedBundlesResult;
|
|
34
38
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetNextBundleResult;
|
|
35
39
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetVersionCodeResult;
|
|
36
40
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.GetVersionNameResult;
|
|
41
|
+
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.IsSyncingResult;
|
|
37
42
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.ReadyResult;
|
|
38
43
|
import io.capawesome.capacitorjs.plugins.liveupdate.classes.results.SyncResult;
|
|
39
44
|
import io.capawesome.capacitorjs.plugins.liveupdate.enums.ArtifactType;
|
|
@@ -55,8 +60,12 @@ import java.util.ArrayList;
|
|
|
55
60
|
import java.util.Arrays;
|
|
56
61
|
import java.util.List;
|
|
57
62
|
import java.util.UUID;
|
|
63
|
+
import java.util.concurrent.CountDownLatch;
|
|
64
|
+
import java.util.concurrent.atomic.AtomicBoolean;
|
|
65
|
+
import java.util.concurrent.atomic.AtomicLong;
|
|
58
66
|
import java.util.concurrent.atomic.AtomicReference;
|
|
59
67
|
import net.lingala.zip4j.ZipFile;
|
|
68
|
+
import okhttp3.Call;
|
|
60
69
|
import okhttp3.HttpUrl;
|
|
61
70
|
import okhttp3.Response;
|
|
62
71
|
import okhttp3.ResponseBody;
|
|
@@ -103,11 +112,18 @@ public class LiveUpdate {
|
|
|
103
112
|
this.preferences = new LiveUpdatePreferences(plugin.getContext());
|
|
104
113
|
this.webViewSettingsEditor = plugin.getContext().getSharedPreferences(WebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE).edit();
|
|
105
114
|
|
|
115
|
+
// Check version and reset config if version changed
|
|
116
|
+
checkAndResetConfigIfVersionChanged();
|
|
117
|
+
|
|
106
118
|
// Start the rollback timer to rollback to the default bundle
|
|
107
119
|
// if the app is not ready after a certain time
|
|
108
120
|
startRollbackTimer();
|
|
109
121
|
}
|
|
110
122
|
|
|
123
|
+
public void clearBlockedBundles() {
|
|
124
|
+
preferences.setBlockedBundleIds(null);
|
|
125
|
+
}
|
|
126
|
+
|
|
111
127
|
public void deleteBundle(@NonNull DeleteBundleOptions options, @NonNull EmptyCallback callback) {
|
|
112
128
|
String bundleId = options.getBundleId();
|
|
113
129
|
|
|
@@ -121,7 +137,7 @@ public class LiveUpdate {
|
|
|
121
137
|
callback.success();
|
|
122
138
|
}
|
|
123
139
|
|
|
124
|
-
public void downloadBundle(@NonNull DownloadBundleOptions options, @NonNull EmptyCallback callback)
|
|
140
|
+
public void downloadBundle(@NonNull DownloadBundleOptions options, @NonNull EmptyCallback callback) {
|
|
125
141
|
ArtifactType artifactType = options.getArtifactType();
|
|
126
142
|
String bundleId = options.getBundleId();
|
|
127
143
|
String checksum = options.getChecksum();
|
|
@@ -137,44 +153,80 @@ public class LiveUpdate {
|
|
|
137
153
|
|
|
138
154
|
// Download the bundle
|
|
139
155
|
if (artifactType == ArtifactType.MANIFEST) {
|
|
140
|
-
downloadBundleOfTypeManifest(bundleId, url);
|
|
156
|
+
downloadBundleOfTypeManifest(bundleId, url, callback);
|
|
141
157
|
} else {
|
|
142
|
-
downloadBundleOfTypeZip(bundleId, checksum, signature, url);
|
|
158
|
+
downloadBundleOfTypeZip(bundleId, checksum, signature, url, callback);
|
|
143
159
|
}
|
|
144
|
-
callback.success();
|
|
145
160
|
}
|
|
146
161
|
|
|
147
|
-
public void fetchLatestBundle(@NonNull FetchLatestBundleOptions options, @NonNull NonEmptyCallback callback)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
public void fetchLatestBundle(@NonNull FetchLatestBundleOptions options, @NonNull NonEmptyCallback<FetchLatestBundleResult> callback) {
|
|
163
|
+
fetchLatestBundleInternal(
|
|
164
|
+
options,
|
|
165
|
+
new NonEmptyCallback<GetLatestBundleResponse>() {
|
|
166
|
+
@Override
|
|
167
|
+
public void success(@Nullable GetLatestBundleResponse response) {
|
|
168
|
+
ArtifactType artifactType = response == null ? null : response.getArtifactType();
|
|
169
|
+
String bundleId = response == null ? null : response.getBundleId();
|
|
170
|
+
String checksum = response == null ? null : response.getChecksum();
|
|
171
|
+
JSONObject customProperties = response == null ? null : response.getCustomProperties();
|
|
172
|
+
String downloadUrl = response == null ? null : response.getUrl();
|
|
173
|
+
String signature = response == null ? null : response.getSignature();
|
|
174
|
+
FetchLatestBundleResult result = new FetchLatestBundleResult(
|
|
175
|
+
artifactType,
|
|
176
|
+
bundleId,
|
|
177
|
+
checksum,
|
|
178
|
+
customProperties,
|
|
179
|
+
downloadUrl,
|
|
180
|
+
signature
|
|
181
|
+
);
|
|
182
|
+
callback.success(result);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@Override
|
|
186
|
+
public void error(@NonNull Exception exception) {
|
|
187
|
+
callback.error(exception);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
162
190
|
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public void getBlockedBundles(@NonNull NonEmptyCallback<GetBlockedBundlesResult> callback) {
|
|
194
|
+
String blockedIds = preferences.getBlockedBundleIds();
|
|
195
|
+
String[] bundleIds;
|
|
196
|
+
if (blockedIds == null || blockedIds.isEmpty()) {
|
|
197
|
+
bundleIds = new String[0];
|
|
198
|
+
} else {
|
|
199
|
+
bundleIds = blockedIds.split(",");
|
|
200
|
+
}
|
|
201
|
+
GetBlockedBundlesResult result = new GetBlockedBundlesResult(bundleIds);
|
|
163
202
|
callback.success(result);
|
|
164
203
|
}
|
|
165
204
|
|
|
166
205
|
public void getBundles(@NonNull NonEmptyCallback callback) {
|
|
167
|
-
String[] bundleIds =
|
|
206
|
+
String[] bundleIds = getDownloadedBundleIds();
|
|
168
207
|
GetBundlesResult result = new GetBundlesResult(bundleIds);
|
|
169
208
|
callback.success(result);
|
|
170
209
|
}
|
|
171
210
|
|
|
211
|
+
public void getDownloadedBundles(@NonNull NonEmptyCallback<GetDownloadedBundlesResult> callback) {
|
|
212
|
+
String[] bundleIds = getDownloadedBundleIds();
|
|
213
|
+
GetDownloadedBundlesResult result = new GetDownloadedBundlesResult(bundleIds);
|
|
214
|
+
callback.success(result);
|
|
215
|
+
}
|
|
216
|
+
|
|
172
217
|
public void getChannel(@NonNull NonEmptyCallback callback) {
|
|
173
218
|
String channel = getChannel();
|
|
174
219
|
GetChannelResult result = new GetChannelResult(channel);
|
|
175
220
|
callback.success(result);
|
|
176
221
|
}
|
|
177
222
|
|
|
223
|
+
public void getConfig(@NonNull NonEmptyCallback<GetConfigResult> callback) {
|
|
224
|
+
String appId = getAppId();
|
|
225
|
+
String autoUpdateStrategy = config.getAutoUpdateStrategy();
|
|
226
|
+
GetConfigResult result = new GetConfigResult(appId, autoUpdateStrategy);
|
|
227
|
+
callback.success(result);
|
|
228
|
+
}
|
|
229
|
+
|
|
178
230
|
public void getCurrentBundle(@NonNull NonEmptyCallback<GetCurrentBundleResult> callback) {
|
|
179
231
|
String bundleId = getCurrentBundleId();
|
|
180
232
|
GetCurrentBundleResult result = new GetCurrentBundleResult(bundleId);
|
|
@@ -200,7 +252,7 @@ public class LiveUpdate {
|
|
|
200
252
|
}
|
|
201
253
|
|
|
202
254
|
public void getVersionCode(@NonNull NonEmptyCallback callback) throws PackageManager.NameNotFoundException {
|
|
203
|
-
String versionCode =
|
|
255
|
+
String versionCode = getVersionCodeAsString();
|
|
204
256
|
GetVersionCodeResult result = new GetVersionCodeResult(versionCode);
|
|
205
257
|
callback.success(result);
|
|
206
258
|
}
|
|
@@ -211,6 +263,11 @@ public class LiveUpdate {
|
|
|
211
263
|
callback.success(result);
|
|
212
264
|
}
|
|
213
265
|
|
|
266
|
+
public void isSyncing(@NonNull NonEmptyCallback<IsSyncingResult> callback) {
|
|
267
|
+
IsSyncingResult result = new IsSyncingResult(syncInProgress);
|
|
268
|
+
callback.success(result);
|
|
269
|
+
}
|
|
270
|
+
|
|
214
271
|
public void handleOnPageLoaded() {
|
|
215
272
|
// Wait for initial page load to perform auto update to make sure the WebViewLocalServer is initialized.
|
|
216
273
|
// Otherwise, a NullPointerException may occur for `com.getcapacitor.WebViewLocalServer.getBasePath()`.
|
|
@@ -263,6 +320,10 @@ public class LiveUpdate {
|
|
|
263
320
|
setNextBundleById(null);
|
|
264
321
|
}
|
|
265
322
|
|
|
323
|
+
public void resetConfig() {
|
|
324
|
+
preferences.setAppId(null);
|
|
325
|
+
}
|
|
326
|
+
|
|
266
327
|
public void setChannel(@NonNull SetChannelOptions options, @NonNull EmptyCallback callback) {
|
|
267
328
|
String channel = options.getChannel();
|
|
268
329
|
|
|
@@ -270,6 +331,11 @@ public class LiveUpdate {
|
|
|
270
331
|
callback.success();
|
|
271
332
|
}
|
|
272
333
|
|
|
334
|
+
public void setConfig(@NonNull SetConfigOptions options) {
|
|
335
|
+
String appId = options.getAppId();
|
|
336
|
+
preferences.setAppId(appId);
|
|
337
|
+
}
|
|
338
|
+
|
|
273
339
|
public void setCustomId(@NonNull SetCustomIdOptions options, @NonNull EmptyCallback callback) {
|
|
274
340
|
String customId = options.getCustomId();
|
|
275
341
|
|
|
@@ -294,7 +360,7 @@ public class LiveUpdate {
|
|
|
294
360
|
callback.success();
|
|
295
361
|
}
|
|
296
362
|
|
|
297
|
-
public void sync(@NonNull SyncOptions options, @NonNull NonEmptyCallback<Result> callback)
|
|
363
|
+
public void sync(@NonNull SyncOptions options, @NonNull NonEmptyCallback<Result> callback) {
|
|
298
364
|
if (syncInProgress) {
|
|
299
365
|
Exception exception = new Exception(LiveUpdatePlugin.ERROR_SYNC_IN_PROGRESS);
|
|
300
366
|
callback.error(exception);
|
|
@@ -302,55 +368,91 @@ public class LiveUpdate {
|
|
|
302
368
|
}
|
|
303
369
|
syncInProgress = true;
|
|
304
370
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
371
|
+
String channel = options.getChannel();
|
|
372
|
+
// Fetch the latest bundle
|
|
373
|
+
FetchLatestBundleOptions fetchLatestBundleOptions = new FetchLatestBundleOptions(channel);
|
|
374
|
+
fetchLatestBundleInternal(
|
|
375
|
+
fetchLatestBundleOptions,
|
|
376
|
+
new NonEmptyCallback<GetLatestBundleResponse>() {
|
|
377
|
+
@Override
|
|
378
|
+
public void success(@Nullable GetLatestBundleResponse response) {
|
|
379
|
+
try {
|
|
380
|
+
if (response == null) {
|
|
381
|
+
Logger.debug(LiveUpdatePlugin.TAG, "No update available.");
|
|
382
|
+
syncInProgress = false;
|
|
383
|
+
SyncResult syncResult = new SyncResult(null);
|
|
384
|
+
callback.success(syncResult);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
ArtifactType artifactType = response.getArtifactType();
|
|
388
|
+
String latestBundleId = response.getBundleId();
|
|
389
|
+
String checksum = response.getChecksum();
|
|
390
|
+
String signature = response.getSignature();
|
|
391
|
+
String url = response.getUrl();
|
|
392
|
+
// Check if the bundle is blocked
|
|
393
|
+
if (isBlockedBundleId(latestBundleId)) {
|
|
394
|
+
Logger.warn(LiveUpdatePlugin.TAG, "Bundle is blocked and will not be downloaded.");
|
|
395
|
+
syncInProgress = false;
|
|
396
|
+
SyncResult syncResult = new SyncResult(null);
|
|
397
|
+
callback.success(syncResult);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
// Check if the bundle already exists
|
|
401
|
+
if (hasBundleById(latestBundleId)) {
|
|
402
|
+
String nextBundleId = null;
|
|
403
|
+
String currentBundleId = getCurrentBundleId();
|
|
404
|
+
if (!latestBundleId.equals(currentBundleId)) {
|
|
405
|
+
// Set the next bundle
|
|
406
|
+
setNextBundleById(latestBundleId);
|
|
407
|
+
nextBundleId = latestBundleId;
|
|
408
|
+
}
|
|
409
|
+
syncInProgress = false;
|
|
410
|
+
SyncResult syncResult = new SyncResult(nextBundleId);
|
|
411
|
+
callback.success(syncResult);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Download the bundle
|
|
416
|
+
EmptyCallback downloadCallback = new EmptyCallback() {
|
|
417
|
+
@Override
|
|
418
|
+
public void success() {
|
|
419
|
+
try {
|
|
420
|
+
// Set the next bundle
|
|
421
|
+
setNextBundleById(latestBundleId);
|
|
422
|
+
syncInProgress = false;
|
|
423
|
+
SyncResult syncResult = new SyncResult(latestBundleId);
|
|
424
|
+
callback.success(syncResult);
|
|
425
|
+
} catch (Exception e) {
|
|
426
|
+
syncInProgress = false;
|
|
427
|
+
callback.error(e);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
@Override
|
|
432
|
+
public void error(@NonNull Exception exception) {
|
|
433
|
+
syncInProgress = false;
|
|
434
|
+
callback.error(exception);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
if (artifactType == ArtifactType.MANIFEST) {
|
|
439
|
+
downloadBundleOfTypeManifest(latestBundleId, url, downloadCallback);
|
|
440
|
+
} else {
|
|
441
|
+
downloadBundleOfTypeZip(latestBundleId, checksum, signature, url, downloadCallback);
|
|
442
|
+
}
|
|
443
|
+
} catch (Exception e) {
|
|
444
|
+
syncInProgress = false;
|
|
445
|
+
callback.error(e);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
@Override
|
|
450
|
+
public void error(@NonNull Exception exception) {
|
|
451
|
+
syncInProgress = false;
|
|
452
|
+
callback.error(exception);
|
|
336
453
|
}
|
|
337
|
-
SyncResult syncResult = new SyncResult(nextBundleId);
|
|
338
|
-
callback.success(syncResult);
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
// Download the bundle
|
|
342
|
-
if (artifactType == ArtifactType.MANIFEST) {
|
|
343
|
-
downloadBundleOfTypeManifest(latestBundleId, url);
|
|
344
|
-
} else {
|
|
345
|
-
downloadBundleOfTypeZip(latestBundleId, checksum, signature, url);
|
|
346
454
|
}
|
|
347
|
-
|
|
348
|
-
setNextBundleById(latestBundleId);
|
|
349
|
-
SyncResult syncResult = new SyncResult(latestBundleId);
|
|
350
|
-
callback.success(syncResult);
|
|
351
|
-
} finally {
|
|
352
|
-
syncInProgress = false;
|
|
353
|
-
}
|
|
455
|
+
);
|
|
354
456
|
}
|
|
355
457
|
|
|
356
458
|
private void addBundle(@NonNull String bundleId, @NonNull File sourceDirectory) throws Exception {
|
|
@@ -508,7 +610,7 @@ public class LiveUpdate {
|
|
|
508
610
|
}
|
|
509
611
|
|
|
510
612
|
private void deleteUnusedBundles() {
|
|
511
|
-
String[] bundleIds =
|
|
613
|
+
String[] bundleIds = getDownloadedBundleIds();
|
|
512
614
|
for (String bundleId : bundleIds) {
|
|
513
615
|
if (!isBundleInUse(bundleId)) {
|
|
514
616
|
deleteBundleById(bundleId);
|
|
@@ -516,202 +618,349 @@ public class LiveUpdate {
|
|
|
516
618
|
}
|
|
517
619
|
}
|
|
518
620
|
|
|
519
|
-
private
|
|
621
|
+
private Call downloadAndVerifyFile(
|
|
520
622
|
@NonNull String url,
|
|
521
623
|
@NonNull File file,
|
|
522
624
|
@Nullable String checksum,
|
|
523
625
|
@Nullable String signature,
|
|
524
|
-
@Nullable DownloadProgressCallback
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
626
|
+
@Nullable DownloadProgressCallback progressCallback,
|
|
627
|
+
@NonNull EmptyCallback completionCallback
|
|
628
|
+
) {
|
|
629
|
+
return httpClient.enqueue(
|
|
630
|
+
url,
|
|
631
|
+
new NonEmptyCallback<Response>() {
|
|
632
|
+
@Override
|
|
633
|
+
public void success(@NonNull Response response) {
|
|
634
|
+
try {
|
|
635
|
+
if (response.isSuccessful()) {
|
|
636
|
+
ResponseBody responseBody = response.body();
|
|
637
|
+
LiveUpdateHttpClient.writeResponseBodyToFile(responseBody, file, progressCallback);
|
|
638
|
+
|
|
639
|
+
// Extract checksum/signature from headers
|
|
640
|
+
String finalChecksum = checksum == null ? LiveUpdateHttpClient.getChecksumFromResponse(response) : checksum;
|
|
641
|
+
String finalSignature = signature == null ? LiveUpdateHttpClient.getSignatureFromResponse(response) : signature;
|
|
642
|
+
|
|
643
|
+
// Verify file
|
|
644
|
+
verifyFile(file, finalChecksum, finalSignature);
|
|
645
|
+
completionCallback.success();
|
|
646
|
+
} else {
|
|
647
|
+
String errorMessage = response.body().string();
|
|
648
|
+
Exception exception = new Exception(LiveUpdatePlugin.ERROR_DOWNLOAD_FAILED);
|
|
649
|
+
Logger.error(LiveUpdatePlugin.TAG, errorMessage, exception);
|
|
650
|
+
completionCallback.error(exception);
|
|
651
|
+
}
|
|
652
|
+
} catch (Exception e) {
|
|
653
|
+
completionCallback.error(e);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
@Override
|
|
658
|
+
public void error(@NonNull Exception exception) {
|
|
659
|
+
completionCallback.error(exception);
|
|
660
|
+
}
|
|
536
661
|
}
|
|
537
|
-
|
|
538
|
-
} else {
|
|
539
|
-
Exception exception = new Exception(responseBody.string());
|
|
540
|
-
Logger.error(LiveUpdatePlugin.TAG, exception.getMessage(), exception);
|
|
541
|
-
throw new Exception(LiveUpdatePlugin.ERROR_DOWNLOAD_FAILED);
|
|
542
|
-
}
|
|
662
|
+
);
|
|
543
663
|
}
|
|
544
664
|
|
|
545
|
-
private
|
|
665
|
+
private Call downloadBundleFile(
|
|
546
666
|
@NonNull String baseUrl,
|
|
547
667
|
@NonNull String href,
|
|
548
668
|
@NonNull File destinationDirectory,
|
|
549
|
-
@Nullable DownloadProgressCallback
|
|
550
|
-
|
|
669
|
+
@Nullable DownloadProgressCallback progressCallback,
|
|
670
|
+
@NonNull EmptyCallback completionCallback
|
|
671
|
+
) {
|
|
551
672
|
HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl).newBuilder();
|
|
552
673
|
urlBuilder.addQueryParameter("href", href);
|
|
553
674
|
String url = urlBuilder.build().toString();
|
|
554
675
|
|
|
555
676
|
File destinationFile = new File(destinationDirectory, href);
|
|
556
677
|
destinationFile.getParentFile().mkdirs();
|
|
557
|
-
downloadAndVerifyFile(url, destinationFile, null, null,
|
|
558
|
-
return destinationFile;
|
|
678
|
+
return downloadAndVerifyFile(url, destinationFile, null, null, progressCallback, completionCallback);
|
|
559
679
|
}
|
|
560
680
|
|
|
561
681
|
private void downloadBundleFiles(
|
|
562
682
|
@NonNull String baseUrl,
|
|
563
683
|
@NonNull List<ManifestItem> filesToDownload,
|
|
564
684
|
@NonNull File destinationDirectory,
|
|
565
|
-
@Nullable DownloadProgressCallback
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
685
|
+
@Nullable DownloadProgressCallback progressCallback,
|
|
686
|
+
@NonNull EmptyCallback completionCallback
|
|
687
|
+
) {
|
|
688
|
+
if (filesToDownload.isEmpty()) {
|
|
689
|
+
if (progressCallback != null) {
|
|
690
|
+
progressCallback.onProgress(0, 0);
|
|
691
|
+
}
|
|
692
|
+
completionCallback.success();
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Thread-safe progress tracking
|
|
697
|
+
AtomicLong totalBytesDownloaded = new AtomicLong(0);
|
|
569
698
|
long totalBytesToDownload = 0;
|
|
570
|
-
for (ManifestItem
|
|
571
|
-
totalBytesToDownload +=
|
|
699
|
+
for (ManifestItem item : filesToDownload) {
|
|
700
|
+
totalBytesToDownload += item.getSizeInBytes();
|
|
572
701
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
702
|
+
final long finalTotalBytesToDownload = totalBytesToDownload;
|
|
703
|
+
|
|
704
|
+
// Coordination primitives
|
|
705
|
+
CountDownLatch latch = new CountDownLatch(filesToDownload.size());
|
|
706
|
+
AtomicReference<Exception> firstError = new AtomicReference<>();
|
|
707
|
+
AtomicBoolean completionHandled = new AtomicBoolean(false);
|
|
708
|
+
List<Call> activeCalls = new ArrayList<>();
|
|
709
|
+
|
|
710
|
+
// Start all downloads asynchronously (OkHttp's dispatcher handles parallelization)
|
|
711
|
+
for (ManifestItem item : filesToDownload) {
|
|
712
|
+
Call call = downloadBundleFile(
|
|
713
|
+
baseUrl,
|
|
714
|
+
item.getHref(),
|
|
715
|
+
destinationDirectory,
|
|
716
|
+
(downloadedBytes, totalBytes) -> {
|
|
717
|
+
// Per-file progress
|
|
718
|
+
if (progressCallback != null) {
|
|
719
|
+
long totalProgress = totalBytesDownloaded.get() + downloadedBytes;
|
|
720
|
+
progressCallback.onProgress(totalProgress, finalTotalBytesToDownload);
|
|
584
721
|
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
722
|
+
},
|
|
723
|
+
new EmptyCallback() {
|
|
724
|
+
@Override
|
|
725
|
+
public void success() {
|
|
726
|
+
// Update total progress
|
|
727
|
+
totalBytesDownloaded.addAndGet(item.getSizeInBytes());
|
|
728
|
+
if (progressCallback != null) {
|
|
729
|
+
progressCallback.onProgress(totalBytesDownloaded.get(), finalTotalBytesToDownload);
|
|
730
|
+
}
|
|
731
|
+
latch.countDown();
|
|
732
|
+
|
|
733
|
+
// Check if this was the last download to complete
|
|
734
|
+
if (latch.getCount() == 0 && completionHandled.compareAndSet(false, true)) {
|
|
735
|
+
Exception error = firstError.get();
|
|
736
|
+
if (error != null) {
|
|
737
|
+
completionCallback.error(error);
|
|
738
|
+
} else {
|
|
739
|
+
// Final progress update
|
|
740
|
+
if (progressCallback != null) {
|
|
741
|
+
progressCallback.onProgress(finalTotalBytesToDownload, finalTotalBytesToDownload);
|
|
742
|
+
}
|
|
743
|
+
completionCallback.success();
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
@Override
|
|
749
|
+
public void error(@NonNull Exception e) {
|
|
750
|
+
// Capture first error and cancel all remaining downloads
|
|
751
|
+
if (firstError.compareAndSet(null, e)) {
|
|
752
|
+
Logger.error(LiveUpdatePlugin.TAG, "Failed to download file: " + item.getHref(), e);
|
|
753
|
+
// Cancel all in-flight downloads (fail-fast)
|
|
754
|
+
synchronized (activeCalls) {
|
|
755
|
+
for (Call activeCall : activeCalls) {
|
|
756
|
+
if (!activeCall.isCanceled() && !activeCall.isExecuted()) {
|
|
757
|
+
activeCall.cancel();
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
latch.countDown();
|
|
763
|
+
|
|
764
|
+
// Check if this was the last download to complete
|
|
765
|
+
if (latch.getCount() == 0 && completionHandled.compareAndSet(false, true)) {
|
|
766
|
+
completionCallback.error(firstError.get());
|
|
601
767
|
}
|
|
602
|
-
});
|
|
603
|
-
if (callback != null) {
|
|
604
|
-
totalBytesDownloaded[0] += fileToDownload.getSizeInBytes();
|
|
605
|
-
callback.onProgress(totalBytesDownloaded[0], finalTotalBytesToDownload);
|
|
606
768
|
}
|
|
607
|
-
} catch (Exception exception) {
|
|
608
|
-
exceptionReference.set(exception);
|
|
609
|
-
Logger.error(LiveUpdatePlugin.TAG, "Failed to download file: " + fileToDownload.getHref(), exception);
|
|
610
769
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
// Wait for all threads to finish
|
|
616
|
-
for (Thread thread : threads) {
|
|
617
|
-
thread.join();
|
|
618
|
-
}
|
|
619
|
-
// Throw the exception if one occurred
|
|
620
|
-
Exception exception = exceptionReference.get();
|
|
621
|
-
if (exception != null) {
|
|
622
|
-
throw exception;
|
|
623
|
-
}
|
|
624
|
-
// Call the callback one last time to make sure the progress is at 100%
|
|
625
|
-
if (callback != null) {
|
|
626
|
-
callback.onProgress(totalBytesToDownload, totalBytesToDownload);
|
|
770
|
+
);
|
|
771
|
+
synchronized (activeCalls) {
|
|
772
|
+
activeCalls.add(call);
|
|
773
|
+
}
|
|
627
774
|
}
|
|
628
775
|
}
|
|
629
776
|
|
|
630
|
-
private void downloadBundleOfTypeManifest(
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
777
|
+
private void downloadBundleOfTypeManifest(
|
|
778
|
+
@NonNull String bundleId,
|
|
779
|
+
@NonNull String downloadUrl,
|
|
780
|
+
@NonNull EmptyCallback completionCallback
|
|
781
|
+
) {
|
|
782
|
+
try {
|
|
783
|
+
// Create a temporary directory
|
|
784
|
+
File temporaryDirectory = createTemporaryDirectory();
|
|
785
|
+
|
|
786
|
+
// Download the latest manifest
|
|
787
|
+
downloadBundleFile(
|
|
788
|
+
downloadUrl,
|
|
789
|
+
manifestFileName,
|
|
790
|
+
temporaryDirectory,
|
|
791
|
+
null,
|
|
792
|
+
new EmptyCallback() {
|
|
793
|
+
@Override
|
|
794
|
+
public void success() {
|
|
795
|
+
try {
|
|
796
|
+
File latestManifestFile = new File(temporaryDirectory, manifestFileName);
|
|
797
|
+
Manifest latestManifest = loadManifest(latestManifestFile);
|
|
798
|
+
// Load the current manifest
|
|
799
|
+
Manifest currentManifest = loadCurrentManifest();
|
|
800
|
+
// Compare the manifests
|
|
801
|
+
List<ManifestItem> itemsToCopy = new ArrayList<>();
|
|
802
|
+
List<ManifestItem> itemsToDownload = new ArrayList<>();
|
|
803
|
+
if (currentManifest == null) {
|
|
804
|
+
itemsToDownload.addAll(latestManifest.getItems());
|
|
805
|
+
} else {
|
|
806
|
+
itemsToCopy.addAll(Manifest.findDuplicateItems(latestManifest, currentManifest));
|
|
807
|
+
itemsToDownload.addAll(Manifest.findMissingItems(latestManifest, currentManifest));
|
|
808
|
+
}
|
|
809
|
+
// Copy the files
|
|
810
|
+
List<ManifestItem> missingItems = copyCurrentBundleFilesAndReturnFailures(itemsToCopy, temporaryDirectory);
|
|
811
|
+
// If items could not be copied, add them to the list of items to download
|
|
812
|
+
if (!missingItems.isEmpty()) {
|
|
813
|
+
itemsToDownload.addAll(missingItems);
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// Download the files
|
|
817
|
+
downloadBundleFiles(
|
|
818
|
+
downloadUrl,
|
|
819
|
+
itemsToDownload,
|
|
820
|
+
temporaryDirectory,
|
|
821
|
+
(downloadedBytes, totalBytes) -> {
|
|
822
|
+
DownloadBundleProgressEvent event = new DownloadBundleProgressEvent(
|
|
823
|
+
bundleId,
|
|
824
|
+
downloadedBytes,
|
|
825
|
+
totalBytes
|
|
826
|
+
);
|
|
827
|
+
notifyDownloadBundleProgressListeners(event);
|
|
828
|
+
},
|
|
829
|
+
new EmptyCallback() {
|
|
830
|
+
@Override
|
|
831
|
+
public void success() {
|
|
832
|
+
try {
|
|
833
|
+
// Add the bundle
|
|
834
|
+
addBundleOfTypeManifest(bundleId, temporaryDirectory);
|
|
835
|
+
completionCallback.success();
|
|
836
|
+
} catch (Exception e) {
|
|
837
|
+
completionCallback.error(e);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
@Override
|
|
842
|
+
public void error(@NonNull Exception exception) {
|
|
843
|
+
completionCallback.error(exception);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
);
|
|
847
|
+
} catch (Exception e) {
|
|
848
|
+
completionCallback.error(e);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
@Override
|
|
853
|
+
public void error(@NonNull Exception exception) {
|
|
854
|
+
completionCallback.error(exception);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
);
|
|
858
|
+
} catch (Exception e) {
|
|
859
|
+
completionCallback.error(e);
|
|
652
860
|
}
|
|
653
|
-
// Download the files
|
|
654
|
-
downloadBundleFiles(downloadUrl, itemsToDownload, temporaryDirectory, (downloadedBytes, totalBytes) -> {
|
|
655
|
-
DownloadBundleProgressEvent event = new DownloadBundleProgressEvent(bundleId, downloadedBytes, totalBytes);
|
|
656
|
-
notifyDownloadBundleProgressListeners(event);
|
|
657
|
-
});
|
|
658
|
-
// Add the bundle
|
|
659
|
-
addBundleOfTypeManifest(bundleId, temporaryDirectory);
|
|
660
861
|
}
|
|
661
862
|
|
|
662
863
|
private void downloadBundleOfTypeZip(
|
|
663
864
|
@NonNull String bundleId,
|
|
664
865
|
@Nullable String checksum,
|
|
665
866
|
@Nullable String signature,
|
|
666
|
-
@NonNull String downloadUrl
|
|
667
|
-
|
|
867
|
+
@NonNull String downloadUrl,
|
|
868
|
+
@NonNull EmptyCallback completionCallback
|
|
869
|
+
) {
|
|
668
870
|
File file = buildTemporaryZipFile();
|
|
669
871
|
// Download the bundle
|
|
670
|
-
downloadAndVerifyFile(
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
872
|
+
downloadAndVerifyFile(
|
|
873
|
+
downloadUrl,
|
|
874
|
+
file,
|
|
875
|
+
checksum,
|
|
876
|
+
signature,
|
|
877
|
+
(downloadedBytes, totalBytes) -> {
|
|
878
|
+
DownloadBundleProgressEvent event = new DownloadBundleProgressEvent(bundleId, downloadedBytes, totalBytes);
|
|
879
|
+
notifyDownloadBundleProgressListeners(event);
|
|
880
|
+
},
|
|
881
|
+
new EmptyCallback() {
|
|
882
|
+
@Override
|
|
883
|
+
public void success() {
|
|
884
|
+
try {
|
|
885
|
+
// Add the bundle
|
|
886
|
+
addBundleOfTypeZip(bundleId, file);
|
|
887
|
+
// Delete the temporary file
|
|
888
|
+
file.delete();
|
|
889
|
+
completionCallback.success();
|
|
890
|
+
} catch (Exception e) {
|
|
891
|
+
completionCallback.error(e);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
@Override
|
|
896
|
+
public void error(@NonNull Exception exception) {
|
|
897
|
+
// Delete the temporary file on error
|
|
898
|
+
file.delete();
|
|
899
|
+
completionCallback.error(exception);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
);
|
|
678
903
|
}
|
|
679
904
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
.
|
|
686
|
-
.
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
905
|
+
private void fetchLatestBundleInternal(
|
|
906
|
+
@NonNull FetchLatestBundleOptions options,
|
|
907
|
+
@NonNull NonEmptyCallback<GetLatestBundleResponse> callback
|
|
908
|
+
) {
|
|
909
|
+
try {
|
|
910
|
+
String channel = options.getChannel() == null ? getChannel() : options.getChannel();
|
|
911
|
+
String url = new HttpUrl.Builder()
|
|
912
|
+
.scheme("https")
|
|
913
|
+
.host(config.getServerDomain())
|
|
914
|
+
.addPathSegment("v1")
|
|
915
|
+
.addPathSegment("apps")
|
|
916
|
+
.addPathSegment(getAppId())
|
|
917
|
+
.addPathSegment("bundles")
|
|
918
|
+
.addPathSegment("latest")
|
|
919
|
+
.addQueryParameter("appVersionCode", getVersionCodeAsString())
|
|
920
|
+
.addQueryParameter("appVersionName", getVersionName())
|
|
921
|
+
.addQueryParameter("bundleId", getCurrentBundleId())
|
|
922
|
+
.addQueryParameter("channelName", channel)
|
|
923
|
+
.addQueryParameter("customId", preferences.getCustomId())
|
|
924
|
+
.addQueryParameter("deviceId", getDeviceId())
|
|
925
|
+
.addQueryParameter("osVersion", String.valueOf(Build.VERSION.SDK_INT))
|
|
926
|
+
.addQueryParameter("platform", "0")
|
|
927
|
+
.addQueryParameter("pluginVersion", LiveUpdatePlugin.VERSION)
|
|
928
|
+
.build()
|
|
929
|
+
.toString();
|
|
930
|
+
Logger.debug(LiveUpdatePlugin.TAG, "Fetching latest bundle: " + url);
|
|
931
|
+
|
|
932
|
+
httpClient.enqueue(
|
|
933
|
+
url,
|
|
934
|
+
new NonEmptyCallback<Response>() {
|
|
935
|
+
@Override
|
|
936
|
+
public void success(@NonNull Response response) {
|
|
937
|
+
try {
|
|
938
|
+
String responseBodyString = response.body().string();
|
|
939
|
+
Logger.debug(LiveUpdatePlugin.TAG, "Latest bundle response: " + responseBodyString);
|
|
940
|
+
if (response.isSuccessful()) {
|
|
941
|
+
JSONObject responseJson = new JSONObject(responseBodyString);
|
|
942
|
+
GetLatestBundleResponse result = new GetLatestBundleResponse(responseJson);
|
|
943
|
+
callback.success(result);
|
|
944
|
+
} else {
|
|
945
|
+
callback.success(null);
|
|
946
|
+
}
|
|
947
|
+
} catch (Exception e) {
|
|
948
|
+
callback.error(e);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
@Override
|
|
953
|
+
public void error(@NonNull Exception exception) {
|
|
954
|
+
callback.error(exception);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
);
|
|
958
|
+
} catch (Exception e) {
|
|
959
|
+
callback.error(e);
|
|
711
960
|
}
|
|
712
961
|
}
|
|
713
962
|
|
|
714
|
-
private String[]
|
|
963
|
+
private String[] getDownloadedBundleIds() {
|
|
715
964
|
File bundlesDirectory = buildBundlesDirectory();
|
|
716
965
|
File[] bundles = bundlesDirectory.listFiles();
|
|
717
966
|
if (bundles == null) {
|
|
@@ -751,6 +1000,15 @@ public class LiveUpdate {
|
|
|
751
1000
|
return checksum.toString();
|
|
752
1001
|
}
|
|
753
1002
|
|
|
1003
|
+
@Nullable
|
|
1004
|
+
private String getAppId() {
|
|
1005
|
+
String appId = preferences.getAppId();
|
|
1006
|
+
if (appId != null) {
|
|
1007
|
+
return appId;
|
|
1008
|
+
}
|
|
1009
|
+
return config.getAppId();
|
|
1010
|
+
}
|
|
1011
|
+
|
|
754
1012
|
@Nullable
|
|
755
1013
|
private String getChannel() {
|
|
756
1014
|
String channel = null;
|
|
@@ -784,10 +1042,10 @@ public class LiveUpdate {
|
|
|
784
1042
|
|
|
785
1043
|
@NonNull
|
|
786
1044
|
private String getDeviceId() {
|
|
787
|
-
String deviceId = preferences.getDeviceIdForApp(
|
|
1045
|
+
String deviceId = preferences.getDeviceIdForApp(getAppId());
|
|
788
1046
|
if (deviceId == null) {
|
|
789
1047
|
deviceId = UUID.randomUUID().toString().toLowerCase();
|
|
790
|
-
preferences.setDeviceIdForApp(
|
|
1048
|
+
preferences.setDeviceIdForApp(getAppId(), deviceId);
|
|
791
1049
|
}
|
|
792
1050
|
return deviceId;
|
|
793
1051
|
}
|
|
@@ -828,8 +1086,12 @@ public class LiveUpdate {
|
|
|
828
1086
|
return preferences.getPreviousBundleId();
|
|
829
1087
|
}
|
|
830
1088
|
|
|
831
|
-
private
|
|
832
|
-
return
|
|
1089
|
+
private int getVersionCodeAsInt() throws PackageManager.NameNotFoundException {
|
|
1090
|
+
return getPackageInfo().versionCode;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
private String getVersionCodeAsString() throws PackageManager.NameNotFoundException {
|
|
1094
|
+
return String.valueOf(getVersionCodeAsInt());
|
|
833
1095
|
}
|
|
834
1096
|
|
|
835
1097
|
private String getVersionName() throws PackageManager.NameNotFoundException {
|
|
@@ -897,27 +1159,21 @@ public class LiveUpdate {
|
|
|
897
1159
|
// Update the timestamp
|
|
898
1160
|
lastAutoUpdateCheckTimestamp = now;
|
|
899
1161
|
|
|
900
|
-
// Run sync
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
Logger.debug(LiveUpdatePlugin.TAG, "Auto-update completed successfully.");
|
|
909
|
-
}
|
|
1162
|
+
// Run sync
|
|
1163
|
+
Logger.debug(LiveUpdatePlugin.TAG, "Auto-update started.");
|
|
1164
|
+
SyncOptions options = new SyncOptions((String) null);
|
|
1165
|
+
NonEmptyCallback<Result> callback = new NonEmptyCallback<>() {
|
|
1166
|
+
@Override
|
|
1167
|
+
public void success(@NonNull Result result) {
|
|
1168
|
+
Logger.debug(LiveUpdatePlugin.TAG, "Auto-update completed successfully.");
|
|
1169
|
+
}
|
|
910
1170
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
Logger.error(LiveUpdatePlugin.TAG, "Auto-update failed: " + exception.getMessage(), exception);
|
|
914
|
-
}
|
|
915
|
-
};
|
|
916
|
-
sync(options, callback);
|
|
917
|
-
} catch (Exception exception) {
|
|
1171
|
+
@Override
|
|
1172
|
+
public void error(@NonNull Exception exception) {
|
|
918
1173
|
Logger.error(LiveUpdatePlugin.TAG, "Auto-update failed: " + exception.getMessage(), exception);
|
|
919
1174
|
}
|
|
920
|
-
}
|
|
1175
|
+
};
|
|
1176
|
+
sync(options, callback);
|
|
921
1177
|
}
|
|
922
1178
|
|
|
923
1179
|
private void rollback() {
|
|
@@ -981,6 +1237,8 @@ public class LiveUpdate {
|
|
|
981
1237
|
this.plugin.getBridge().setServerBasePath(path);
|
|
982
1238
|
}
|
|
983
1239
|
this.plugin.getBridge().reload();
|
|
1240
|
+
// Notify listeners
|
|
1241
|
+
notifyReloadedListeners();
|
|
984
1242
|
}
|
|
985
1243
|
|
|
986
1244
|
/**
|
|
@@ -1003,6 +1261,10 @@ public class LiveUpdate {
|
|
|
1003
1261
|
plugin.notifyNextBundleSetListeners(event);
|
|
1004
1262
|
}
|
|
1005
1263
|
|
|
1264
|
+
private void notifyReloadedListeners() {
|
|
1265
|
+
plugin.notifyReloadedListeners();
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1006
1268
|
private void addBlockedBundleId(@NonNull String bundleId) {
|
|
1007
1269
|
String blockedIds = preferences.getBlockedBundleIds();
|
|
1008
1270
|
List<String> blockedList = new ArrayList<>();
|
|
@@ -1048,9 +1310,20 @@ public class LiveUpdate {
|
|
|
1048
1310
|
this.webViewSettingsEditor.commit();
|
|
1049
1311
|
}
|
|
1050
1312
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1313
|
+
private void checkAndResetConfigIfVersionChanged() throws PackageManager.NameNotFoundException {
|
|
1314
|
+
int currentVersionCode = getVersionCodeAsInt();
|
|
1315
|
+
int lastVersionCode = preferences.getLastVersionCode();
|
|
1316
|
+
|
|
1317
|
+
if (lastVersionCode == -1 || lastVersionCode != currentVersionCode) {
|
|
1318
|
+
Logger.debug(
|
|
1319
|
+
LiveUpdatePlugin.TAG,
|
|
1320
|
+
"App version changed (last: " + lastVersionCode + ", current: " + currentVersionCode + "), resetting config."
|
|
1321
|
+
);
|
|
1322
|
+
resetConfig();
|
|
1323
|
+
preferences.setLastVersionCode(currentVersionCode);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1054
1327
|
private void setPreviousBundleId(@Nullable String bundleId) {
|
|
1055
1328
|
preferences.setPreviousBundleId(bundleId);
|
|
1056
1329
|
}
|