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