@capgo/capacitor-updater 3.0.3

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.
@@ -0,0 +1,404 @@
1
+ package ee.forgr.capacitor_updater;
2
+
3
+ import android.app.Activity;
4
+ import android.app.Application;
5
+ import android.content.SharedPreferences;
6
+ import android.content.pm.PackageInfo;
7
+ import android.content.pm.PackageManager;
8
+ import android.os.Build;
9
+ import android.os.Bundle;
10
+ import android.util.Log;
11
+
12
+ import androidx.annotation.NonNull;
13
+ import androidx.annotation.Nullable;
14
+ import androidx.annotation.RequiresApi;
15
+
16
+ import com.getcapacitor.CapConfig;
17
+ import com.getcapacitor.JSArray;
18
+ import com.getcapacitor.JSObject;
19
+ import com.getcapacitor.Plugin;
20
+ import com.getcapacitor.PluginCall;
21
+ import com.getcapacitor.PluginMethod;
22
+ import com.getcapacitor.annotation.CapacitorPlugin;
23
+ import io.github.g00fy2.versioncompare.Version;
24
+
25
+ import org.json.JSONException;
26
+
27
+ import java.io.IOException;
28
+ import java.util.ArrayList;
29
+
30
+ @CapacitorPlugin(name = "CapacitorUpdater")
31
+ public class CapacitorUpdaterPlugin extends Plugin implements Application.ActivityLifecycleCallbacks {
32
+ private String TAG = "Capacitor-updater";
33
+ private CapacitorUpdater implementation;
34
+ private SharedPreferences prefs;
35
+ private SharedPreferences.Editor editor;
36
+ private static final String autoUpdateUrlDefault = "https://capgo.app/api/auto_update";
37
+ private static final String statsUrlDefault = "https://capgo.app/api/stats";
38
+ private String autoUpdateUrl = "";
39
+ private Version currentVersionNative;
40
+ private Boolean autoUpdate = false;
41
+ private Boolean resetWhenUpdate = true;
42
+
43
+
44
+ @Override
45
+ public void load() {
46
+ super.load();
47
+ this.prefs = this.getContext().getSharedPreferences("CapWebViewSettings", Activity.MODE_PRIVATE);
48
+ this.editor = prefs.edit();
49
+ try {
50
+ implementation = new CapacitorUpdater(this.getContext(), this);
51
+ PackageInfo pInfo = this.getContext().getPackageManager().getPackageInfo(this.getContext().getPackageName(), 0);
52
+ currentVersionNative = new Version(pInfo.versionName);
53
+ } catch (PackageManager.NameNotFoundException e) {
54
+ e.printStackTrace();
55
+ return;
56
+ } catch (Exception ex) {
57
+ Log.e(TAG, "Error get currentVersionNative", ex);
58
+ return;
59
+ }
60
+ CapConfig config = CapConfig.loadDefault(getActivity());
61
+ implementation.appId = config.getString("appId", "");
62
+ implementation.statsUrl = getConfig().getString("statsUrl", statsUrlDefault);
63
+ this.autoUpdateUrl = getConfig().getString("autoUpdateUrl", autoUpdateUrlDefault);
64
+ this.autoUpdate = getConfig().getBoolean("autoUpdate", false);
65
+ resetWhenUpdate = getConfig().getBoolean("resetWhenUpdate", true);
66
+ if (resetWhenUpdate) {
67
+ Version LatestVersionNative = new Version(prefs.getString("LatestVersionNative", ""));
68
+ try {
69
+ if (!LatestVersionNative.equals("") && currentVersionNative.getMajor() > LatestVersionNative.getMajor()) {
70
+ this._reset(false);
71
+ editor.putString("LatestVersionAutoUpdate", "");
72
+ editor.putString("LatestVersionNameAutoUpdate", "");
73
+ ArrayList<String> res = implementation.list();
74
+ for (int i = 0; i < res.size(); i++) {
75
+ try {
76
+ implementation.delete(res.get(i), "");
77
+ } catch (IOException e) {
78
+ e.printStackTrace();
79
+ }
80
+ }
81
+ }
82
+ editor.putString("LatestVersionNative", currentVersionNative.toString());
83
+ editor.commit();
84
+ } catch (Exception ex) {
85
+ Log.e("CapacitorUpdater", "Cannot get the current version" + ex.getMessage());
86
+ }
87
+ }
88
+ if (!autoUpdate || this.autoUpdateUrl.equals("")) return;
89
+ Application application = (Application) this.getContext().getApplicationContext();
90
+ application.registerActivityLifecycleCallbacks(this);
91
+ onActivityStarted(getActivity());
92
+ }
93
+
94
+ public void notifyDownload(int percent) {
95
+ JSObject ret = new JSObject();
96
+ ret.put("percent", percent);
97
+ notifyListeners("download", ret);
98
+ }
99
+
100
+ @PluginMethod
101
+ public void getId(PluginCall call) {
102
+ JSObject ret = new JSObject();
103
+ ret.put("id", implementation.deviceID);
104
+ call.resolve(ret);
105
+ }
106
+
107
+ @PluginMethod
108
+ public void download(PluginCall call) {
109
+ new Thread(new Runnable(){
110
+ @Override
111
+ public void run() {
112
+ String url = call.getString("url");
113
+ String res = implementation.download(url);
114
+ if (!res.equals("")) {
115
+ JSObject ret = new JSObject();
116
+ ret.put("version", res);
117
+ call.resolve(ret);
118
+ } else {
119
+ call.reject("download failed");
120
+ }
121
+ }
122
+ }).start();
123
+ }
124
+
125
+ private boolean _reload() {
126
+ String pathHot = implementation.getLastPathHot();
127
+ this.bridge.setServerBasePath(pathHot);
128
+ return true;
129
+ }
130
+
131
+ @PluginMethod
132
+ public void reload(PluginCall call) {
133
+ if (this._reload()) {
134
+ call.resolve();
135
+ } else {
136
+ call.reject("reload failed");
137
+ }
138
+ }
139
+
140
+ @PluginMethod
141
+ public void set(PluginCall call) {
142
+ String version = call.getString("version");
143
+ String versionName = call.getString("versionName", version);
144
+ Boolean res = implementation.set(version, versionName);
145
+
146
+ if (!res) {
147
+ call.reject("Update failed, version " + version + " doesn't exist");
148
+ } else {
149
+ this.reload(call);
150
+ }
151
+ }
152
+
153
+ @PluginMethod
154
+ public void delete(PluginCall call) {
155
+ String version = call.getString("version");
156
+ try {
157
+ Boolean res = implementation.delete(version, "");
158
+ if (res) {
159
+ call.resolve();
160
+ } else {
161
+ call.reject("Delete failed, version " + version + " doesn't exist");
162
+ }
163
+ } catch(IOException ex) {
164
+ Log.e("CapacitorUpdater", "An unexpected error occurred during deletion of folder. Message: " + ex.getMessage());
165
+ call.reject("An unexpected error occurred during deletion of folder.");
166
+ }
167
+ }
168
+
169
+ @PluginMethod
170
+ public void list(PluginCall call) {
171
+ ArrayList<String> res = implementation.list();
172
+ JSObject ret = new JSObject();
173
+ ret.put("versions", new JSArray(res));
174
+ call.resolve(ret);
175
+ }
176
+
177
+ private boolean _reset(Boolean toAutoUpdate) {
178
+ String version = prefs.getString("LatestVersionAutoUpdate", "");
179
+ String versionName = prefs.getString("LatestVersionNameAutoUpdate", "");
180
+ if (toAutoUpdate && !version.equals("") && !versionName.equals("")) {
181
+ Boolean res = implementation.set(version, versionName);
182
+ return res && this._reload();
183
+ }
184
+ implementation.reset();
185
+ String pathHot = implementation.getLastPathHot();
186
+ this.bridge.setServerAssetPath(pathHot);
187
+ return true;
188
+ }
189
+
190
+ @PluginMethod
191
+ public void reset(PluginCall call) {
192
+ Boolean toAutoUpdate = call.getBoolean("toAutoUpdate");
193
+ if (this._reset(toAutoUpdate)) {
194
+ call.resolve();
195
+ return;
196
+ }
197
+ call.reject("✨ Capacitor-updater: Reset failed");
198
+ }
199
+
200
+ @PluginMethod
201
+ public void versionName(PluginCall call) {
202
+ String name = implementation.getVersionName();
203
+ JSObject ret = new JSObject();
204
+ ret.put("versionName", name);
205
+ call.resolve(ret);
206
+ }
207
+
208
+ @PluginMethod
209
+ public void current(PluginCall call) {
210
+ String pathHot = implementation.getLastPathHot();
211
+ JSObject ret = new JSObject();
212
+ String current = pathHot.length() >= 10 ? pathHot.substring(pathHot.length() - 10) : "builtin";
213
+ ret.put("current", current);
214
+ ret.put("currentNative", currentVersionNative);
215
+ call.resolve(ret);
216
+ }
217
+
218
+ @PluginMethod
219
+ public void notifyAppReady(PluginCall call) {
220
+ editor.putBoolean("notifyAppReady", true);
221
+ editor.commit();
222
+ call.resolve();
223
+ }
224
+
225
+ @PluginMethod
226
+ public void delayUpdate(PluginCall call) {
227
+ editor.putBoolean("delayUpdate", true);
228
+ editor.commit();
229
+ call.resolve();
230
+ }
231
+
232
+ @PluginMethod
233
+ public void cancelDelay(PluginCall call) {
234
+ editor.putBoolean("delayUpdate", false);
235
+ editor.commit();
236
+ call.resolve();
237
+ }
238
+
239
+ @Override
240
+ public void onActivityStarted(@NonNull Activity activity) {
241
+ // disableRevert disableBreaking
242
+ String currentVersionNative = "";
243
+ try {
244
+ PackageInfo pInfo = this.getContext().getPackageManager().getPackageInfo(this.getContext().getPackageName(), 0);
245
+ currentVersionNative = pInfo.versionName;
246
+ } catch (Exception ex) {
247
+ Log.e(TAG, "Error get stats", ex);
248
+ return;
249
+ }
250
+ Log.i(TAG, "Check for update in the server");
251
+ if (autoUpdateUrl.equals("")) return;
252
+ String finalCurrentVersionNative = currentVersionNative;
253
+ new Thread(new Runnable(){
254
+ @Override
255
+ public void run() {
256
+ implementation.getLatest(autoUpdateUrl, (res) -> {
257
+ try {
258
+ String currentVersion = implementation.getVersionName();
259
+ String newVersion = (String) res.get("version");
260
+ JSObject ret = new JSObject();
261
+ ret.put("newVersion", newVersion);
262
+ if (res.has("message")) {
263
+ Log.i(TAG, "Capacitor-updater: " + res.get("message"));
264
+ if (res.getBoolean("major")) {
265
+ notifyListeners("majorAvailable", ret);
266
+ }
267
+ return;
268
+ }
269
+ String failingVersion = prefs.getString("failingVersion", "");
270
+ if (!newVersion.equals("") && !newVersion.equals(failingVersion)) {
271
+ new Thread(new Runnable(){
272
+ @Override
273
+ public void run() {
274
+ try {
275
+ String dl = implementation.download((String) res.get("url"));
276
+ if (dl.equals("")) {
277
+ Log.i(TAG, "Download version: " + newVersion + " failed");
278
+ return;
279
+ }
280
+ Log.i(TAG, "New version: " + newVersion + " found. Current is " + (currentVersion.equals("") ? "builtin" : currentVersion) + ", next backgrounding will trigger update");
281
+ editor.putString("nextVersion", dl);
282
+ editor.putString("nextVersionName", (String) res.get("version"));
283
+ editor.commit();
284
+ notifyListeners("updateAvailable", ret);
285
+ } catch (JSONException e) {
286
+ e.printStackTrace();
287
+ }
288
+ }
289
+ }).start();
290
+ } else {
291
+ Log.i(TAG, "No need to update, " + currentVersion + " is the latest");
292
+ }
293
+ } catch (JSONException e) {
294
+ e.printStackTrace();
295
+ }
296
+ });
297
+ }
298
+ }).start();
299
+ }
300
+
301
+ @Override
302
+ public void onActivityStopped(@NonNull Activity activity) {
303
+ String pathHot = implementation.getLastPathHot();
304
+ Log.i(TAG, "Check for waiting update");
305
+ String nextVersion = prefs.getString("nextVersion", "");
306
+ Boolean delayUpdate = prefs.getBoolean("delayUpdate", false);
307
+ editor.putBoolean("delayUpdate", false);
308
+ editor.commit();
309
+ if (delayUpdate) {
310
+ Log.i(TAG, "Update delayed to next backgrounding");
311
+ return;
312
+ }
313
+ String nextVersionName = prefs.getString("nextVersionName", "");
314
+ String pastVersion = prefs.getString("pastVersion", "");
315
+ String pastVersionName = prefs.getString("pastVersionName", "");
316
+ Boolean notifyAppReady = prefs.getBoolean("notifyAppReady", false);
317
+ String tmpCurVersion = implementation.getLastPathHot();
318
+ String curVersion = tmpCurVersion.substring(tmpCurVersion.lastIndexOf('/') +1);
319
+ String curVersionName = implementation.getVersionName();
320
+ if (!nextVersion.equals("") && !nextVersionName.equals("")) {
321
+ Boolean res = implementation.set(nextVersion, nextVersionName);
322
+ if (res && this._reload()) {
323
+ Log.i(TAG, "Auto update to version: " + nextVersionName);
324
+ editor.putString("LatestVersionAutoUpdate", nextVersion);
325
+ editor.putString("LatestVersionNameAutoUpdate", nextVersionName);
326
+ editor.putString("nextVersion", "");
327
+ editor.putString("nextVersionName", "");
328
+ editor.putString("pastVersion", curVersion);
329
+ editor.putString("pastVersionName", curVersionName);
330
+ editor.putBoolean("notifyAppReady", false);
331
+ editor.commit();
332
+ } else {
333
+ Log.i(TAG, "Auto update to version: " + nextVersionName + "Failed");
334
+ }
335
+ } else if (!notifyAppReady && !pathHot.equals("public")) {
336
+ Log.i(TAG, "notifyAppReady never trigger");
337
+ Log.i(TAG, "Version: " + curVersionName + ", is considered broken");
338
+ Log.i(TAG, "Will downgraded to version: " + (pastVersionName.equals("") ? "builtin" : pastVersionName) + " for next start");
339
+ Log.i(TAG, "Don't forget to trigger 'notifyAppReady()' in js code to validate a version.");
340
+ if (!pastVersion.equals("") && !pastVersionName.equals("")) {
341
+ Boolean res = implementation.set(pastVersion, pastVersionName);
342
+ if (res && this._reload()) {
343
+ Log.i(TAG, "Revert to version: " + (pastVersionName.equals("") ? "builtin" : pastVersionName));
344
+ editor.putString("LatestVersionAutoUpdate", pastVersion);
345
+ editor.putString("LatestVersionNameAutoUpdate", pastVersionName);
346
+ editor.putString("pastVersion", "");
347
+ editor.putString("pastVersionName", "");
348
+ editor.commit();
349
+ } else {
350
+ Log.i(TAG, "Revert to version: " + (pastVersionName.equals("") ? "builtin" : pastVersionName) + "Failed");
351
+ }
352
+ } else {
353
+ if (this._reset(false)) {
354
+ editor.putString("LatestVersionAutoUpdate", "");
355
+ editor.putString("LatestVersionNameAutoUpdate", "");
356
+ Log.i(TAG, "Auto reset done");
357
+ }
358
+ }
359
+ editor.putString("failingVersion", curVersionName);
360
+ editor.commit();
361
+ try {
362
+ Boolean res = implementation.delete(curVersion, curVersionName);
363
+ if (res) {
364
+ Log.i(TAG, "Delete failing version: " + curVersionName);
365
+ }
366
+ } catch (IOException e) {
367
+ e.printStackTrace();
368
+ }
369
+ } else if (!pastVersion.equals("")) {
370
+ Log.i(TAG, "Validated version: " + curVersionName);
371
+ try {
372
+ Boolean res = implementation.delete(pastVersion, pastVersionName);
373
+ if (res) {
374
+ Log.i(TAG, "Delete past version: " + pastVersionName);
375
+ }
376
+ } catch (IOException e) {
377
+ e.printStackTrace();
378
+ }
379
+ editor.putString("pastVersion", "");
380
+ editor.putString("pastVersionName", "");
381
+ editor.commit();
382
+ }
383
+ }
384
+
385
+ // not use but necessary here to remove warnings
386
+ @Override
387
+ public void onActivityResumed(@NonNull Activity activity) {
388
+ }
389
+
390
+ @Override
391
+ public void onActivityPaused(@NonNull Activity activity) {
392
+ }
393
+ @Override
394
+ public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
395
+ }
396
+
397
+ @Override
398
+ public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
399
+ }
400
+
401
+ @Override
402
+ public void onActivityDestroyed(@NonNull Activity activity) {
403
+ }
404
+ }
File without changes