@capgo/capacitor-updater 4.13.7 → 4.14.1

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.
@@ -1,3 +1,6 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
2
  package="ee.forgr.capacitor_updater">
3
+ <application>
4
+ <service android:name="ee.forgr.capacitor_updater.DownloadService" />
5
+ </application>
3
6
  </manifest>
@@ -1,7 +1,13 @@
1
1
  package ee.forgr.capacitor_updater;
2
2
 
3
+ import android.app.Activity;
4
+ import android.content.BroadcastReceiver;
5
+ import android.content.Context;
6
+ import android.content.Intent;
7
+ import android.content.IntentFilter;
3
8
  import android.content.SharedPreferences;
4
9
  import android.os.Build;
10
+ import android.os.Bundle;
5
11
  import android.util.Base64;
6
12
  import android.util.Log;
7
13
  import com.android.volley.BuildConfig;
@@ -54,7 +60,7 @@ public class CapacitorUpdater {
54
60
  private static final String bundleDirectory = "versions";
55
61
 
56
62
  public static final String TAG = "Capacitor-updater";
57
- public static final String pluginVersion = "4.13.7";
63
+ public static final String pluginVersion = "4.14.1";
58
64
 
59
65
  public SharedPreferences.Editor editor;
60
66
  public SharedPreferences prefs;
@@ -62,6 +68,7 @@ public class CapacitorUpdater {
62
68
  public RequestQueue requestQueue;
63
69
 
64
70
  public File documentsDir;
71
+ public Activity activity;
65
72
  public String versionBuild = "";
66
73
  public String versionCode = "";
67
74
  public String versionOs = "";
@@ -125,6 +132,10 @@ public class CapacitorUpdater {
125
132
  return;
126
133
  }
127
134
 
135
+ void notifyListeners(final String id, final JSObject res) {
136
+ return;
137
+ }
138
+
128
139
  private String randomString(final int len) {
129
140
  final StringBuilder sb = new StringBuilder(len);
130
141
  for (int i = 0; i < len; i++) sb.append(
@@ -224,6 +235,135 @@ public class CapacitorUpdater {
224
235
  sourceFile.delete();
225
236
  }
226
237
 
238
+ public void onResume() {
239
+ this.activity.registerReceiver(
240
+ receiver,
241
+ new IntentFilter(DownloadService.NOTIFICATION)
242
+ );
243
+ }
244
+
245
+ public void onPause() {
246
+ this.activity.unregisterReceiver(receiver);
247
+ }
248
+
249
+ private BroadcastReceiver receiver = new BroadcastReceiver() {
250
+ @Override
251
+ public void onReceive(Context context, Intent intent) {
252
+ String action = intent.getAction();
253
+ Bundle bundle = intent.getExtras();
254
+ if (bundle != null) {
255
+ if (action == DownloadService.PERCENTDOWNLOAD) {
256
+ String id = bundle.getString(DownloadService.ID);
257
+ int percent = bundle.getInt(DownloadService.PERCENT);
258
+ CapacitorUpdater.this.notifyDownload(id, percent);
259
+ } else if (action == DownloadService.NOTIFICATION) {
260
+ String id = bundle.getString(DownloadService.ID);
261
+ String dest = bundle.getString(DownloadService.FILEDEST);
262
+ String version = bundle.getString(DownloadService.VERSION);
263
+ String sessionKey = bundle.getString(DownloadService.SESSIONKEY);
264
+ String checksum = bundle.getString(DownloadService.CHECKSUM);
265
+ Log.i(
266
+ CapacitorUpdater.TAG,
267
+ "res " +
268
+ id +
269
+ " " +
270
+ dest +
271
+ " " +
272
+ version +
273
+ " " +
274
+ sessionKey +
275
+ " " +
276
+ checksum
277
+ );
278
+ CapacitorUpdater.this.finishBackground(
279
+ id,
280
+ dest,
281
+ version,
282
+ sessionKey,
283
+ checksum
284
+ );
285
+ } else {
286
+ Log.i(TAG, "Unknown action " + action);
287
+ }
288
+ }
289
+ }
290
+ };
291
+
292
+ public void finishBackground(
293
+ String id,
294
+ String dest,
295
+ String version,
296
+ String sessionKey,
297
+ String checksumRes
298
+ ) {
299
+ try {
300
+ final File downloaded = new File(this.documentsDir, dest);
301
+ this.decryptFile(downloaded, sessionKey);
302
+ final String checksum;
303
+ checksum = this.getChecksum(downloaded);
304
+
305
+ this.notifyDownload(id, 71);
306
+ final File unzipped = this.unzip(id, downloaded, this.randomString(10));
307
+ downloaded.delete();
308
+ this.notifyDownload(id, 91);
309
+ final String idName = bundleDirectory + "/" + id;
310
+ this.flattenAssets(unzipped, idName);
311
+ this.notifyDownload(id, 100);
312
+ this.saveBundleInfo(id, null);
313
+ BundleInfo info = new BundleInfo(
314
+ id,
315
+ version,
316
+ BundleStatus.PENDING,
317
+ new Date(System.currentTimeMillis()),
318
+ checksum
319
+ );
320
+ this.saveBundleInfo(id, info);
321
+ if (!checksumRes.equals("") && !checksumRes.equals(checksum)) {
322
+ Log.e(
323
+ CapacitorUpdater.TAG,
324
+ "Error checksum " + info.getChecksum() + " " + checksum
325
+ );
326
+ this.sendStats("checksum_fail", getCurrentBundle().getVersionName());
327
+ final Boolean res = this.delete(info.getId());
328
+ if (res) {
329
+ Log.i(
330
+ CapacitorUpdater.TAG,
331
+ "Failed bundle deleted: " + info.getVersionName()
332
+ );
333
+ }
334
+ return;
335
+ }
336
+ final JSObject ret = new JSObject();
337
+ ret.put("bundle", info.toJSON());
338
+ CapacitorUpdater.this.notifyListeners("updateAvailable", ret);
339
+ this.setNextBundle(info.getId());
340
+ } catch (IOException e) {
341
+ e.printStackTrace();
342
+ }
343
+ }
344
+
345
+ private void downloadFileBackground(
346
+ final String id,
347
+ final String url,
348
+ final String version,
349
+ final String sessionKey,
350
+ final String checksum,
351
+ final String dest
352
+ ) {
353
+ Intent intent = new Intent(this.activity, DownloadService.class);
354
+ intent.putExtra(DownloadService.URL, url);
355
+ intent.putExtra(DownloadService.FILEDEST, dest);
356
+ intent.putExtra(
357
+ DownloadService.DOCDIR,
358
+ this.documentsDir.getAbsolutePath()
359
+ );
360
+ intent.putExtra(DownloadService.ID, id);
361
+ intent.putExtra(DownloadService.VERSION, version);
362
+ intent.putExtra(DownloadService.SESSIONKEY, sessionKey);
363
+ intent.putExtra(DownloadService.CHECKSUM, checksum);
364
+ this.activity.startService(intent);
365
+ }
366
+
227
367
  private File downloadFile(
228
368
  final String id,
229
369
  final String url,
@@ -325,6 +465,35 @@ public class CapacitorUpdater {
325
465
  }
326
466
  }
327
467
 
468
+ public void downloadBackground(
469
+ final String url,
470
+ final String version,
471
+ final String sessionKey,
472
+ final String checksum
473
+ ) {
474
+ final String id = this.randomString(10);
475
+ this.saveBundleInfo(
476
+ id,
477
+ new BundleInfo(
478
+ id,
479
+ version,
480
+ BundleStatus.DOWNLOADING,
481
+ new Date(System.currentTimeMillis()),
482
+ ""
483
+ )
484
+ );
485
+ this.notifyDownload(id, 0);
486
+ this.notifyDownload(id, 5);
487
+ this.downloadFileBackground(
488
+ id,
489
+ url,
490
+ version,
491
+ sessionKey,
492
+ checksum,
493
+ this.randomString(10)
494
+ );
495
+ }
496
+
328
497
  public BundleInfo download(
329
498
  final String url,
330
499
  final String version,
@@ -81,11 +81,17 @@ public class CapacitorUpdaterPlugin
81
81
  public void notifyDownload(final String id, final int percent) {
82
82
  CapacitorUpdaterPlugin.this.notifyDownload(id, percent);
83
83
  }
84
+
85
+ @Override
86
+ public void notifyListeners(final String id, final JSObject res) {
87
+ CapacitorUpdaterPlugin.this.notifyListeners(id, res);
88
+ }
84
89
  };
85
90
  final PackageInfo pInfo =
86
91
  this.getContext()
87
92
  .getPackageManager()
88
93
  .getPackageInfo(this.getContext().getPackageName(), 0);
94
+ this.implementation.activity = this.getActivity();
89
95
  this.implementation.versionBuild = pInfo.versionName;
90
96
  this.implementation.versionCode = Integer.toString(pInfo.versionCode);
91
97
  this.implementation.requestQueue =
@@ -803,245 +809,191 @@ public class CapacitorUpdaterPlugin
803
809
  }
804
810
  }
805
811
 
806
- @Override // appMovedToForeground
807
- public void onActivityStarted(@NonNull final Activity activity) {
808
- if (CapacitorUpdaterPlugin.this._isAutoUpdateEnabled()) {
809
- new Thread(
810
- new Runnable() {
811
- @Override
812
- public void run() {
813
- Log.i(
814
- CapacitorUpdater.TAG,
815
- "Check for update via: " + CapacitorUpdaterPlugin.this.updateUrl
816
- );
817
- CapacitorUpdaterPlugin.this.implementation.getLatest(
818
- CapacitorUpdaterPlugin.this.updateUrl,
819
- res -> {
820
- final BundleInfo current =
821
- CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
822
- try {
823
- if (res.has("message")) {
824
- Log.i(
825
- CapacitorUpdater.TAG,
826
- "message " + res.get("message")
827
- );
828
- if (
829
- res.has("major") &&
830
- res.getBoolean("major") &&
831
- res.has("version")
832
- ) {
833
- final JSObject majorAvailable = new JSObject();
834
- majorAvailable.put("version", res.getString("version"));
835
- CapacitorUpdaterPlugin.this.notifyListeners(
836
- "majorAvailable",
837
- majorAvailable
838
- );
839
- }
840
- final JSObject retNoNeed = new JSObject();
841
- retNoNeed.put("bundle", current.toJSON());
842
- CapacitorUpdaterPlugin.this.notifyListeners(
843
- "noNeedUpdate",
844
- retNoNeed
845
- );
846
- return;
847
- }
848
-
812
+ private void backgroundDownload() {
813
+ new Thread(
814
+ new Runnable() {
815
+ @Override
816
+ public void run() {
817
+ Log.i(
818
+ CapacitorUpdater.TAG,
819
+ "Check for update via: " + CapacitorUpdaterPlugin.this.updateUrl
820
+ );
821
+ CapacitorUpdaterPlugin.this.implementation.getLatest(
822
+ CapacitorUpdaterPlugin.this.updateUrl,
823
+ res -> {
824
+ final BundleInfo current =
825
+ CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
826
+ try {
827
+ if (res.has("message")) {
828
+ Log.i(
829
+ CapacitorUpdater.TAG,
830
+ "message " + res.get("message")
831
+ );
849
832
  if (
850
- !res.has("url") ||
851
- !CapacitorUpdaterPlugin.this.isValidURL(
852
- res.getString("url")
853
- )
833
+ res.has("major") &&
834
+ res.getBoolean("major") &&
835
+ res.has("version")
854
836
  ) {
855
- Log.e(
856
- CapacitorUpdater.TAG,
857
- "Error no url or wrong format"
858
- );
859
- final JSObject retNoNeed = new JSObject();
860
- retNoNeed.put("bundle", current.toJSON());
837
+ final JSObject majorAvailable = new JSObject();
838
+ majorAvailable.put("version", res.getString("version"));
861
839
  CapacitorUpdaterPlugin.this.notifyListeners(
862
- "noNeedUpdate",
863
- retNoNeed
840
+ "majorAvailable",
841
+ majorAvailable
864
842
  );
865
843
  }
866
- final String latestVersionName = res.getString("version");
844
+ final JSObject retNoNeed = new JSObject();
845
+ retNoNeed.put("bundle", current.toJSON());
846
+ CapacitorUpdaterPlugin.this.notifyListeners(
847
+ "noNeedUpdate",
848
+ retNoNeed
849
+ );
850
+ return;
851
+ }
867
852
 
868
- if (
869
- latestVersionName != null &&
870
- !"".equals(latestVersionName) &&
871
- !current.getVersionName().equals(latestVersionName)
872
- ) {
873
- final BundleInfo latest =
874
- CapacitorUpdaterPlugin.this.implementation.getBundleInfoByName(
875
- latestVersionName
853
+ if (
854
+ !res.has("url") ||
855
+ !CapacitorUpdaterPlugin.this.isValidURL(
856
+ res.getString("url")
857
+ )
858
+ ) {
859
+ Log.e(CapacitorUpdater.TAG, "Error no url or wrong format");
860
+ final JSObject retNoNeed = new JSObject();
861
+ retNoNeed.put("bundle", current.toJSON());
862
+ CapacitorUpdaterPlugin.this.notifyListeners(
863
+ "noNeedUpdate",
864
+ retNoNeed
865
+ );
866
+ }
867
+ final String latestVersionName = res.getString("version");
868
+
869
+ if (
870
+ latestVersionName != null &&
871
+ !"".equals(latestVersionName) &&
872
+ !current.getVersionName().equals(latestVersionName)
873
+ ) {
874
+ final BundleInfo latest =
875
+ CapacitorUpdaterPlugin.this.implementation.getBundleInfoByName(
876
+ latestVersionName
877
+ );
878
+ if (latest != null) {
879
+ if (latest.isErrorStatus()) {
880
+ Log.e(
881
+ CapacitorUpdater.TAG,
882
+ "Latest bundle already exists, and is in error state. Aborting update."
883
+ );
884
+ final JSObject retNoNeed = new JSObject();
885
+ retNoNeed.put("bundle", current.toJSON());
886
+ CapacitorUpdaterPlugin.this.notifyListeners(
887
+ "noNeedUpdate",
888
+ retNoNeed
876
889
  );
877
- if (latest != null) {
878
- if (latest.isErrorStatus()) {
879
- Log.e(
880
- CapacitorUpdater.TAG,
881
- "Latest bundle already exists, and is in error state. Aborting update."
890
+ return;
891
+ }
892
+ if (latest.isDownloaded()) {
893
+ Log.i(
894
+ CapacitorUpdater.TAG,
895
+ "Latest bundle already exists and download is NOT required. Update will occur next time app moves to background."
896
+ );
897
+ final JSObject ret = new JSObject();
898
+ ret.put("bundle", latest.toJSON());
899
+ CapacitorUpdaterPlugin.this.notifyListeners(
900
+ "updateAvailable",
901
+ ret
882
902
  );
883
- final JSObject retNoNeed = new JSObject();
884
- retNoNeed.put("bundle", current.toJSON());
885
- CapacitorUpdaterPlugin.this.notifyListeners(
886
- "noNeedUpdate",
887
- retNoNeed
888
- );
889
- return;
890
- }
891
- if (latest.isDownloaded()) {
892
- Log.i(
893
- CapacitorUpdater.TAG,
894
- "Latest bundle already exists and download is NOT required. Update will occur next time app moves to background."
903
+ CapacitorUpdaterPlugin.this.implementation.setNextBundle(
904
+ latest.getId()
895
905
  );
896
- final JSObject ret = new JSObject();
897
- ret.put("bundle", latest.toJSON());
898
- CapacitorUpdaterPlugin.this.notifyListeners(
899
- "updateAvailable",
900
- ret
901
- );
902
- CapacitorUpdaterPlugin.this.implementation.setNextBundle(
903
- latest.getId()
906
+ return;
907
+ }
908
+ if (latest.isDeleted()) {
909
+ Log.i(
910
+ CapacitorUpdater.TAG,
911
+ "Latest bundle already exists and will be deleted, download will overwrite it."
912
+ );
913
+ try {
914
+ final Boolean deleted =
915
+ CapacitorUpdaterPlugin.this.implementation.delete(
916
+ latest.getId(),
917
+ true
918
+ );
919
+ if (deleted) {
920
+ Log.i(
921
+ CapacitorUpdater.TAG,
922
+ "Failed bundle deleted: " +
923
+ latest.getVersionName()
904
924
  );
905
- return;
906
- }
907
- if (latest.isDeleted()) {
908
- Log.i(
925
+ }
926
+ } catch (final IOException e) {
927
+ Log.e(
909
928
  CapacitorUpdater.TAG,
910
- "Latest bundle already exists and will be deleted, download will overwrite it."
929
+ "Failed to delete failed bundle: " +
930
+ latest.getVersionName(),
931
+ e
911
932
  );
933
+ }
934
+ }
935
+ }
936
+
937
+ new Thread(
938
+ new Runnable() {
939
+ @Override
940
+ public void run() {
912
941
  try {
913
- final Boolean deleted =
914
- CapacitorUpdaterPlugin.this.implementation.delete(
915
- latest.getId(),
916
- true
917
- );
918
- if (deleted) {
919
- Log.i(
920
- CapacitorUpdater.TAG,
921
- "Failed bundle deleted: " +
922
- latest.getVersionName()
942
+ Log.i(
943
+ CapacitorUpdater.TAG,
944
+ "New bundle: " +
945
+ latestVersionName +
946
+ " found. Current is: " +
947
+ current.getVersionName() +
948
+ ". Update will occur next time app moves to background."
949
+ );
950
+
951
+ final String url = res.getString("url");
952
+ final String session_key = res.has("session_key")
953
+ ? res.getString("session_key")
954
+ : "";
955
+ CapacitorUpdaterPlugin.this.implementation.downloadBackground(
956
+ url,
957
+ latestVersionName,
958
+ session_key,
959
+ res.getString("checksum")
923
960
  );
924
- }
925
- } catch (final IOException e) {
961
+ } catch (final Exception e) {
926
962
  Log.e(
927
963
  CapacitorUpdater.TAG,
928
- "Failed to delete failed bundle: " +
929
- latest.getVersionName(),
964
+ "error downloading file",
930
965
  e
931
966
  );
932
- }
933
- }
934
- }
935
-
936
- new Thread(
937
- new Runnable() {
938
- @Override
939
- public void run() {
940
- try {
941
- Log.i(
942
- CapacitorUpdater.TAG,
943
- "New bundle: " +
944
- latestVersionName +
945
- " found. Current is: " +
946
- current.getVersionName() +
947
- ". Update will occur next time app moves to background."
967
+ final JSObject ret = new JSObject();
968
+ ret.put("version", latestVersionName);
969
+ CapacitorUpdaterPlugin.this.notifyListeners(
970
+ "downloadFailed",
971
+ ret
948
972
  );
949
-
950
- final String url = res.getString("url");
951
- final String session_key = res.has("session_key")
952
- ? res.getString("session_key")
953
- : "";
954
- final BundleInfo next =
955
- CapacitorUpdaterPlugin.this.implementation.download(
956
- url,
957
- latestVersionName,
958
- session_key
959
- );
960
- final String checksum = res.has("checksum")
961
- ? res.getString("checksum")
962
- : "";
963
- if (
964
- !checksum.equals("") &&
965
- !next.getChecksum().equals(checksum)
966
- ) {
967
- Log.e(
968
- CapacitorUpdater.TAG,
969
- "Error checksum " +
970
- next.getChecksum() +
971
- " " +
972
- checksum
973
- );
974
- CapacitorUpdaterPlugin.this.implementation.sendStats(
975
- "checksum_fail",
976
- current.getVersionName()
977
- );
978
- final Boolean res =
979
- CapacitorUpdaterPlugin.this.implementation.delete(
980
- next.getId()
981
- );
982
- if (res) {
983
- Log.i(
984
- CapacitorUpdater.TAG,
985
- "Failed bundle deleted: " +
986
- next.getVersionName()
987
- );
988
- }
989
- return;
990
- }
991
- final JSObject ret = new JSObject();
992
- ret.put("bundle", next.toJSON());
993
- CapacitorUpdaterPlugin.this.notifyListeners(
994
- "updateAvailable",
995
- ret
996
- );
997
- CapacitorUpdaterPlugin.this.implementation.setNextBundle(
998
- next.getId()
999
- );
1000
- } catch (final Exception e) {
1001
- Log.e(
1002
- CapacitorUpdater.TAG,
1003
- "error downloading file",
1004
- e
973
+ final BundleInfo current =
974
+ CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
975
+ CapacitorUpdaterPlugin.this.implementation.sendStats(
976
+ "download_fail",
977
+ current.getVersionName()
978
+ );
979
+ final JSObject retNoNeed = new JSObject();
980
+ retNoNeed.put("bundle", current.toJSON());
981
+ CapacitorUpdaterPlugin.this.notifyListeners(
982
+ "noNeedUpdate",
983
+ retNoNeed
1005
984
  );
1006
- final JSObject ret = new JSObject();
1007
- ret.put("version", latestVersionName);
1008
- CapacitorUpdaterPlugin.this.notifyListeners(
1009
- "downloadFailed",
1010
- ret
1011
- );
1012
- final BundleInfo current =
1013
- CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
1014
- CapacitorUpdaterPlugin.this.implementation.sendStats(
1015
- "download_fail",
1016
- current.getVersionName()
1017
- );
1018
- final JSObject retNoNeed = new JSObject();
1019
- retNoNeed.put("bundle", current.toJSON());
1020
- CapacitorUpdaterPlugin.this.notifyListeners(
1021
- "noNeedUpdate",
1022
- retNoNeed
1023
- );
1024
- }
1025
985
  }
1026
986
  }
1027
- )
1028
- .start();
1029
- } else {
1030
- Log.i(
1031
- CapacitorUpdater.TAG,
1032
- "No need to update, " +
1033
- current.getId() +
1034
- " is the latest bundle."
1035
- );
1036
- final JSObject retNoNeed = new JSObject();
1037
- retNoNeed.put("bundle", current.toJSON());
1038
- CapacitorUpdaterPlugin.this.notifyListeners(
1039
- "noNeedUpdate",
1040
- retNoNeed
1041
- );
1042
- }
1043
- } catch (final JSONException e) {
1044
- Log.e(CapacitorUpdater.TAG, "error parsing JSON", e);
987
+ }
988
+ )
989
+ .start();
990
+ } else {
991
+ Log.i(
992
+ CapacitorUpdater.TAG,
993
+ "No need to update, " +
994
+ current.getId() +
995
+ " is the latest bundle."
996
+ );
1045
997
  final JSObject retNoNeed = new JSObject();
1046
998
  retNoNeed.put("bundle", current.toJSON());
1047
999
  CapacitorUpdaterPlugin.this.notifyListeners(
@@ -1049,14 +1001,28 @@ public class CapacitorUpdaterPlugin
1049
1001
  retNoNeed
1050
1002
  );
1051
1003
  }
1004
+ } catch (final JSONException e) {
1005
+ Log.e(CapacitorUpdater.TAG, "error parsing JSON", e);
1006
+ final JSObject retNoNeed = new JSObject();
1007
+ retNoNeed.put("bundle", current.toJSON());
1008
+ CapacitorUpdaterPlugin.this.notifyListeners(
1009
+ "noNeedUpdate",
1010
+ retNoNeed
1011
+ );
1052
1012
  }
1053
- );
1054
- }
1013
+ }
1014
+ );
1055
1015
  }
1056
- )
1057
- .start();
1058
- }
1016
+ }
1017
+ )
1018
+ .start();
1019
+ }
1059
1020
 
1021
+ @Override // appMovedToForeground
1022
+ public void onActivityStarted(@NonNull final Activity activity) {
1023
+ if (CapacitorUpdaterPlugin.this._isAutoUpdateEnabled()) {
1024
+ this.backgroundDownload();
1025
+ }
1060
1026
  this.checkAppReady();
1061
1027
  }
1062
1028
 
@@ -1246,23 +1212,34 @@ public class CapacitorUpdaterPlugin
1246
1212
  if (backgroundTask != null && taskRunning) {
1247
1213
  backgroundTask.interrupt();
1248
1214
  }
1215
+ this.implementation.activity = activity;
1216
+ this.implementation.onResume();
1249
1217
  }
1250
1218
 
1251
1219
  @Override
1252
- public void onActivityPaused(@NonNull final Activity activity) {}
1220
+ public void onActivityPaused(@NonNull final Activity activity) {
1221
+ this.implementation.activity = activity;
1222
+ this.implementation.onPause();
1223
+ }
1253
1224
 
1254
1225
  @Override
1255
1226
  public void onActivityCreated(
1256
1227
  @NonNull final Activity activity,
1257
1228
  @Nullable final Bundle savedInstanceState
1258
- ) {}
1229
+ ) {
1230
+ this.implementation.activity = activity;
1231
+ }
1259
1232
 
1260
1233
  @Override
1261
1234
  public void onActivitySaveInstanceState(
1262
1235
  @NonNull final Activity activity,
1263
1236
  @NonNull final Bundle outState
1264
- ) {}
1237
+ ) {
1238
+ this.implementation.activity = activity;
1239
+ }
1265
1240
 
1266
1241
  @Override
1267
- public void onActivityDestroyed(@NonNull final Activity activity) {}
1242
+ public void onActivityDestroyed(@NonNull final Activity activity) {
1243
+ this.implementation.activity = activity;
1244
+ }
1268
1245
  }
@@ -0,0 +1,120 @@
1
+ package ee.forgr.capacitor_updater;
2
+
3
+ import android.app.IntentService;
4
+ import android.content.Intent;
5
+ import java.io.DataInputStream;
6
+ import java.io.File;
7
+ import java.io.FileOutputStream;
8
+ import java.io.InputStream;
9
+ import java.net.URL;
10
+ import java.net.URLConnection;
11
+
12
+ public class DownloadService extends IntentService {
13
+
14
+ public static final String URL = "URL";
15
+ public static final String ID = "id";
16
+ public static final String PERCENT = "percent";
17
+ public static final String FILEDEST = "filendest";
18
+ public static final String DOCDIR = "docdir";
19
+ public static final String ERROR = "error";
20
+ public static final String VERSION = "version";
21
+ public static final String SESSIONKEY = "sessionkey";
22
+ public static final String CHECKSUM = "checksum";
23
+ public static final String NOTIFICATION = "service receiver";
24
+ public static final String PERCENTDOWNLOAD = "percent receiver";
25
+
26
+ public DownloadService() {
27
+ super("Background DownloadService");
28
+ }
29
+
30
+ private int calcTotalPercent(
31
+ final int percent,
32
+ final int min,
33
+ final int max
34
+ ) {
35
+ return (percent * (max - min)) / 100 + min;
36
+ }
37
+
38
+ // Will be called asynchronously by OS.
39
+ @Override
40
+ protected void onHandleIntent(Intent intent) {
41
+ String url = intent.getStringExtra(URL);
42
+ String id = intent.getStringExtra(ID);
43
+ String documentsDir = intent.getStringExtra(DOCDIR);
44
+ String dest = intent.getStringExtra(FILEDEST);
45
+ String version = intent.getStringExtra(VERSION);
46
+ String sessionKey = intent.getStringExtra(SESSIONKEY);
47
+ String checksum = intent.getStringExtra(CHECKSUM);
48
+
49
+ try {
50
+ final URL u = new URL(url);
51
+ final URLConnection connection = u.openConnection();
52
+ final InputStream is = u.openStream();
53
+ final DataInputStream dis = new DataInputStream(is);
54
+
55
+ final File target = new File(documentsDir, dest);
56
+ target.getParentFile().mkdirs();
57
+ target.createNewFile();
58
+ final FileOutputStream fos = new FileOutputStream(target);
59
+
60
+ final long totalLength = connection.getContentLength();
61
+ final int bufferSize = 1024;
62
+ final byte[] buffer = new byte[bufferSize];
63
+ int length;
64
+
65
+ int bytesRead = bufferSize;
66
+ int percent = 0;
67
+ this.notifyDownload(id, 10);
68
+ while ((length = dis.read(buffer)) > 0) {
69
+ fos.write(buffer, 0, length);
70
+ final int newPercent = (int) ((bytesRead * 100) / totalLength);
71
+ if (totalLength > 1 && newPercent != percent) {
72
+ percent = newPercent;
73
+ this.notifyDownload(id, this.calcTotalPercent(percent, 10, 70));
74
+ }
75
+ bytesRead += length;
76
+ }
77
+ publishResults(dest, id, version, checksum, sessionKey, "");
78
+ } catch (Exception e) {
79
+ e.printStackTrace();
80
+ publishResults(
81
+ "",
82
+ id,
83
+ version,
84
+ checksum,
85
+ sessionKey,
86
+ e.getLocalizedMessage()
87
+ );
88
+ }
89
+ }
90
+
91
+ private void notifyDownload(String id, int percent) {
92
+ Intent intent = new Intent(PERCENTDOWNLOAD);
93
+ intent.putExtra(ID, id);
94
+ intent.putExtra(PERCENT, percent);
95
+ sendBroadcast(intent);
96
+ }
97
+
98
+ private void publishResults(
99
+ String dest,
100
+ String id,
101
+ String version,
102
+ String checksum,
103
+ String sessionKey,
104
+ String error
105
+ ) {
106
+ Intent intent = new Intent(NOTIFICATION);
107
+ if (!dest.equals("")) {
108
+ intent.putExtra(FILEDEST, dest);
109
+ }
110
+ if (!error.equals("")) {
111
+ intent.putExtra(ERROR, error);
112
+ }
113
+ intent.putExtra(ID, id);
114
+ intent.putExtra(VERSION, version);
115
+ intent.putExtra(SESSIONKEY, sessionKey);
116
+ intent.putExtra(CHECKSUM, checksum);
117
+ intent.putExtra(ERROR, error);
118
+ sendBroadcast(intent);
119
+ }
120
+ }
@@ -466,101 +466,105 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
466
466
  self.appReadyCheck = nil
467
467
  }
468
468
 
469
- func EndBackGroundTask() {
469
+ func endBackGroundTask() {
470
470
  UIApplication.shared.endBackgroundTask(self.backgroundTaskID)
471
471
  self.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
472
472
  }
473
- @objc func appMovedToForeground() {
474
- if backgroundWork != nil && taskRunning {
475
- backgroundWork!.cancel()
476
- print("\(self.implementation.TAG) Background Timer Task canceled, Activity resumed before timer completes")
477
- }
478
- if self._isAutoUpdateEnabled() {
479
- DispatchQueue.global(qos: .background).async {
480
- self.backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish Download Tasks") {
481
- // End the task if time expires.
482
- UIApplication.shared.endBackgroundTask(self.backgroundTaskID)
483
- self.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
473
+
474
+ func backgroundDownload() {
475
+ DispatchQueue.global(qos: .background).async {
476
+ self.backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish Download Tasks") {
477
+ // End the task if time expires.
478
+ self.endBackGroundTask()
479
+ }
480
+ print("\(self.implementation.TAG) Check for update via \(self.updateUrl)")
481
+ let url = URL(string: self.updateUrl)!
482
+ let res = self.implementation.getLatest(url: url)
483
+ let current = self.implementation.getCurrentBundle()
484
+
485
+ if (res.message) != nil {
486
+ print("\(self.implementation.TAG) message \(res.message ?? "")")
487
+ if res.major == true {
488
+ self.notifyListeners("majorAvailable", data: ["version": res.version])
484
489
  }
485
- print("\(self.implementation.TAG) Check for update via \(self.updateUrl)")
486
- let url = URL(string: self.updateUrl)!
487
- let res = self.implementation.getLatest(url: url)
488
- let current = self.implementation.getCurrentBundle()
489
-
490
- if (res.message) != nil {
491
- print("\(self.implementation.TAG) message \(res.message ?? "")")
492
- if res.major == true {
493
- self.notifyListeners("majorAvailable", data: ["version": res.version])
490
+ self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
491
+ self.endBackGroundTask()
492
+ return
493
+ }
494
+ let sessionKey = res.sessionKey ?? ""
495
+ guard let downloadUrl = URL(string: res.url) else {
496
+ print("\(self.implementation.TAG) Error no url or wrong format")
497
+ self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
498
+ self.endBackGroundTask()
499
+ return
500
+ }
501
+ let latestVersionName = res.version
502
+ if latestVersionName != "" && current.getVersionName() != latestVersionName {
503
+ let latest = self.implementation.getBundleInfoByVersionName(version: latestVersionName)
504
+ if latest != nil {
505
+ if latest!.isErrorStatus() {
506
+ print("\(self.implementation.TAG) Latest version already exists, and is in error state. Aborting update.")
507
+ self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
508
+ self.endBackGroundTask()
509
+ return
494
510
  }
495
- self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
496
- self.EndBackGroundTask()
497
- return
498
- }
499
- let sessionKey = res.sessionKey ?? ""
500
- guard let downloadUrl = URL(string: res.url) else {
501
- print("\(self.implementation.TAG) Error no url or wrong format")
502
- self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
503
- self.EndBackGroundTask()
504
- return
505
- }
506
- let latestVersionName = res.version
507
- if latestVersionName != "" && current.getVersionName() != latestVersionName {
508
- let latest = self.implementation.getBundleInfoByVersionName(version: latestVersionName)
509
- if latest != nil {
510
- if latest!.isErrorStatus() {
511
- print("\(self.implementation.TAG) Latest version already exists, and is in error state. Aborting update.")
512
- self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
513
- self.EndBackGroundTask()
514
- return
515
- }
516
- if latest!.isDownloaded() {
517
- print("\(self.implementation.TAG) Latest version already exists and download is NOT required. Update will occur next time app moves to background.")
518
- self.notifyListeners("updateAvailable", data: ["bundle": current.toJSON()])
519
- _ = self.implementation.setNextBundle(next: latest!.getId())
520
- self.EndBackGroundTask()
521
- return
522
- }
523
- if latest!.isDeleted() {
524
- print("\(self.implementation.TAG) Latest bundle already exists and will be deleted, download will overwrite it.")
525
- let res = self.implementation.delete(id: latest!.getId(), removeInfo: true)
526
- if !res {
527
- print("\(self.implementation.TAG) Delete version deleted: \(latest!.toString())")
528
- } else {
529
- print("\(self.implementation.TAG) Failed to delete failed bundle: \(latest!.toString())")
530
- }
511
+ if latest!.isDownloaded() {
512
+ print("\(self.implementation.TAG) Latest version already exists and download is NOT required. Update will occur next time app moves to background.")
513
+ self.notifyListeners("updateAvailable", data: ["bundle": current.toJSON()])
514
+ _ = self.implementation.setNextBundle(next: latest!.getId())
515
+ self.endBackGroundTask()
516
+ return
517
+ }
518
+ if latest!.isDeleted() {
519
+ print("\(self.implementation.TAG) Latest bundle already exists and will be deleted, download will overwrite it.")
520
+ let res = self.implementation.delete(id: latest!.getId(), removeInfo: true)
521
+ if !res {
522
+ print("\(self.implementation.TAG) Delete version deleted: \(latest!.toString())")
523
+ } else {
524
+ print("\(self.implementation.TAG) Failed to delete failed bundle: \(latest!.toString())")
531
525
  }
532
526
  }
527
+ }
533
528
 
534
- do {
535
- print("\(self.implementation.TAG) New bundle: \(latestVersionName) found. Current is: \(current.getVersionName()). Update will occur next time app moves to background.")
536
- let next = try self.implementation.download(url: downloadUrl, version: latestVersionName, sessionKey: sessionKey)
537
- if res.checksum != "" && next.getChecksum() != res.checksum {
538
- print("\(self.implementation.TAG) Error checksum", next.getChecksum(), res.checksum)
539
- self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
540
- let resDel = self.implementation.delete(id: next.getId())
541
- if !resDel {
542
- print("\(self.implementation.TAG) Delete failed, id \(next.getId()) doesn't exist")
543
- }
544
- self.EndBackGroundTask()
545
- return
529
+ do {
530
+ print("\(self.implementation.TAG) New bundle: \(latestVersionName) found. Current is: \(current.getVersionName()). Update will occur next time app moves to background.")
531
+ let next = try self.implementation.download(url: downloadUrl, version: latestVersionName, sessionKey: sessionKey)
532
+ if res.checksum != "" && next.getChecksum() != res.checksum {
533
+ print("\(self.implementation.TAG) Error checksum", next.getChecksum(), res.checksum)
534
+ self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
535
+ let resDel = self.implementation.delete(id: next.getId())
536
+ if !resDel {
537
+ print("\(self.implementation.TAG) Delete failed, id \(next.getId()) doesn't exist")
546
538
  }
547
- self.notifyListeners("updateAvailable", data: ["bundle": next.toJSON()])
548
- _ = self.implementation.setNextBundle(next: next.getId())
549
- } catch {
550
- print("\(self.implementation.TAG) Error downloading file", error.localizedDescription)
551
- let current: BundleInfo = self.implementation.getCurrentBundle()
552
- self.implementation.sendStats(action: "download_fail", versionName: current.getVersionName())
553
- self.notifyListeners("downloadFailed", data: ["version": latestVersionName])
554
- self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
539
+ self.endBackGroundTask()
540
+ return
555
541
  }
556
- } else {
557
- print("\(self.implementation.TAG) No need to update, \(current.getId()) is the latest bundle.")
542
+ self.notifyListeners("updateAvailable", data: ["bundle": next.toJSON()])
543
+ _ = self.implementation.setNextBundle(next: next.getId())
544
+ } catch {
545
+ print("\(self.implementation.TAG) Error downloading file", error.localizedDescription)
546
+ let current: BundleInfo = self.implementation.getCurrentBundle()
547
+ self.implementation.sendStats(action: "download_fail", versionName: current.getVersionName())
548
+ self.notifyListeners("downloadFailed", data: ["version": latestVersionName])
558
549
  self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
559
550
  }
551
+ } else {
552
+ print("\(self.implementation.TAG) No need to update, \(current.getId()) is the latest bundle.")
553
+ self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
560
554
  }
555
+ self.endBackGroundTask()
556
+ }
557
+ }
558
+
559
+ @objc func appMovedToForeground() {
560
+ if backgroundWork != nil && taskRunning {
561
+ backgroundWork!.cancel()
562
+ print("\(self.implementation.TAG) Background Timer Task canceled, Activity resumed before timer completes")
563
+ }
564
+ if self._isAutoUpdateEnabled() {
565
+ self.backgroundDownload()
561
566
  }
562
567
  self.checkAppReady()
563
- self.EndBackGroundTask()
564
568
  }
565
569
 
566
570
  @objc func appMovedToBackground() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "4.13.7",
3
+ "version": "4.14.1",
4
4
  "license": "LGPL-3.0-only",
5
5
  "description": "OTA update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",