@capgo/capacitor-updater 5.0.0-alpha.0 → 7.0.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/CapgoCapacitorUpdater.podspec +1 -1
- package/LICENCE +373 -661
- package/README.md +339 -75
- package/android/build.gradle +13 -12
- package/android/src/main/AndroidManifest.xml +4 -2
- package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +205 -121
- package/android/src/main/java/ee/forgr/capacitor_updater/BundleStatus.java +32 -24
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdater.java +1041 -441
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +1217 -536
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +153 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/DelayCondition.java +62 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/DelayUntilNext.java +14 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +126 -0
- package/dist/docs.json +727 -171
- package/dist/esm/definitions.d.ts +234 -45
- package/dist/esm/definitions.js +5 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +9 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +12 -6
- package/dist/esm/web.js +64 -20
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +70 -23
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +70 -23
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/BundleInfo.swift +38 -19
- package/ios/Plugin/BundleStatus.swift +11 -4
- package/ios/Plugin/CapacitorUpdater.swift +520 -192
- package/ios/Plugin/CapacitorUpdaterPlugin.m +8 -1
- package/ios/Plugin/CapacitorUpdaterPlugin.swift +447 -190
- package/ios/Plugin/CryptoCipher.swift +240 -0
- package/ios/Plugin/DelayCondition.swift +74 -0
- package/ios/Plugin/DelayUntilNext.swift +30 -0
- package/ios/Plugin/UserDefaultsExtension.swift +48 -0
- package/package.json +26 -20
- package/ios/Plugin/ObjectPreferences.swift +0 -97
|
@@ -1,18 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
package ee.forgr.capacitor_updater;
|
|
2
8
|
|
|
3
9
|
import android.app.Activity;
|
|
10
|
+
import android.app.ActivityManager;
|
|
4
11
|
import android.app.Application;
|
|
12
|
+
import android.content.Context;
|
|
5
13
|
import android.content.SharedPreferences;
|
|
6
14
|
import android.content.pm.PackageInfo;
|
|
7
15
|
import android.content.pm.PackageManager;
|
|
8
16
|
import android.os.Build;
|
|
9
17
|
import android.os.Bundle;
|
|
10
|
-
import android.provider.Settings;
|
|
11
18
|
import android.util.Log;
|
|
12
|
-
|
|
13
19
|
import androidx.annotation.NonNull;
|
|
14
20
|
import androidx.annotation.Nullable;
|
|
15
|
-
|
|
16
21
|
import com.android.volley.toolbox.Volley;
|
|
17
22
|
import com.getcapacitor.CapConfig;
|
|
18
23
|
import com.getcapacitor.JSArray;
|
|
@@ -22,605 +27,1281 @@ import com.getcapacitor.PluginCall;
|
|
|
22
27
|
import com.getcapacitor.PluginMethod;
|
|
23
28
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
24
29
|
import com.getcapacitor.plugin.WebView;
|
|
25
|
-
|
|
30
|
+
import com.google.gson.Gson;
|
|
31
|
+
import com.google.gson.reflect.TypeToken;
|
|
26
32
|
import io.github.g00fy2.versioncompare.Version;
|
|
27
|
-
|
|
28
|
-
import org.json.JSONException;
|
|
29
|
-
|
|
30
33
|
import java.io.IOException;
|
|
34
|
+
import java.lang.reflect.Type;
|
|
35
|
+
import java.net.MalformedURLException;
|
|
36
|
+
import java.net.URL;
|
|
37
|
+
import java.text.SimpleDateFormat;
|
|
38
|
+
import java.util.ArrayList;
|
|
39
|
+
import java.util.Date;
|
|
40
|
+
import java.util.Iterator;
|
|
31
41
|
import java.util.List;
|
|
42
|
+
import java.util.UUID;
|
|
43
|
+
import org.json.JSONException;
|
|
32
44
|
|
|
33
45
|
@CapacitorPlugin(name = "CapacitorUpdater")
|
|
34
|
-
public class CapacitorUpdaterPlugin
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
this.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
46
|
+
public class CapacitorUpdaterPlugin
|
|
47
|
+
extends Plugin
|
|
48
|
+
implements Application.ActivityLifecycleCallbacks {
|
|
49
|
+
|
|
50
|
+
private static final String updateUrlDefault =
|
|
51
|
+
"https://api.capgo.app/updates";
|
|
52
|
+
private static final String statsUrlDefault = "https://api.capgo.app/stats";
|
|
53
|
+
private static final String defaultPrivateKey =
|
|
54
|
+
"-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA4pW9olT0FBXXivRCzd3xcImlWZrqkwcF2xTkX/FwXmj9eh9H\nkBLrsQmfsC+PJisRXIOGq6a0z3bsGq6jBpp3/Jr9jiaW5VuPGaKeMaZZBRvi/N5f\nIMG3hZXSOcy0IYg+E1Q7RkYO1xq5GLHseqG+PXvJsNe4R8R/Bmd/ngq0xh/cvcrH\nHpXwO0Aj9tfprlb+rHaVV79EkVRWYPidOLnK1n0EFHFJ1d/MyDIp10TEGm2xHpf/\nBrlb1an8wXEuzoC0DgYaczgTjovwR+ewSGhSHJliQdM0Qa3o1iN87DldWtydImMs\nPjJ3DUwpsjAMRe5X8Et4+udFW2ciYnQo9H0CkwIDAQABAoIBAQCtjlMV/4qBxAU4\nu0ZcWA9yywwraX0aJ3v1xrfzQYV322Wk4Ea5dbSxA5UcqCE29DA1M824t1Wxv/6z\npWbcTP9xLuresnJMtmgTE7umfiubvTONy2sENT20hgDkIwcq1CfwOEm61zjQzPhQ\nkSB5AmEsyR/BZEsUNc+ygR6AWOUFB7tj4yMc32LOTWSbE/znnF2BkmlmnQykomG1\n2oVqM3lUFP7+m8ux1O7scO6IMts+Z/eFXjWfxpbebUSvSIR83GXPQZ34S/c0ehOg\nyHdmCSOel1r3VvInMe+30j54Jr+Ml/7Ee6axiwyE2e/bd85MsK9sVdp0OtelXaqA\nOZZqWvN5AoGBAP2Hn3lSq+a8GsDH726mHJw60xM0LPbVJTYbXsmQkg1tl3NKJTMM\nQqz41+5uys+phEgLHI9gVJ0r+HaGHXnJ4zewlFjsudstb/0nfctUvTqnhEhfNo9I\ny4kufVKPRF3sMEeo7CDVJs4GNBLycEyIBy6Mbv0VcO7VaZqggRwu4no9AoGBAOTK\n6NWYs1BWlkua2wmxexGOzehNGedInp0wGr2l4FDayWjkZLqvB+nNXUQ63NdHlSs4\nWB2Z1kQXZxVaI2tPYexGUKXEo2uFob63uflbuE029ovDXIIPFTPtGNdNXwhHT5a+\nPhmy3sMc+s2BSNM5qaNmfxQxhdd6gRU6oikE+c0PAoGAMn3cKNFqIt27hkFLUgIL\nGKIuf1iYy9/PNWNmEUaVj88PpopRtkTu0nwMpROzmH/uNFriKTvKHjMvnItBO4wV\nkHW+VadvrFL0Rrqituf9d7z8/1zXBNo+juePVe3qc7oiM2NVA4Tv4YAixtM5wkQl\nCgQ15nlqsGYYTg9BJ1e/CxECgYEAjEYPzO2reuUrjr0p8F59ev1YJ0YmTJRMk0ks\nC/yIdGo/tGzbiU3JB0LfHPcN8Xu07GPGOpfYM7U5gXDbaG6qNgfCaHAQVdr/mQPi\nJQ1kCQtay8QCkscWk9iZM1//lP7LwDtxraXqSCwbZSYP9VlUNZeg8EuQqNU2EUL6\nqzWexmcCgYEA0prUGNBacraTYEknB1CsbP36UPWsqFWOvevlz+uEC5JPxPuW5ZHh\nSQN7xl6+PHyjPBM7ttwPKyhgLOVTb3K7ex/PXnudojMUK5fh7vYfChVTSlx2p6r0\nDi58PdD+node08cJH+ie0Yphp7m+D4+R9XD0v0nEvnu4BtAW6DrJasw=\n-----END RSA PRIVATE KEY-----\n";
|
|
55
|
+
private static final String channelUrlDefault =
|
|
56
|
+
"https://api.capgo.app/channel_self";
|
|
57
|
+
|
|
58
|
+
private final String PLUGIN_VERSION = "7.0.0";
|
|
59
|
+
private static final String DELAY_CONDITION_PREFERENCES = "";
|
|
60
|
+
|
|
61
|
+
private SharedPreferences.Editor editor;
|
|
62
|
+
private SharedPreferences prefs;
|
|
63
|
+
private CapacitorUpdater implementation;
|
|
64
|
+
|
|
65
|
+
private Integer appReadyTimeout = 10000;
|
|
66
|
+
private Integer counterActivityCreate = 0;
|
|
67
|
+
private Boolean autoDeleteFailed = true;
|
|
68
|
+
private Boolean autoDeletePrevious = true;
|
|
69
|
+
private Boolean autoUpdate = false;
|
|
70
|
+
private String updateUrl = "";
|
|
71
|
+
private Version currentVersionNative;
|
|
72
|
+
private Boolean resetWhenUpdate = true;
|
|
73
|
+
private Thread backgroundTask;
|
|
74
|
+
private Boolean taskRunning = false;
|
|
75
|
+
|
|
76
|
+
private Boolean isPreviousMainActivity = true;
|
|
77
|
+
|
|
78
|
+
private volatile Thread appReadyCheck;
|
|
79
|
+
|
|
80
|
+
@Override
|
|
81
|
+
public void load() {
|
|
82
|
+
super.load();
|
|
83
|
+
this.prefs =
|
|
84
|
+
this.getContext()
|
|
85
|
+
.getSharedPreferences(
|
|
86
|
+
WebView.WEBVIEW_PREFS_NAME,
|
|
87
|
+
Activity.MODE_PRIVATE
|
|
88
|
+
);
|
|
89
|
+
this.editor = this.prefs.edit();
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
this.implementation =
|
|
93
|
+
new CapacitorUpdater() {
|
|
94
|
+
@Override
|
|
95
|
+
public void notifyDownload(final String id, final int percent) {
|
|
96
|
+
CapacitorUpdaterPlugin.this.notifyDownload(id, percent);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Override
|
|
100
|
+
public void notifyListeners(final String id, final JSObject res) {
|
|
101
|
+
CapacitorUpdaterPlugin.this.notifyListeners(id, res);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
final PackageInfo pInfo =
|
|
105
|
+
this.getContext()
|
|
106
|
+
.getPackageManager()
|
|
107
|
+
.getPackageInfo(this.getContext().getPackageName(), 0);
|
|
108
|
+
this.implementation.activity = this.getActivity();
|
|
109
|
+
this.implementation.versionBuild =
|
|
110
|
+
this.getConfig().getString("version", pInfo.versionName);
|
|
111
|
+
this.implementation.PLUGIN_VERSION = this.PLUGIN_VERSION;
|
|
112
|
+
this.implementation.versionCode = Integer.toString(pInfo.versionCode);
|
|
113
|
+
this.implementation.requestQueue =
|
|
114
|
+
Volley.newRequestQueue(this.getContext());
|
|
115
|
+
this.currentVersionNative =
|
|
116
|
+
new Version(this.getConfig().getString("version", pInfo.versionName));
|
|
117
|
+
} catch (final PackageManager.NameNotFoundException e) {
|
|
118
|
+
Log.e(CapacitorUpdater.TAG, "Error instantiating implementation", e);
|
|
119
|
+
return;
|
|
120
|
+
} catch (final Exception e) {
|
|
121
|
+
Log.e(
|
|
122
|
+
CapacitorUpdater.TAG,
|
|
123
|
+
"Error getting current native app version",
|
|
124
|
+
e
|
|
125
|
+
);
|
|
126
|
+
return;
|
|
102
127
|
}
|
|
103
128
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
129
|
+
final CapConfig config = CapConfig.loadDefault(this.getActivity());
|
|
130
|
+
this.implementation.appId = config.getString("appId", "");
|
|
131
|
+
this.implementation.privateKey =
|
|
132
|
+
this.getConfig().getString("privateKey", defaultPrivateKey);
|
|
133
|
+
this.implementation.statsUrl =
|
|
134
|
+
this.getConfig().getString("statsUrl", statsUrlDefault);
|
|
135
|
+
this.implementation.channelUrl =
|
|
136
|
+
this.getConfig().getString("channelUrl", channelUrlDefault);
|
|
137
|
+
this.implementation.documentsDir = this.getContext().getFilesDir();
|
|
138
|
+
this.implementation.prefs = this.prefs;
|
|
139
|
+
this.implementation.editor = this.editor;
|
|
140
|
+
this.implementation.versionOs = Build.VERSION.RELEASE;
|
|
141
|
+
this.implementation.deviceID =
|
|
142
|
+
this.prefs.getString("appUUID", UUID.randomUUID().toString());
|
|
143
|
+
this.editor.putString("appUUID", this.implementation.deviceID);
|
|
144
|
+
Log.i(
|
|
145
|
+
CapacitorUpdater.TAG,
|
|
146
|
+
"init for device " + this.implementation.deviceID
|
|
147
|
+
);
|
|
148
|
+
Log.i(
|
|
149
|
+
CapacitorUpdater.TAG,
|
|
150
|
+
"version native " + this.currentVersionNative.getOriginalString()
|
|
151
|
+
);
|
|
152
|
+
this.autoDeleteFailed =
|
|
153
|
+
this.getConfig().getBoolean("autoDeleteFailed", true);
|
|
154
|
+
this.autoDeletePrevious =
|
|
155
|
+
this.getConfig().getBoolean("autoDeletePrevious", true);
|
|
156
|
+
this.updateUrl = this.getConfig().getString("updateUrl", updateUrlDefault);
|
|
157
|
+
this.autoUpdate = this.getConfig().getBoolean("autoUpdate", true);
|
|
158
|
+
this.appReadyTimeout = this.getConfig().getInt("appReadyTimeout", 10000);
|
|
159
|
+
this.resetWhenUpdate = this.getConfig().getBoolean("resetWhenUpdate", true);
|
|
160
|
+
|
|
161
|
+
if (this.resetWhenUpdate) {
|
|
162
|
+
this.cleanupObsoleteVersions();
|
|
163
|
+
}
|
|
164
|
+
final Application application = (Application) this.getContext()
|
|
165
|
+
.getApplicationContext();
|
|
166
|
+
application.registerActivityLifecycleCallbacks(this);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private void cleanupObsoleteVersions() {
|
|
170
|
+
try {
|
|
171
|
+
final Version previous = new Version(
|
|
172
|
+
this.prefs.getString("LatestVersionNative", "")
|
|
173
|
+
);
|
|
174
|
+
try {
|
|
175
|
+
if (
|
|
176
|
+
!"".equals(previous.getOriginalString()) &&
|
|
177
|
+
!this.currentVersionNative.getOriginalString()
|
|
178
|
+
.equals(previous.getOriginalString())
|
|
179
|
+
) {
|
|
180
|
+
Log.i(
|
|
181
|
+
CapacitorUpdater.TAG,
|
|
182
|
+
"New native version detected: " + this.currentVersionNative
|
|
183
|
+
);
|
|
184
|
+
this.implementation.reset(true);
|
|
185
|
+
final List<BundleInfo> installed = this.implementation.list();
|
|
186
|
+
for (final BundleInfo bundle : installed) {
|
|
107
187
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
for (final BundleInfo bundle: installed) {
|
|
114
|
-
try {
|
|
115
|
-
Log.i(CapacitorUpdater.TAG, "Deleting obsolete bundle: " + bundle.getId());
|
|
116
|
-
this.implementation.delete(bundle.getId());
|
|
117
|
-
} catch (final Exception e) {
|
|
118
|
-
Log.e(CapacitorUpdater.TAG, "Failed to delete: " + bundle.getId(), e);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
188
|
+
Log.i(
|
|
189
|
+
CapacitorUpdater.TAG,
|
|
190
|
+
"Deleting obsolete bundle: " + bundle.getId()
|
|
191
|
+
);
|
|
192
|
+
this.implementation.delete(bundle.getId());
|
|
122
193
|
} catch (final Exception e) {
|
|
123
|
-
|
|
194
|
+
Log.e(
|
|
195
|
+
CapacitorUpdater.TAG,
|
|
196
|
+
"Failed to delete: " + bundle.getId(),
|
|
197
|
+
e
|
|
198
|
+
);
|
|
124
199
|
}
|
|
125
|
-
|
|
126
|
-
Log.e(CapacitorUpdater.TAG, "Error calculating previous native version", e);
|
|
200
|
+
}
|
|
127
201
|
}
|
|
128
|
-
|
|
129
|
-
|
|
202
|
+
} catch (final Exception e) {
|
|
203
|
+
Log.e(
|
|
204
|
+
CapacitorUpdater.TAG,
|
|
205
|
+
"Could not determine the current version",
|
|
206
|
+
e
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
} catch (final Exception e) {
|
|
210
|
+
Log.e(
|
|
211
|
+
CapacitorUpdater.TAG,
|
|
212
|
+
"Error calculating previous native version",
|
|
213
|
+
e
|
|
214
|
+
);
|
|
130
215
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
216
|
+
this.editor.putString(
|
|
217
|
+
"LatestVersionNative",
|
|
218
|
+
this.currentVersionNative.toString()
|
|
219
|
+
);
|
|
220
|
+
this.editor.commit();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
public void notifyDownload(final String id, final int percent) {
|
|
224
|
+
try {
|
|
225
|
+
final JSObject ret = new JSObject();
|
|
226
|
+
ret.put("percent", percent);
|
|
227
|
+
final BundleInfo bundleInfo = this.implementation.getBundleInfo(id);
|
|
228
|
+
ret.put("bundle", bundleInfo.toJSON());
|
|
229
|
+
this.notifyListeners("download", ret);
|
|
230
|
+
if (percent == 100) {
|
|
231
|
+
this.notifyListeners("downloadComplete", bundleInfo.toJSON());
|
|
232
|
+
this.implementation.sendStats(
|
|
233
|
+
"download_complete",
|
|
234
|
+
bundleInfo.getVersionName()
|
|
235
|
+
);
|
|
236
|
+
} else if (percent % 10 == 0) {
|
|
237
|
+
this.implementation.sendStats(
|
|
238
|
+
"download_" + percent,
|
|
239
|
+
bundleInfo.getVersionName()
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
} catch (final Exception e) {
|
|
243
|
+
Log.e(CapacitorUpdater.TAG, "Could not notify listeners", e);
|
|
145
244
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@PluginMethod
|
|
248
|
+
public void getDeviceId(final PluginCall call) {
|
|
249
|
+
try {
|
|
250
|
+
final JSObject ret = new JSObject();
|
|
251
|
+
ret.put("deviceId", this.implementation.deviceID);
|
|
252
|
+
call.resolve(ret);
|
|
253
|
+
} catch (final Exception e) {
|
|
254
|
+
Log.e(CapacitorUpdater.TAG, "Could not get device id", e);
|
|
255
|
+
call.reject("Could not get device id", e);
|
|
158
256
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
call.reject("Could not get plugin version", e);
|
|
169
|
-
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@PluginMethod
|
|
260
|
+
public void setCustomId(final PluginCall call) {
|
|
261
|
+
final String customId = call.getString("customId");
|
|
262
|
+
if (customId == null) {
|
|
263
|
+
Log.e(CapacitorUpdater.TAG, "setCustomId called without customId");
|
|
264
|
+
call.reject("setCustomId called without customId");
|
|
265
|
+
return;
|
|
170
266
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
267
|
+
this.implementation.customId = customId;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
@PluginMethod
|
|
271
|
+
public void getPluginVersion(final PluginCall call) {
|
|
272
|
+
try {
|
|
273
|
+
final JSObject ret = new JSObject();
|
|
274
|
+
ret.put("version", this.PLUGIN_VERSION);
|
|
275
|
+
call.resolve(ret);
|
|
276
|
+
} catch (final Exception e) {
|
|
277
|
+
Log.e(CapacitorUpdater.TAG, "Could not get plugin version", e);
|
|
278
|
+
call.reject("Could not get plugin version", e);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@PluginMethod
|
|
283
|
+
public void setChannel(final PluginCall call) {
|
|
284
|
+
final String channel = call.getString("channel");
|
|
285
|
+
if (channel == null) {
|
|
286
|
+
Log.e(CapacitorUpdater.TAG, "setChannel called without channel");
|
|
287
|
+
call.reject("setChannel called without channel");
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
Log.i(CapacitorUpdater.TAG, "setChannel " + channel);
|
|
292
|
+
new Thread(
|
|
293
|
+
new Runnable() {
|
|
294
|
+
@Override
|
|
295
|
+
public void run() {
|
|
296
|
+
CapacitorUpdaterPlugin.this.implementation.setChannel(
|
|
297
|
+
channel,
|
|
298
|
+
res -> {
|
|
299
|
+
if (res.has("error")) {
|
|
300
|
+
call.reject(res.getString("error"));
|
|
301
|
+
} else {
|
|
302
|
+
call.resolve(res);
|
|
303
|
+
}
|
|
193
304
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
Log.e(CapacitorUpdater.TAG, "Failed to download " + url, e);
|
|
197
|
-
call.reject("Failed to download " + url, e);
|
|
305
|
+
);
|
|
306
|
+
}
|
|
198
307
|
}
|
|
308
|
+
)
|
|
309
|
+
.start();
|
|
310
|
+
} catch (final Exception e) {
|
|
311
|
+
Log.e(CapacitorUpdater.TAG, "Failed to setChannel: " + channel, e);
|
|
312
|
+
call.reject("Failed to setChannel: " + channel, e);
|
|
199
313
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@PluginMethod
|
|
317
|
+
public void getChannel(final PluginCall call) {
|
|
318
|
+
try {
|
|
319
|
+
Log.i(CapacitorUpdater.TAG, "getChannel");
|
|
320
|
+
new Thread(
|
|
321
|
+
new Runnable() {
|
|
322
|
+
@Override
|
|
323
|
+
public void run() {
|
|
324
|
+
CapacitorUpdaterPlugin.this.implementation.getChannel(res -> {
|
|
325
|
+
if (res.has("error")) {
|
|
326
|
+
call.reject(res.getString("error"));
|
|
327
|
+
} else {
|
|
328
|
+
call.resolve(res);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
208
332
|
}
|
|
209
|
-
|
|
210
|
-
|
|
333
|
+
)
|
|
334
|
+
.start();
|
|
335
|
+
} catch (final Exception e) {
|
|
336
|
+
Log.e(CapacitorUpdater.TAG, "Failed to getChannel", e);
|
|
337
|
+
call.reject("Failed to getChannel", e);
|
|
211
338
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@PluginMethod
|
|
342
|
+
public void download(final PluginCall call) {
|
|
343
|
+
final String url = call.getString("url");
|
|
344
|
+
final String version = call.getString("version");
|
|
345
|
+
final String sessionKey = call.getString("sessionKey", "");
|
|
346
|
+
final String checksum = call.getString("checksum", "");
|
|
347
|
+
if (url == null) {
|
|
348
|
+
Log.e(CapacitorUpdater.TAG, "Download called without url");
|
|
349
|
+
call.reject("Download called without url");
|
|
350
|
+
return;
|
|
225
351
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
Log.i(CapacitorUpdater.TAG, "Setting next active id " + id);
|
|
233
|
-
if (!this.implementation.setNextVersion(id)) {
|
|
234
|
-
call.reject("Set next id failed. Bundle " + id + " does not exist.");
|
|
235
|
-
} else {
|
|
236
|
-
call.resolve(this.implementation.getBundleInfo(id).toJSON());
|
|
237
|
-
}
|
|
238
|
-
} catch (final Exception e) {
|
|
239
|
-
Log.e(CapacitorUpdater.TAG, "Could not set next id " + id, e);
|
|
240
|
-
call.reject("Could not set next id " + id, e);
|
|
241
|
-
}
|
|
352
|
+
if (version == null) {
|
|
353
|
+
Log.e(CapacitorUpdater.TAG, "Download called without version");
|
|
354
|
+
call.reject("Download called without version");
|
|
355
|
+
return;
|
|
242
356
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
357
|
+
try {
|
|
358
|
+
Log.i(CapacitorUpdater.TAG, "Downloading " + url);
|
|
359
|
+
new Thread(
|
|
360
|
+
new Runnable() {
|
|
361
|
+
@Override
|
|
362
|
+
public void run() {
|
|
363
|
+
try {
|
|
364
|
+
final BundleInfo downloaded =
|
|
365
|
+
CapacitorUpdaterPlugin.this.implementation.download(
|
|
366
|
+
url,
|
|
367
|
+
version,
|
|
368
|
+
sessionKey,
|
|
369
|
+
checksum
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
call.resolve(downloaded.toJSON());
|
|
373
|
+
} catch (final IOException e) {
|
|
374
|
+
Log.e(CapacitorUpdater.TAG, "Failed to download from: " + url, e);
|
|
375
|
+
call.reject("Failed to download from: " + url, e);
|
|
376
|
+
final JSObject ret = new JSObject();
|
|
377
|
+
ret.put("version", version);
|
|
378
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
379
|
+
"downloadFailed",
|
|
380
|
+
ret
|
|
381
|
+
);
|
|
382
|
+
final BundleInfo current =
|
|
383
|
+
CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
384
|
+
CapacitorUpdaterPlugin.this.implementation.sendStats(
|
|
385
|
+
"download_fail",
|
|
386
|
+
current.getVersionName()
|
|
387
|
+
);
|
|
256
388
|
}
|
|
257
|
-
|
|
258
|
-
Log.e(CapacitorUpdater.TAG, "Could not set id " + id, e);
|
|
259
|
-
call.reject("Could not set id " + id, e);
|
|
389
|
+
}
|
|
260
390
|
}
|
|
391
|
+
)
|
|
392
|
+
.start();
|
|
393
|
+
} catch (final Exception e) {
|
|
394
|
+
Log.e(CapacitorUpdater.TAG, "Failed to download from: " + url, e);
|
|
395
|
+
call.reject("Failed to download from: " + url, e);
|
|
396
|
+
final JSObject ret = new JSObject();
|
|
397
|
+
ret.put("version", version);
|
|
398
|
+
CapacitorUpdaterPlugin.this.notifyListeners("downloadFailed", ret);
|
|
399
|
+
final BundleInfo current =
|
|
400
|
+
CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
401
|
+
CapacitorUpdaterPlugin.this.implementation.sendStats(
|
|
402
|
+
"download_fail",
|
|
403
|
+
current.getVersionName()
|
|
404
|
+
);
|
|
261
405
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
} else {
|
|
272
|
-
call.reject("Delete failed, id " + id + " does not exist");
|
|
273
|
-
}
|
|
274
|
-
} catch(final Exception e) {
|
|
275
|
-
Log.e(CapacitorUpdater.TAG, "Could not delete id " + id, e);
|
|
276
|
-
call.reject("Could not delete id " + id, e);
|
|
277
|
-
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
private boolean _reload() {
|
|
409
|
+
final String path = this.implementation.getCurrentBundlePath();
|
|
410
|
+
Log.i(CapacitorUpdater.TAG, "Reloading: " + path);
|
|
411
|
+
if (this.implementation.isUsingBuiltin()) {
|
|
412
|
+
this.bridge.setServerAssetPath(path);
|
|
413
|
+
} else {
|
|
414
|
+
this.bridge.setServerBasePath(path);
|
|
278
415
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
416
|
+
this.checkAppReady();
|
|
417
|
+
this.notifyListeners("appReloaded", new JSObject());
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
@PluginMethod
|
|
422
|
+
public void reload(final PluginCall call) {
|
|
423
|
+
try {
|
|
424
|
+
if (this._reload()) {
|
|
425
|
+
call.resolve();
|
|
426
|
+
} else {
|
|
427
|
+
Log.e(CapacitorUpdater.TAG, "Reload failed");
|
|
428
|
+
call.reject("Reload failed");
|
|
429
|
+
}
|
|
430
|
+
} catch (final Exception e) {
|
|
431
|
+
Log.e(CapacitorUpdater.TAG, "Could not reload", e);
|
|
432
|
+
call.reject("Could not reload", e);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
@PluginMethod
|
|
437
|
+
public void next(final PluginCall call) {
|
|
438
|
+
final String id = call.getString("id");
|
|
439
|
+
if (id == null) {
|
|
440
|
+
Log.e(CapacitorUpdater.TAG, "Next called without id");
|
|
441
|
+
call.reject("Next called without id");
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
try {
|
|
445
|
+
Log.i(CapacitorUpdater.TAG, "Setting next active id " + id);
|
|
446
|
+
if (!this.implementation.setNextBundle(id)) {
|
|
447
|
+
Log.e(
|
|
448
|
+
CapacitorUpdater.TAG,
|
|
449
|
+
"Set next id failed. Bundle " + id + " does not exist."
|
|
450
|
+
);
|
|
451
|
+
call.reject("Set next id failed. Bundle " + id + " does not exist.");
|
|
452
|
+
} else {
|
|
453
|
+
call.resolve(this.implementation.getBundleInfo(id).toJSON());
|
|
454
|
+
}
|
|
455
|
+
} catch (final Exception e) {
|
|
456
|
+
Log.e(CapacitorUpdater.TAG, "Could not set next id " + id, e);
|
|
457
|
+
call.reject("Could not set next id: " + id, e);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
@PluginMethod
|
|
462
|
+
public void set(final PluginCall call) {
|
|
463
|
+
final String id = call.getString("id");
|
|
464
|
+
if (id == null) {
|
|
465
|
+
Log.e(CapacitorUpdater.TAG, "Set called without id");
|
|
466
|
+
call.reject("Set called without id");
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
try {
|
|
470
|
+
Log.i(CapacitorUpdater.TAG, "Setting active bundle " + id);
|
|
471
|
+
if (!this.implementation.set(id)) {
|
|
472
|
+
Log.i(CapacitorUpdater.TAG, "No such bundle " + id);
|
|
473
|
+
call.reject("Update failed, id " + id + " does not exist.");
|
|
474
|
+
} else {
|
|
475
|
+
Log.i(CapacitorUpdater.TAG, "Bundle successfully set to " + id);
|
|
476
|
+
this.reload(call);
|
|
477
|
+
}
|
|
478
|
+
} catch (final Exception e) {
|
|
479
|
+
Log.e(CapacitorUpdater.TAG, "Could not set id " + id, e);
|
|
480
|
+
call.reject("Could not set id " + id, e);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
@PluginMethod
|
|
485
|
+
public void delete(final PluginCall call) {
|
|
486
|
+
final String id = call.getString("id");
|
|
487
|
+
if (id == null) {
|
|
488
|
+
Log.e(CapacitorUpdater.TAG, "missing id");
|
|
489
|
+
call.reject("missing id");
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
Log.i(CapacitorUpdater.TAG, "Deleting id " + id);
|
|
493
|
+
try {
|
|
494
|
+
final Boolean res = this.implementation.delete(id);
|
|
495
|
+
if (res) {
|
|
496
|
+
call.resolve();
|
|
497
|
+
} else {
|
|
498
|
+
Log.e(
|
|
499
|
+
CapacitorUpdater.TAG,
|
|
500
|
+
"Delete failed, id " + id + " does not exist"
|
|
501
|
+
);
|
|
502
|
+
call.reject("Delete failed, id " + id + " does not exist");
|
|
503
|
+
}
|
|
504
|
+
} catch (final Exception e) {
|
|
505
|
+
Log.e(CapacitorUpdater.TAG, "Could not delete id " + id, e);
|
|
506
|
+
call.reject("Could not delete id " + id, e);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
@PluginMethod
|
|
511
|
+
public void list(final PluginCall call) {
|
|
512
|
+
try {
|
|
513
|
+
final List<BundleInfo> res = this.implementation.list();
|
|
514
|
+
final JSObject ret = new JSObject();
|
|
515
|
+
final JSArray values = new JSArray();
|
|
516
|
+
for (final BundleInfo bundle : res) {
|
|
517
|
+
values.put(bundle.toJSON());
|
|
518
|
+
}
|
|
519
|
+
ret.put("bundles", values);
|
|
520
|
+
call.resolve(ret);
|
|
521
|
+
} catch (final Exception e) {
|
|
522
|
+
Log.e(CapacitorUpdater.TAG, "Could not list bundles", e);
|
|
523
|
+
call.reject("Could not list bundles", e);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
@PluginMethod
|
|
528
|
+
public void getLatest(final PluginCall call) {
|
|
529
|
+
try {
|
|
530
|
+
new Thread(
|
|
531
|
+
new Runnable() {
|
|
532
|
+
@Override
|
|
533
|
+
public void run() {
|
|
534
|
+
CapacitorUpdaterPlugin.this.implementation.getLatest(
|
|
535
|
+
CapacitorUpdaterPlugin.this.updateUrl,
|
|
536
|
+
res -> {
|
|
537
|
+
if (res.has("error")) {
|
|
538
|
+
call.reject(res.getString("error"));
|
|
539
|
+
return;
|
|
540
|
+
} else {
|
|
541
|
+
call.resolve(res);
|
|
542
|
+
}
|
|
543
|
+
final JSObject ret = new JSObject();
|
|
544
|
+
Iterator<String> keys = res.keys();
|
|
545
|
+
while (keys.hasNext()) {
|
|
546
|
+
String key = keys.next();
|
|
547
|
+
if (res.has(key)) {
|
|
548
|
+
try {
|
|
549
|
+
ret.put(key, res.get(key));
|
|
550
|
+
} catch (JSONException e) {
|
|
551
|
+
e.printStackTrace();
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
call.resolve(ret);
|
|
556
|
+
}
|
|
557
|
+
);
|
|
558
|
+
}
|
|
296
559
|
}
|
|
560
|
+
)
|
|
561
|
+
.start();
|
|
562
|
+
} catch (final Exception e) {
|
|
563
|
+
Log.e(CapacitorUpdater.TAG, "Failed to getLatest", e);
|
|
564
|
+
call.reject("Failed to getLatest", e);
|
|
297
565
|
}
|
|
566
|
+
}
|
|
298
567
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
568
|
+
private boolean _reset(final Boolean toLastSuccessful) {
|
|
569
|
+
final BundleInfo fallback = this.implementation.getFallbackBundle();
|
|
570
|
+
this.implementation.reset();
|
|
302
571
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
Log.i(CapacitorUpdater.TAG, "Resetting to native.");
|
|
309
|
-
return this._reload();
|
|
572
|
+
if (toLastSuccessful && !fallback.isBuiltin()) {
|
|
573
|
+
Log.i(CapacitorUpdater.TAG, "Resetting to: " + fallback);
|
|
574
|
+
return this.implementation.set(fallback) && this._reload();
|
|
310
575
|
}
|
|
311
576
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
577
|
+
Log.i(CapacitorUpdater.TAG, "Resetting to native.");
|
|
578
|
+
return this._reload();
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
@PluginMethod
|
|
582
|
+
public void reset(final PluginCall call) {
|
|
583
|
+
try {
|
|
584
|
+
final Boolean toLastSuccessful = call.getBoolean(
|
|
585
|
+
"toLastSuccessful",
|
|
586
|
+
false
|
|
587
|
+
);
|
|
588
|
+
if (this._reset(toLastSuccessful)) {
|
|
589
|
+
call.resolve();
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
Log.e(CapacitorUpdater.TAG, "Reset failed");
|
|
593
|
+
call.reject("Reset failed");
|
|
594
|
+
} catch (final Exception e) {
|
|
595
|
+
Log.e(CapacitorUpdater.TAG, "Reset failed", e);
|
|
596
|
+
call.reject("Reset failed", e);
|
|
326
597
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
@PluginMethod
|
|
601
|
+
public void current(final PluginCall call) {
|
|
602
|
+
try {
|
|
603
|
+
final JSObject ret = new JSObject();
|
|
604
|
+
final BundleInfo bundle = this.implementation.getCurrentBundle();
|
|
605
|
+
ret.put("bundle", bundle.toJSON());
|
|
606
|
+
ret.put("native", this.currentVersionNative);
|
|
607
|
+
call.resolve(ret);
|
|
608
|
+
} catch (final Exception e) {
|
|
609
|
+
Log.e(CapacitorUpdater.TAG, "Could not get current bundle", e);
|
|
610
|
+
call.reject("Could not get current bundle", e);
|
|
341
611
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
@PluginMethod
|
|
615
|
+
public void notifyAppReady(final PluginCall call) {
|
|
616
|
+
try {
|
|
617
|
+
final BundleInfo bundle = this.implementation.getCurrentBundle();
|
|
618
|
+
this.implementation.setSuccess(bundle, this.autoDeletePrevious);
|
|
619
|
+
Log.i(
|
|
620
|
+
CapacitorUpdater.TAG,
|
|
621
|
+
"Current bundle loaded successfully. ['notifyAppReady()' was called] " +
|
|
622
|
+
bundle
|
|
623
|
+
);
|
|
624
|
+
call.resolve();
|
|
625
|
+
} catch (final Exception e) {
|
|
626
|
+
Log.e(
|
|
627
|
+
CapacitorUpdater.TAG,
|
|
628
|
+
"Failed to notify app ready state. [Error calling 'notifyAppReady()']",
|
|
629
|
+
e
|
|
630
|
+
);
|
|
631
|
+
call.reject("Failed to commit app ready state.", e);
|
|
355
632
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
@PluginMethod
|
|
636
|
+
public void setMultiDelay(final PluginCall call) {
|
|
637
|
+
try {
|
|
638
|
+
final Object delayConditions = call.getData().opt("delayConditions");
|
|
639
|
+
if (delayConditions == null) {
|
|
640
|
+
Log.e(
|
|
641
|
+
CapacitorUpdater.TAG,
|
|
642
|
+
"setMultiDelay called without delayCondition"
|
|
643
|
+
);
|
|
644
|
+
call.reject("setMultiDelay called without delayCondition");
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
if (_setMultiDelay(delayConditions.toString())) {
|
|
648
|
+
call.resolve();
|
|
649
|
+
} else {
|
|
650
|
+
call.reject("Failed to delay update");
|
|
651
|
+
}
|
|
652
|
+
} catch (final Exception e) {
|
|
653
|
+
Log.e(
|
|
654
|
+
CapacitorUpdater.TAG,
|
|
655
|
+
"Failed to delay update, [Error calling 'setMultiDelay()']",
|
|
656
|
+
e
|
|
657
|
+
);
|
|
658
|
+
call.reject("Failed to delay update", e);
|
|
369
659
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
private Boolean _setMultiDelay(String delayConditions) {
|
|
663
|
+
try {
|
|
664
|
+
this.editor.putString(DELAY_CONDITION_PREFERENCES, delayConditions);
|
|
665
|
+
this.editor.commit();
|
|
666
|
+
Log.i(CapacitorUpdater.TAG, "Delay update saved");
|
|
667
|
+
return true;
|
|
668
|
+
} catch (final Exception e) {
|
|
669
|
+
Log.e(
|
|
670
|
+
CapacitorUpdater.TAG,
|
|
671
|
+
"Failed to delay update, [Error calling '_setMultiDelay()']",
|
|
672
|
+
e
|
|
673
|
+
);
|
|
674
|
+
return false;
|
|
383
675
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
private boolean _cancelDelay(String source) {
|
|
679
|
+
try {
|
|
680
|
+
this.editor.remove(DELAY_CONDITION_PREFERENCES);
|
|
681
|
+
this.editor.commit();
|
|
682
|
+
Log.i(CapacitorUpdater.TAG, "All delays canceled from " + source);
|
|
683
|
+
return true;
|
|
684
|
+
} catch (final Exception e) {
|
|
685
|
+
Log.e(CapacitorUpdater.TAG, "Failed to cancel update delay", e);
|
|
686
|
+
return false;
|
|
387
687
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
Log.e(CapacitorUpdater.TAG, "Could not get autoUpdate status", e);
|
|
397
|
-
call.reject("Could not get autoUpdate status", e);
|
|
398
|
-
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
@PluginMethod
|
|
691
|
+
public void cancelDelay(final PluginCall call) {
|
|
692
|
+
if (this._cancelDelay("JS")) {
|
|
693
|
+
call.resolve();
|
|
694
|
+
} else {
|
|
695
|
+
call.reject("Failed to cancel delay");
|
|
399
696
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
private void _checkCancelDelay(Boolean killed) {
|
|
700
|
+
Gson gson = new Gson();
|
|
701
|
+
String delayUpdatePreferences = prefs.getString(
|
|
702
|
+
DELAY_CONDITION_PREFERENCES,
|
|
703
|
+
"[]"
|
|
704
|
+
);
|
|
705
|
+
Type type = new TypeToken<ArrayList<DelayCondition>>() {}.getType();
|
|
706
|
+
ArrayList<DelayCondition> delayConditionList = gson.fromJson(
|
|
707
|
+
delayUpdatePreferences,
|
|
708
|
+
type
|
|
709
|
+
);
|
|
710
|
+
for (DelayCondition condition : delayConditionList) {
|
|
711
|
+
String kind = condition.getKind().toString();
|
|
712
|
+
String value = condition.getValue();
|
|
713
|
+
if (!"".equals(kind)) {
|
|
714
|
+
switch (kind) {
|
|
715
|
+
case "background":
|
|
716
|
+
if (!killed) {
|
|
717
|
+
this._cancelDelay("background check");
|
|
405
718
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
final BundleInfo latest = CapacitorUpdaterPlugin.this.implementation.getBundleInfoByName(latestVersionName);
|
|
438
|
-
if(latest != null) {
|
|
439
|
-
if(latest.isErrorStatus()) {
|
|
440
|
-
Log.e(CapacitorUpdater.TAG, "Latest bundle already exists, and is in error state. Aborting update.");
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
if(latest.isDownloaded()){
|
|
444
|
-
Log.e(CapacitorUpdater.TAG, "Latest bundle already exists and download is NOT required. Update will occur next time app moves to background.");
|
|
445
|
-
CapacitorUpdaterPlugin.this.implementation.setNextVersion(latest.getId());
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
new Thread(new Runnable(){
|
|
452
|
-
@Override
|
|
453
|
-
public void run() {
|
|
454
|
-
try {
|
|
455
|
-
Log.i(CapacitorUpdater.TAG, "New bundle: " + latestVersionName + " found. Current is: " + current.getVersionName() + ". Update will occur next time app moves to background.");
|
|
456
|
-
|
|
457
|
-
final String url = (String) res.get("url");
|
|
458
|
-
final BundleInfo next = CapacitorUpdaterPlugin.this.implementation.download(url, latestVersionName);
|
|
459
|
-
|
|
460
|
-
CapacitorUpdaterPlugin.this.implementation.setNextVersion(next.getId());
|
|
461
|
-
} catch (final Exception e) {
|
|
462
|
-
Log.e(CapacitorUpdater.TAG, "error downloading file", e);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}).start();
|
|
466
|
-
} else {
|
|
467
|
-
Log.i(CapacitorUpdater.TAG, "No need to update, " + current + " is the latest bundle.");
|
|
468
|
-
}
|
|
469
|
-
} catch (final JSONException e) {
|
|
470
|
-
Log.e(CapacitorUpdater.TAG, "error parsing JSON", e);
|
|
471
|
-
}
|
|
472
|
-
});
|
|
719
|
+
break;
|
|
720
|
+
case "kill":
|
|
721
|
+
if (killed) {
|
|
722
|
+
this._cancelDelay("kill check");
|
|
723
|
+
this.installNext();
|
|
724
|
+
}
|
|
725
|
+
break;
|
|
726
|
+
case "date":
|
|
727
|
+
if (!"".equals(value)) {
|
|
728
|
+
try {
|
|
729
|
+
final SimpleDateFormat sdf = new SimpleDateFormat(
|
|
730
|
+
"yyyy-MM-dd'T'HH:mm:ss.SSS"
|
|
731
|
+
);
|
|
732
|
+
Date date = sdf.parse(value);
|
|
733
|
+
assert date != null;
|
|
734
|
+
if (new Date().compareTo(date) > 0) {
|
|
735
|
+
this._cancelDelay("date expired");
|
|
736
|
+
}
|
|
737
|
+
} catch (final Exception e) {
|
|
738
|
+
this._cancelDelay("date parsing issue");
|
|
739
|
+
}
|
|
740
|
+
} else {
|
|
741
|
+
this._cancelDelay("delayVal absent");
|
|
742
|
+
}
|
|
743
|
+
break;
|
|
744
|
+
case "nativeVersion":
|
|
745
|
+
if (!"".equals(value)) {
|
|
746
|
+
try {
|
|
747
|
+
final Version versionLimit = new Version(value);
|
|
748
|
+
if (this.currentVersionNative.isAtLeast(versionLimit)) {
|
|
749
|
+
this._cancelDelay("nativeVersion above limit");
|
|
473
750
|
}
|
|
474
|
-
|
|
751
|
+
} catch (final Exception e) {
|
|
752
|
+
this._cancelDelay("nativeVersion parsing issue");
|
|
753
|
+
}
|
|
754
|
+
} else {
|
|
755
|
+
this._cancelDelay("delayVal absent");
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
475
758
|
}
|
|
476
|
-
|
|
477
|
-
this.checkAppReady();
|
|
759
|
+
}
|
|
478
760
|
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
private Boolean _isAutoUpdateEnabled() {
|
|
764
|
+
final CapConfig config = CapConfig.loadDefault(this.getActivity());
|
|
765
|
+
String serverUrl = config.getServerUrl();
|
|
766
|
+
if (serverUrl != null && !"".equals(serverUrl)) {
|
|
767
|
+
// log warning autoupdate disabled when serverUrl is set
|
|
768
|
+
Log.w(
|
|
769
|
+
CapacitorUpdater.TAG,
|
|
770
|
+
"AutoUpdate is automatic disabled when serverUrl is set."
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
return (
|
|
774
|
+
CapacitorUpdaterPlugin.this.autoUpdate &&
|
|
775
|
+
!"".equals(CapacitorUpdaterPlugin.this.updateUrl) &&
|
|
776
|
+
serverUrl == null &&
|
|
777
|
+
!"".equals(serverUrl)
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
@PluginMethod
|
|
782
|
+
public void isAutoUpdateEnabled(final PluginCall call) {
|
|
783
|
+
try {
|
|
784
|
+
final JSObject ret = new JSObject();
|
|
785
|
+
ret.put("enabled", this._isAutoUpdateEnabled());
|
|
786
|
+
call.resolve(ret);
|
|
787
|
+
} catch (final Exception e) {
|
|
788
|
+
Log.e(CapacitorUpdater.TAG, "Could not get autoUpdate status", e);
|
|
789
|
+
call.reject("Could not get autoUpdate status", e);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
private void checkAppReady() {
|
|
794
|
+
try {
|
|
795
|
+
if (this.appReadyCheck != null) {
|
|
796
|
+
this.appReadyCheck.interrupt();
|
|
797
|
+
}
|
|
798
|
+
this.appReadyCheck = new Thread(new DeferredNotifyAppReadyCheck());
|
|
799
|
+
this.appReadyCheck.start();
|
|
800
|
+
} catch (final Exception e) {
|
|
801
|
+
Log.e(
|
|
802
|
+
CapacitorUpdater.TAG,
|
|
803
|
+
"Failed to start " + DeferredNotifyAppReadyCheck.class.getName(),
|
|
804
|
+
e
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
private boolean isValidURL(String urlStr) {
|
|
810
|
+
try {
|
|
811
|
+
URL url = new URL(urlStr);
|
|
812
|
+
return true;
|
|
813
|
+
} catch (MalformedURLException e) {
|
|
814
|
+
return false;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
479
817
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
} else if (!success) {
|
|
512
|
-
// There is a no next bundle, and the current bundle has failed
|
|
513
|
-
|
|
514
|
-
if(!current.isBuiltin()) {
|
|
515
|
-
// Don't try to roll back the builtin bundle. Nothing we can do.
|
|
516
|
-
|
|
517
|
-
this.implementation.rollback(current);
|
|
518
|
-
|
|
519
|
-
Log.i(CapacitorUpdater.TAG, "Update failed: 'notifyAppReady()' was never called.");
|
|
520
|
-
Log.i(CapacitorUpdater.TAG, "Bundle: " + current + ", is in error state.");
|
|
521
|
-
Log.i(CapacitorUpdater.TAG, "Will fallback to: " + fallback + " on application restart.");
|
|
522
|
-
Log.i(CapacitorUpdater.TAG, "Did you forget to call 'notifyAppReady()' in your Capacitor App code?");
|
|
523
|
-
final JSObject ret = new JSObject();
|
|
524
|
-
ret.put("bundle", current);
|
|
525
|
-
this.notifyListeners("updateFailed", ret);
|
|
526
|
-
this.implementation.sendStats("revert", current);
|
|
527
|
-
if (!fallback.isBuiltin() && !fallback.equals(current)) {
|
|
528
|
-
final Boolean res = this.implementation.set(fallback);
|
|
529
|
-
if (res && this._reload()) {
|
|
530
|
-
Log.i(CapacitorUpdater.TAG, "Revert to bundle: " + fallback.getVersionName());
|
|
531
|
-
} else {
|
|
532
|
-
Log.e(CapacitorUpdater.TAG, "Revert to bundle: " + fallback.getVersionName() + " Failed!");
|
|
533
|
-
}
|
|
534
|
-
} else {
|
|
535
|
-
if (this._reset(false)) {
|
|
536
|
-
Log.i(CapacitorUpdater.TAG, "Reverted to 'builtin' bundle.");
|
|
537
|
-
}
|
|
818
|
+
private void backgroundDownload() {
|
|
819
|
+
new Thread(
|
|
820
|
+
new Runnable() {
|
|
821
|
+
@Override
|
|
822
|
+
public void run() {
|
|
823
|
+
Log.i(
|
|
824
|
+
CapacitorUpdater.TAG,
|
|
825
|
+
"Check for update via: " + CapacitorUpdaterPlugin.this.updateUrl
|
|
826
|
+
);
|
|
827
|
+
CapacitorUpdaterPlugin.this.implementation.getLatest(
|
|
828
|
+
CapacitorUpdaterPlugin.this.updateUrl,
|
|
829
|
+
res -> {
|
|
830
|
+
final BundleInfo current =
|
|
831
|
+
CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
832
|
+
try {
|
|
833
|
+
if (res.has("message")) {
|
|
834
|
+
Log.i(
|
|
835
|
+
CapacitorUpdater.TAG,
|
|
836
|
+
"message " + res.get("message")
|
|
837
|
+
);
|
|
838
|
+
if (
|
|
839
|
+
res.has("major") &&
|
|
840
|
+
res.getBoolean("major") &&
|
|
841
|
+
res.has("version")
|
|
842
|
+
) {
|
|
843
|
+
final JSObject majorAvailable = new JSObject();
|
|
844
|
+
majorAvailable.put("version", res.getString("version"));
|
|
845
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
846
|
+
"majorAvailable",
|
|
847
|
+
majorAvailable
|
|
848
|
+
);
|
|
538
849
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
850
|
+
final JSObject retNoNeed = new JSObject();
|
|
851
|
+
retNoNeed.put("bundle", current.toJSON());
|
|
852
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
853
|
+
"noNeedUpdate",
|
|
854
|
+
retNoNeed
|
|
855
|
+
);
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if (
|
|
860
|
+
!res.has("url") ||
|
|
861
|
+
!CapacitorUpdaterPlugin.this.isValidURL(
|
|
862
|
+
res.getString("url")
|
|
863
|
+
)
|
|
864
|
+
) {
|
|
865
|
+
Log.e(CapacitorUpdater.TAG, "Error no url or wrong format");
|
|
866
|
+
final JSObject retNoNeed = new JSObject();
|
|
867
|
+
retNoNeed.put("bundle", current.toJSON());
|
|
868
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
869
|
+
"noNeedUpdate",
|
|
870
|
+
retNoNeed
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
final String latestVersionName = res.getString("version");
|
|
874
|
+
|
|
875
|
+
if (
|
|
876
|
+
latestVersionName != null &&
|
|
877
|
+
!"".equals(latestVersionName) &&
|
|
878
|
+
!current.getVersionName().equals(latestVersionName)
|
|
879
|
+
) {
|
|
880
|
+
final BundleInfo latest =
|
|
881
|
+
CapacitorUpdaterPlugin.this.implementation.getBundleInfoByName(
|
|
882
|
+
latestVersionName
|
|
883
|
+
);
|
|
884
|
+
if (latest != null) {
|
|
885
|
+
if (latest.isErrorStatus()) {
|
|
886
|
+
Log.e(
|
|
887
|
+
CapacitorUpdater.TAG,
|
|
888
|
+
"Latest bundle already exists, and is in error state. Aborting update."
|
|
889
|
+
);
|
|
890
|
+
final JSObject retNoNeed = new JSObject();
|
|
891
|
+
retNoNeed.put("bundle", current.toJSON());
|
|
892
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
893
|
+
"noNeedUpdate",
|
|
894
|
+
retNoNeed
|
|
895
|
+
);
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
if (latest.isDownloaded()) {
|
|
899
|
+
Log.i(
|
|
900
|
+
CapacitorUpdater.TAG,
|
|
901
|
+
"Latest bundle already exists and download is NOT required. Update will occur next time app moves to background."
|
|
902
|
+
);
|
|
903
|
+
final JSObject ret = new JSObject();
|
|
904
|
+
ret.put("bundle", latest.toJSON());
|
|
905
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
906
|
+
"updateAvailable",
|
|
907
|
+
ret
|
|
908
|
+
);
|
|
909
|
+
CapacitorUpdaterPlugin.this.implementation.setNextBundle(
|
|
910
|
+
latest.getId()
|
|
911
|
+
);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
if (latest.isDeleted()) {
|
|
915
|
+
Log.i(
|
|
916
|
+
CapacitorUpdater.TAG,
|
|
917
|
+
"Latest bundle already exists and will be deleted, download will overwrite it."
|
|
918
|
+
);
|
|
542
919
|
try {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
920
|
+
final Boolean deleted =
|
|
921
|
+
CapacitorUpdaterPlugin.this.implementation.delete(
|
|
922
|
+
latest.getId(),
|
|
923
|
+
true
|
|
924
|
+
);
|
|
925
|
+
if (deleted) {
|
|
926
|
+
Log.i(
|
|
927
|
+
CapacitorUpdater.TAG,
|
|
928
|
+
"Failed bundle deleted: " +
|
|
929
|
+
latest.getVersionName()
|
|
930
|
+
);
|
|
931
|
+
}
|
|
547
932
|
} catch (final IOException e) {
|
|
548
|
-
|
|
933
|
+
Log.e(
|
|
934
|
+
CapacitorUpdater.TAG,
|
|
935
|
+
"Failed to delete failed bundle: " +
|
|
936
|
+
latest.getVersionName(),
|
|
937
|
+
e
|
|
938
|
+
);
|
|
549
939
|
}
|
|
940
|
+
}
|
|
550
941
|
}
|
|
551
|
-
} else {
|
|
552
|
-
// Nothing we can/should do by default if the 'builtin' bundle fails to call 'notifyAppReady()'.
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
} else if (!fallback.isBuiltin()) {
|
|
556
|
-
// There is a no next bundle, and the current bundle has succeeded
|
|
557
|
-
this.implementation.commit(current);
|
|
558
942
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
Log.i(
|
|
943
|
+
new Thread(
|
|
944
|
+
new Runnable() {
|
|
945
|
+
@Override
|
|
946
|
+
public void run() {
|
|
947
|
+
try {
|
|
948
|
+
Log.i(
|
|
949
|
+
CapacitorUpdater.TAG,
|
|
950
|
+
"New bundle: " +
|
|
951
|
+
latestVersionName +
|
|
952
|
+
" found. Current is: " +
|
|
953
|
+
current.getVersionName() +
|
|
954
|
+
". Update will occur next time app moves to background."
|
|
955
|
+
);
|
|
956
|
+
|
|
957
|
+
final String url = res.getString("url");
|
|
958
|
+
final String sessionKey = res.has("sessionKey")
|
|
959
|
+
? res.getString("sessionKey")
|
|
960
|
+
: "";
|
|
961
|
+
final String checksum = res.has("checksum")
|
|
962
|
+
? res.getString("checksum")
|
|
963
|
+
: "";
|
|
964
|
+
CapacitorUpdaterPlugin.this.implementation.downloadBackground(
|
|
965
|
+
url,
|
|
966
|
+
latestVersionName,
|
|
967
|
+
sessionKey,
|
|
968
|
+
checksum
|
|
969
|
+
);
|
|
970
|
+
} catch (final Exception e) {
|
|
971
|
+
Log.e(
|
|
972
|
+
CapacitorUpdater.TAG,
|
|
973
|
+
"error downloading file",
|
|
974
|
+
e
|
|
975
|
+
);
|
|
976
|
+
final JSObject ret = new JSObject();
|
|
977
|
+
ret.put("version", latestVersionName);
|
|
978
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
979
|
+
"downloadFailed",
|
|
980
|
+
ret
|
|
981
|
+
);
|
|
982
|
+
final BundleInfo current =
|
|
983
|
+
CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
984
|
+
CapacitorUpdaterPlugin.this.implementation.sendStats(
|
|
985
|
+
"download_fail",
|
|
986
|
+
current.getVersionName()
|
|
987
|
+
);
|
|
988
|
+
final JSObject retNoNeed = new JSObject();
|
|
989
|
+
retNoNeed.put("bundle", current.toJSON());
|
|
990
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
991
|
+
"noNeedUpdate",
|
|
992
|
+
retNoNeed
|
|
993
|
+
);
|
|
994
|
+
}
|
|
565
995
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
996
|
+
}
|
|
997
|
+
)
|
|
998
|
+
.start();
|
|
999
|
+
} else {
|
|
1000
|
+
Log.i(
|
|
1001
|
+
CapacitorUpdater.TAG,
|
|
1002
|
+
"No need to update, " +
|
|
1003
|
+
current.getId() +
|
|
1004
|
+
" is the latest bundle."
|
|
1005
|
+
);
|
|
1006
|
+
final JSObject retNoNeed = new JSObject();
|
|
1007
|
+
retNoNeed.put("bundle", current.toJSON());
|
|
1008
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
1009
|
+
"noNeedUpdate",
|
|
1010
|
+
retNoNeed
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
} catch (final JSONException e) {
|
|
1014
|
+
Log.e(CapacitorUpdater.TAG, "error parsing JSON", e);
|
|
1015
|
+
final JSObject retNoNeed = new JSObject();
|
|
1016
|
+
retNoNeed.put("bundle", current.toJSON());
|
|
1017
|
+
CapacitorUpdaterPlugin.this.notifyListeners(
|
|
1018
|
+
"noNeedUpdate",
|
|
1019
|
+
retNoNeed
|
|
1020
|
+
);
|
|
569
1021
|
}
|
|
570
|
-
|
|
1022
|
+
}
|
|
1023
|
+
);
|
|
571
1024
|
}
|
|
572
|
-
|
|
573
|
-
|
|
1025
|
+
}
|
|
1026
|
+
)
|
|
1027
|
+
.start();
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
private void installNext() {
|
|
1031
|
+
try {
|
|
1032
|
+
Gson gson = new Gson();
|
|
1033
|
+
String delayUpdatePreferences = prefs.getString(
|
|
1034
|
+
DELAY_CONDITION_PREFERENCES,
|
|
1035
|
+
"[]"
|
|
1036
|
+
);
|
|
1037
|
+
Type type = new TypeToken<ArrayList<DelayCondition>>() {}.getType();
|
|
1038
|
+
ArrayList<DelayCondition> delayConditionList = gson.fromJson(
|
|
1039
|
+
delayUpdatePreferences,
|
|
1040
|
+
type
|
|
1041
|
+
);
|
|
1042
|
+
if (delayConditionList != null && delayConditionList.size() != 0) {
|
|
1043
|
+
Log.i(CapacitorUpdater.TAG, "Update delayed to next backgrounding");
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
final BundleInfo current = this.implementation.getCurrentBundle();
|
|
1047
|
+
final BundleInfo next = this.implementation.getNextBundle();
|
|
1048
|
+
|
|
1049
|
+
if (
|
|
1050
|
+
next != null &&
|
|
1051
|
+
!next.isErrorStatus() &&
|
|
1052
|
+
!next.getId().equals(current.getId())
|
|
1053
|
+
) {
|
|
1054
|
+
// There is a next bundle waiting for activation
|
|
1055
|
+
Log.d(CapacitorUpdater.TAG, "Next bundle is: " + next.getVersionName());
|
|
1056
|
+
if (this.implementation.set(next) && this._reload()) {
|
|
1057
|
+
Log.i(
|
|
1058
|
+
CapacitorUpdater.TAG,
|
|
1059
|
+
"Updated to bundle: " + next.getVersionName()
|
|
1060
|
+
);
|
|
1061
|
+
this.implementation.setNextBundle(null);
|
|
1062
|
+
} else {
|
|
1063
|
+
Log.e(
|
|
1064
|
+
CapacitorUpdater.TAG,
|
|
1065
|
+
"Update to bundle: " + next.getVersionName() + " Failed!"
|
|
1066
|
+
);
|
|
574
1067
|
}
|
|
1068
|
+
}
|
|
1069
|
+
} catch (final Exception e) {
|
|
1070
|
+
Log.e(CapacitorUpdater.TAG, "Error during onActivityStopped", e);
|
|
575
1071
|
}
|
|
1072
|
+
}
|
|
576
1073
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
try {
|
|
581
|
-
Log.i(CapacitorUpdater.TAG, "Wait for " + CapacitorUpdaterPlugin.this.appReadyTimeout + "ms, then check for notifyAppReady");
|
|
582
|
-
Thread.sleep(CapacitorUpdaterPlugin.this.appReadyTimeout);
|
|
583
|
-
// Automatically roll back to fallback version if notifyAppReady has not been called yet
|
|
584
|
-
final BundleInfo current = CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
585
|
-
if(current.isBuiltin()) {
|
|
586
|
-
Log.i(CapacitorUpdater.TAG, "Built-in bundle is active. Nothing to do.");
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
if(BundleStatus.SUCCESS != current.getStatus()) {
|
|
591
|
-
Log.e(CapacitorUpdater.TAG, "notifyAppReady was not called, roll back current bundle: " + current.getId());
|
|
592
|
-
CapacitorUpdaterPlugin.this.implementation.rollback(current);
|
|
593
|
-
CapacitorUpdaterPlugin.this._reset(true);
|
|
594
|
-
} else {
|
|
595
|
-
Log.i(CapacitorUpdater.TAG, "notifyAppReady was called. This is fine: " + current.getId());
|
|
596
|
-
}
|
|
1074
|
+
private void checkRevert() {
|
|
1075
|
+
// Automatically roll back to fallback version if notifyAppReady has not been called yet
|
|
1076
|
+
final BundleInfo current = this.implementation.getCurrentBundle();
|
|
597
1077
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
1078
|
+
if (current.isBuiltin()) {
|
|
1079
|
+
Log.i(CapacitorUpdater.TAG, "Built-in bundle is active. Nothing to do.");
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
Log.d(CapacitorUpdater.TAG, "Current bundle is: " + current);
|
|
1083
|
+
|
|
1084
|
+
if (BundleStatus.SUCCESS != current.getStatus()) {
|
|
1085
|
+
Log.e(
|
|
1086
|
+
CapacitorUpdater.TAG,
|
|
1087
|
+
"notifyAppReady was not called, roll back current bundle: " +
|
|
1088
|
+
current.getId()
|
|
1089
|
+
);
|
|
1090
|
+
Log.i(
|
|
1091
|
+
CapacitorUpdater.TAG,
|
|
1092
|
+
"Did you forget to call 'notifyAppReady()' in your Capacitor App code?"
|
|
1093
|
+
);
|
|
1094
|
+
final JSObject ret = new JSObject();
|
|
1095
|
+
ret.put("bundle", current.toJSON());
|
|
1096
|
+
this.notifyListeners("updateFailed", ret);
|
|
1097
|
+
this.implementation.sendStats("update_fail", current.getVersionName());
|
|
1098
|
+
this.implementation.setError(current);
|
|
1099
|
+
this._reset(true);
|
|
1100
|
+
if (
|
|
1101
|
+
CapacitorUpdaterPlugin.this.autoDeleteFailed && !current.isBuiltin()
|
|
1102
|
+
) {
|
|
1103
|
+
Log.i(
|
|
1104
|
+
CapacitorUpdater.TAG,
|
|
1105
|
+
"Deleting failing bundle: " + current.getVersionName()
|
|
1106
|
+
);
|
|
1107
|
+
try {
|
|
1108
|
+
final Boolean res =
|
|
1109
|
+
this.implementation.delete(current.getId(), false);
|
|
1110
|
+
if (res) {
|
|
1111
|
+
Log.i(
|
|
1112
|
+
CapacitorUpdater.TAG,
|
|
1113
|
+
"Failed bundle deleted: " + current.getVersionName()
|
|
1114
|
+
);
|
|
1115
|
+
}
|
|
1116
|
+
} catch (final IOException e) {
|
|
1117
|
+
Log.e(
|
|
1118
|
+
CapacitorUpdater.TAG,
|
|
1119
|
+
"Failed to delete failed bundle: " + current.getVersionName(),
|
|
1120
|
+
e
|
|
1121
|
+
);
|
|
602
1122
|
}
|
|
1123
|
+
}
|
|
1124
|
+
} else {
|
|
1125
|
+
Log.i(
|
|
1126
|
+
CapacitorUpdater.TAG,
|
|
1127
|
+
"notifyAppReady was called. This is fine: " + current.getId()
|
|
1128
|
+
);
|
|
603
1129
|
}
|
|
1130
|
+
}
|
|
604
1131
|
|
|
605
|
-
|
|
606
|
-
@Override
|
|
607
|
-
public void onActivityResumed(@NonNull final Activity activity) {
|
|
608
|
-
// TODO: Implement background updating based on `backgroundUpdate` and `backgroundUpdateDelay` capacitor.config.ts settings
|
|
609
|
-
}
|
|
1132
|
+
private class DeferredNotifyAppReadyCheck implements Runnable {
|
|
610
1133
|
|
|
611
1134
|
@Override
|
|
612
|
-
public void
|
|
613
|
-
|
|
1135
|
+
public void run() {
|
|
1136
|
+
try {
|
|
1137
|
+
Log.i(
|
|
1138
|
+
CapacitorUpdater.TAG,
|
|
1139
|
+
"Wait for " +
|
|
1140
|
+
CapacitorUpdaterPlugin.this.appReadyTimeout +
|
|
1141
|
+
"ms, then check for notifyAppReady"
|
|
1142
|
+
);
|
|
1143
|
+
Thread.sleep(CapacitorUpdaterPlugin.this.appReadyTimeout);
|
|
1144
|
+
CapacitorUpdaterPlugin.this.checkRevert();
|
|
1145
|
+
CapacitorUpdaterPlugin.this.appReadyCheck = null;
|
|
1146
|
+
} catch (final InterruptedException e) {
|
|
1147
|
+
Log.i(
|
|
1148
|
+
CapacitorUpdater.TAG,
|
|
1149
|
+
DeferredNotifyAppReadyCheck.class.getName() + " was interrupted."
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
614
1152
|
}
|
|
615
|
-
|
|
616
|
-
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
public void appMovedToForeground() {
|
|
1156
|
+
final BundleInfo current =
|
|
1157
|
+
CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
1158
|
+
CapacitorUpdaterPlugin.this.implementation.sendStats(
|
|
1159
|
+
"app_moved_to_foreground",
|
|
1160
|
+
current.getVersionName()
|
|
1161
|
+
);
|
|
1162
|
+
if (CapacitorUpdaterPlugin.this._isAutoUpdateEnabled()) {
|
|
1163
|
+
this.backgroundDownload();
|
|
617
1164
|
}
|
|
1165
|
+
this.checkAppReady();
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
public void appMovedToBackground() {
|
|
1169
|
+
final BundleInfo current =
|
|
1170
|
+
CapacitorUpdaterPlugin.this.implementation.getCurrentBundle();
|
|
1171
|
+
CapacitorUpdaterPlugin.this.implementation.sendStats(
|
|
1172
|
+
"app_moved_to_background",
|
|
1173
|
+
current.getVersionName()
|
|
1174
|
+
);
|
|
1175
|
+
Log.i(CapacitorUpdater.TAG, "Checking for pending update");
|
|
1176
|
+
try {
|
|
1177
|
+
Gson gson = new Gson();
|
|
1178
|
+
String delayUpdatePreferences = prefs.getString(
|
|
1179
|
+
DELAY_CONDITION_PREFERENCES,
|
|
1180
|
+
"[]"
|
|
1181
|
+
);
|
|
1182
|
+
Type type = new TypeToken<ArrayList<DelayCondition>>() {}.getType();
|
|
1183
|
+
ArrayList<DelayCondition> delayConditionList = gson.fromJson(
|
|
1184
|
+
delayUpdatePreferences,
|
|
1185
|
+
type
|
|
1186
|
+
);
|
|
1187
|
+
String backgroundValue = null;
|
|
1188
|
+
for (DelayCondition delayCondition : delayConditionList) {
|
|
1189
|
+
if (delayCondition.getKind().toString().equals("background")) {
|
|
1190
|
+
String value = delayCondition.getValue();
|
|
1191
|
+
backgroundValue = (value != null && !value.isEmpty()) ? value : "0";
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
if (backgroundValue != null) {
|
|
1195
|
+
taskRunning = true;
|
|
1196
|
+
final Long timeout = Long.parseLong(backgroundValue);
|
|
1197
|
+
if (backgroundTask != null) {
|
|
1198
|
+
backgroundTask.interrupt();
|
|
1199
|
+
}
|
|
1200
|
+
backgroundTask =
|
|
1201
|
+
new Thread(
|
|
1202
|
+
new Runnable() {
|
|
1203
|
+
@Override
|
|
1204
|
+
public void run() {
|
|
1205
|
+
try {
|
|
1206
|
+
Thread.sleep(timeout);
|
|
1207
|
+
taskRunning = false;
|
|
1208
|
+
_checkCancelDelay(false);
|
|
1209
|
+
installNext();
|
|
1210
|
+
} catch (InterruptedException e) {
|
|
1211
|
+
Log.i(
|
|
1212
|
+
CapacitorUpdater.TAG,
|
|
1213
|
+
"Background Task canceled, Activity resumed before timer completes"
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
);
|
|
1219
|
+
backgroundTask.start();
|
|
1220
|
+
} else {
|
|
1221
|
+
this._checkCancelDelay(false);
|
|
1222
|
+
this.installNext();
|
|
1223
|
+
}
|
|
1224
|
+
} catch (final Exception e) {
|
|
1225
|
+
Log.e(CapacitorUpdater.TAG, "Error during onActivityStopped", e);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
618
1228
|
|
|
619
|
-
|
|
620
|
-
|
|
1229
|
+
private boolean isMainActivity() {
|
|
1230
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
Context mContext = this.getContext();
|
|
1234
|
+
ActivityManager activityManager =
|
|
1235
|
+
(ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
|
|
1236
|
+
List<ActivityManager.AppTask> runningTasks = activityManager.getAppTasks();
|
|
1237
|
+
ActivityManager.RecentTaskInfo runningTask = runningTasks
|
|
1238
|
+
.get(0)
|
|
1239
|
+
.getTaskInfo();
|
|
1240
|
+
String className = runningTask.baseIntent.getComponent().getClassName();
|
|
1241
|
+
String runningActivity = runningTask.topActivity.getClassName();
|
|
1242
|
+
boolean isThisAppActivity = className.equals(runningActivity);
|
|
1243
|
+
return isThisAppActivity;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
private void appKilled() {
|
|
1247
|
+
Log.d(CapacitorUpdater.TAG, "onActivityDestroyed: all activity destroyed");
|
|
1248
|
+
this._checkCancelDelay(true);
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
@Override
|
|
1252
|
+
public void onActivityStarted(@NonNull final Activity activity) {
|
|
1253
|
+
if (isPreviousMainActivity) {
|
|
1254
|
+
this.appMovedToForeground();
|
|
1255
|
+
}
|
|
1256
|
+
isPreviousMainActivity = true;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
@Override
|
|
1260
|
+
public void onActivityStopped(@NonNull final Activity activity) {
|
|
1261
|
+
isPreviousMainActivity = isMainActivity();
|
|
1262
|
+
if (isPreviousMainActivity) {
|
|
1263
|
+
this.appMovedToBackground();
|
|
621
1264
|
}
|
|
1265
|
+
}
|
|
622
1266
|
|
|
623
|
-
|
|
624
|
-
|
|
1267
|
+
@Override
|
|
1268
|
+
public void onActivityResumed(@NonNull final Activity activity) {
|
|
1269
|
+
if (backgroundTask != null && taskRunning) {
|
|
1270
|
+
backgroundTask.interrupt();
|
|
1271
|
+
}
|
|
1272
|
+
this.implementation.activity = activity;
|
|
1273
|
+
this.implementation.onResume();
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
@Override
|
|
1277
|
+
public void onActivityPaused(@NonNull final Activity activity) {
|
|
1278
|
+
this.implementation.activity = activity;
|
|
1279
|
+
this.implementation.onPause();
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
@Override
|
|
1283
|
+
public void onActivityCreated(
|
|
1284
|
+
@NonNull final Activity activity,
|
|
1285
|
+
@Nullable final Bundle savedInstanceState
|
|
1286
|
+
) {
|
|
1287
|
+
this.implementation.activity = activity;
|
|
1288
|
+
this.counterActivityCreate++;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
@Override
|
|
1292
|
+
public void onActivitySaveInstanceState(
|
|
1293
|
+
@NonNull final Activity activity,
|
|
1294
|
+
@NonNull final Bundle outState
|
|
1295
|
+
) {
|
|
1296
|
+
this.implementation.activity = activity;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
@Override
|
|
1300
|
+
public void onActivityDestroyed(@NonNull final Activity activity) {
|
|
1301
|
+
this.implementation.activity = activity;
|
|
1302
|
+
counterActivityCreate--;
|
|
1303
|
+
if (counterActivityCreate == 0) {
|
|
1304
|
+
this.appKilled();
|
|
625
1305
|
}
|
|
1306
|
+
}
|
|
626
1307
|
}
|