@capgo/capacitor-updater 8.51.13 → 8.51.15
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/Package.swift +2 -1
- package/README.md +1 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +1 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +62 -29
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +89 -35
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +8 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/DataManager.java +23 -7
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +65 -39
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadWorkerManager.java +103 -3
- package/android/src/main/java/ee/forgr/capacitor_updater/ShakeMenu.java +3 -0
- package/dist/docs.json +1 -1
- package/dist/esm/definitions.d.ts +4 -1
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/AES.swift +5 -0
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +32 -11
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +55 -8
- package/package.json +1 -1
|
@@ -76,12 +76,18 @@ public class DownloadService extends Worker {
|
|
|
76
76
|
public static final String DEFAULT_CHANNEL = "default_channel";
|
|
77
77
|
public static final String IS_PROD = "is_prod";
|
|
78
78
|
public static final String IS_EMULATOR = "is_emulator";
|
|
79
|
-
// HTTP + decode share one pool. Cap by CPU: 8 on 4 cores, 16 on 8 cores
|
|
79
|
+
// HTTP + decode share one pool. Cap per host by CPU: 8 on 4 cores, 16 on 8 cores.
|
|
80
|
+
// Keep the global cap at 64 so API calls on another host are not starved by manifest downloads.
|
|
80
81
|
private static final int MANIFEST_MAX_CONCURRENT_FILES = manifestMaxConcurrentFiles();
|
|
82
|
+
private static final int SHARED_MAX_REQUESTS = 64;
|
|
81
83
|
private static final String UPDATE_FILE = "update.dat";
|
|
82
84
|
|
|
83
85
|
// Shared OkHttpClient to prevent resource leaks
|
|
84
|
-
protected static OkHttpClient sharedClient;
|
|
86
|
+
protected static volatile OkHttpClient sharedClient;
|
|
87
|
+
private static final Object HTTP_CLIENT_LOCK = new Object();
|
|
88
|
+
// Match CapgoUpdater.timeout / responseTimeout default (20s). OkHttp's 10s
|
|
89
|
+
// defaults were unused by the plugin config and aborted slow manifest GETs.
|
|
90
|
+
private static volatile int httpTimeoutMs = 20_000;
|
|
85
91
|
private static String currentAppId = "unknown";
|
|
86
92
|
private static String currentPluginVersion = "unknown";
|
|
87
93
|
private static String currentVersionOs = "unknown";
|
|
@@ -89,11 +95,14 @@ public class DownloadService extends Worker {
|
|
|
89
95
|
// Initialize shared client with User-Agent interceptor
|
|
90
96
|
static {
|
|
91
97
|
Dispatcher dispatcher = new Dispatcher();
|
|
92
|
-
dispatcher.setMaxRequests(
|
|
98
|
+
dispatcher.setMaxRequests(SHARED_MAX_REQUESTS);
|
|
93
99
|
dispatcher.setMaxRequestsPerHost(MANIFEST_MAX_CONCURRENT_FILES);
|
|
94
100
|
sharedClient = new OkHttpClient.Builder()
|
|
95
101
|
.dispatcher(dispatcher)
|
|
96
102
|
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
|
|
103
|
+
.connectTimeout(httpTimeoutMs, TimeUnit.MILLISECONDS)
|
|
104
|
+
.readTimeout(httpTimeoutMs, TimeUnit.MILLISECONDS)
|
|
105
|
+
.writeTimeout(httpTimeoutMs, TimeUnit.MILLISECONDS)
|
|
97
106
|
.addInterceptor((chain) -> {
|
|
98
107
|
Request originalRequest = chain.request();
|
|
99
108
|
String userAgent = buildUserAgent(currentAppId, currentPluginVersion, currentVersionOs);
|
|
@@ -103,6 +112,32 @@ public class DownloadService extends Worker {
|
|
|
103
112
|
.build();
|
|
104
113
|
}
|
|
105
114
|
|
|
115
|
+
static int httpTimeoutMs() {
|
|
116
|
+
return httpTimeoutMs;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static void applyHttpTimeouts(int timeoutMs) {
|
|
120
|
+
// OkHttp treats 0 as infinite; keep plugin responseTimeout floor (20s default).
|
|
121
|
+
int ms = timeoutMs > 0 ? timeoutMs : 20_000;
|
|
122
|
+
synchronized (HTTP_CLIENT_LOCK) {
|
|
123
|
+
if (
|
|
124
|
+
sharedClient.connectTimeoutMillis() == ms &&
|
|
125
|
+
sharedClient.readTimeoutMillis() == ms &&
|
|
126
|
+
sharedClient.writeTimeoutMillis() == ms
|
|
127
|
+
) {
|
|
128
|
+
httpTimeoutMs = ms;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
sharedClient = sharedClient
|
|
132
|
+
.newBuilder()
|
|
133
|
+
.connectTimeout(ms, TimeUnit.MILLISECONDS)
|
|
134
|
+
.readTimeout(ms, TimeUnit.MILLISECONDS)
|
|
135
|
+
.writeTimeout(ms, TimeUnit.MILLISECONDS)
|
|
136
|
+
.build();
|
|
137
|
+
httpTimeoutMs = ms;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
106
141
|
static int manifestMaxConcurrentFiles() {
|
|
107
142
|
return manifestMaxConcurrentFiles(Runtime.getRuntime().availableProcessors());
|
|
108
143
|
}
|
|
@@ -340,10 +375,12 @@ public class DownloadService extends Worker {
|
|
|
340
375
|
logger.debug("doWork isManifest: " + isManifest);
|
|
341
376
|
|
|
342
377
|
if (isManifest) {
|
|
343
|
-
JSONArray manifest = DataManager.getInstance().getAndClearManifest();
|
|
378
|
+
JSONArray manifest = DataManager.getInstance().getAndClearManifest(id);
|
|
344
379
|
if (manifest != null) {
|
|
345
380
|
handleManifestDownload(id, documentsDir, dest, version, sessionKey, publicKey, manifest);
|
|
346
381
|
return createSuccessResult(dest, version, sessionKey, checksum, true);
|
|
382
|
+
} else if (isStopped()) {
|
|
383
|
+
return createFailureResult("download_cancelled");
|
|
347
384
|
} else {
|
|
348
385
|
logger.error("Manifest is null");
|
|
349
386
|
return createFailureResult("Manifest is null");
|
|
@@ -524,8 +561,7 @@ public class DownloadService extends Worker {
|
|
|
524
561
|
try {
|
|
525
562
|
if (tryCopyBuiltinAsset(assets, fileName, targetFile, finalFileHash)) {
|
|
526
563
|
logger.debug("using builtin asset " + fileName);
|
|
527
|
-
} else if (
|
|
528
|
-
copyFile(builtinFile, targetFile);
|
|
564
|
+
} else if (tryCopyBuiltinFile(builtinFile, targetFile, finalFileHash)) {
|
|
529
565
|
logger.debug("using builtin file " + fileName);
|
|
530
566
|
} else if (
|
|
531
567
|
tryCopyFromCache(cacheFile, targetFile, finalFileHash) ||
|
|
@@ -624,9 +660,11 @@ public class DownloadService extends Worker {
|
|
|
624
660
|
URL u = new URL(url);
|
|
625
661
|
httpConn = (HttpURLConnection) u.openConnection();
|
|
626
662
|
|
|
627
|
-
//
|
|
628
|
-
|
|
629
|
-
|
|
663
|
+
// Zip can stall longer than a JSON API call; keep a floor so
|
|
664
|
+
// responseTimeout cannot shrink large-bundle downloads.
|
|
665
|
+
int zipTimeoutMs = Math.max(httpTimeoutMs, 60_000);
|
|
666
|
+
httpConn.setConnectTimeout(zipTimeoutMs);
|
|
667
|
+
httpConn.setReadTimeout(zipTimeoutMs);
|
|
630
668
|
|
|
631
669
|
// Reading progress file (if exist)
|
|
632
670
|
long downloadedBytes = 0;
|
|
@@ -676,7 +714,7 @@ public class DownloadService extends Worker {
|
|
|
676
714
|
writer = null;
|
|
677
715
|
}
|
|
678
716
|
|
|
679
|
-
byte[] buffer = new byte[
|
|
717
|
+
byte[] buffer = new byte[CryptoCipher.ioBufferBytes()];
|
|
680
718
|
int lastNotifiedPercent = 0;
|
|
681
719
|
int bytesRead;
|
|
682
720
|
|
|
@@ -799,6 +837,10 @@ public class DownloadService extends Worker {
|
|
|
799
837
|
}
|
|
800
838
|
|
|
801
839
|
private void copyFile(File source, File dest) throws IOException {
|
|
840
|
+
copyFileChannel(source, dest);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
static void copyFileChannel(final File source, final File dest) throws IOException {
|
|
802
844
|
final File parent = dest.getParentFile();
|
|
803
845
|
if (parent != null && !parent.exists() && !parent.mkdirs()) {
|
|
804
846
|
throw new IOException("Failed to create parent directory: " + parent.getAbsolutePath());
|
|
@@ -905,12 +947,9 @@ public class DownloadService extends Worker {
|
|
|
905
947
|
} catch (IOException e) {
|
|
906
948
|
String msg = e.getMessage();
|
|
907
949
|
if (msg != null && msg.contains("Checksum verification failed")) {
|
|
908
|
-
if (finalTargetFile.exists() && !finalTargetFile.delete()) {
|
|
909
|
-
logger.debug("Failed to delete dest after checksum mismatch");
|
|
910
|
-
}
|
|
911
950
|
sendStatsAsync("download_manifest_checksum_fail", getInputData().getString(VERSION) + ":" + finalTargetFile.getName());
|
|
912
951
|
keepPartial = false;
|
|
913
|
-
} else if (isBrotli) {
|
|
952
|
+
} else if (isBrotli && msg != null && msg.toLowerCase(java.util.Locale.US).contains("brotli")) {
|
|
914
953
|
sendStatsAsync("download_manifest_brotli_fail", getInputData().getString(VERSION) + ":" + finalTargetFile.getName());
|
|
915
954
|
keepPartial = false;
|
|
916
955
|
}
|
|
@@ -947,7 +986,8 @@ public class DownloadService extends Worker {
|
|
|
947
986
|
if (CapgoUpdater.isSafeCacheHash(hash) && hash.length() == 64) {
|
|
948
987
|
return new File(cacheDir, "partial_" + hash + "_" + token + ".tmp");
|
|
949
988
|
}
|
|
950
|
-
|
|
989
|
+
String digest = CryptoCipher.shortPathKey((hash == null ? "" : hash) + "\0" + (fileName == null ? "" : fileName));
|
|
990
|
+
return new File(cacheDir, "partial_" + digest + "_" + token + ".tmp");
|
|
951
991
|
}
|
|
952
992
|
|
|
953
993
|
static boolean shouldAppendHttpBody(int statusCode, long existingBytes) {
|
|
@@ -971,33 +1011,19 @@ public class DownloadService extends Worker {
|
|
|
971
1011
|
}
|
|
972
1012
|
}
|
|
973
1013
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
String actualHash = calculateFileHash(file);
|
|
977
|
-
return actualHash.equalsIgnoreCase(expectedHash);
|
|
978
|
-
} catch (Exception e) {
|
|
979
|
-
e.printStackTrace();
|
|
1014
|
+
static boolean tryCopyBuiltinFile(final File builtinFile, final File dest, final String expectedHash) {
|
|
1015
|
+
if (builtinFile == null || dest == null || expectedHash == null || expectedHash.isEmpty() || !builtinFile.isFile()) {
|
|
980
1016
|
return false;
|
|
981
1017
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
|
986
|
-
byte[] byteArray = new byte[1024];
|
|
987
|
-
int bytesCount = 0;
|
|
988
|
-
|
|
989
|
-
try (FileInputStream fis = new FileInputStream(file)) {
|
|
990
|
-
while ((bytesCount = fis.read(byteArray)) != -1) {
|
|
991
|
-
digest.update(byteArray, 0, bytesCount);
|
|
1018
|
+
try {
|
|
1019
|
+
if (!expectedHash.equalsIgnoreCase(CryptoCipher.calcChecksum(builtinFile))) {
|
|
1020
|
+
return false;
|
|
992
1021
|
}
|
|
1022
|
+
copyFileChannel(builtinFile, dest);
|
|
1023
|
+
return true;
|
|
1024
|
+
} catch (IOException e) {
|
|
1025
|
+
return false;
|
|
993
1026
|
}
|
|
994
|
-
|
|
995
|
-
byte[] bytes = digest.digest();
|
|
996
|
-
StringBuilder sb = new StringBuilder();
|
|
997
|
-
for (byte aByte : bytes) {
|
|
998
|
-
sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
|
|
999
|
-
}
|
|
1000
|
-
return sb.toString();
|
|
1001
1027
|
}
|
|
1002
1028
|
|
|
1003
1029
|
static void decompressBrotli(File input, File output, String fileName) throws IOException {
|
|
@@ -1062,7 +1088,7 @@ public class DownloadService extends Worker {
|
|
|
1062
1088
|
}
|
|
1063
1089
|
}
|
|
1064
1090
|
logger.error("Error: Raw data (" + fileName + "): " + hexDump);
|
|
1065
|
-
throw e;
|
|
1091
|
+
throw new IOException("Brotli process failed for " + fileName + ": " + e.getMessage(), e);
|
|
1066
1092
|
}
|
|
1067
1093
|
}
|
|
1068
1094
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package ee.forgr.capacitor_updater;
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
|
+
import android.os.Build;
|
|
4
5
|
import androidx.work.BackoffPolicy;
|
|
5
6
|
import androidx.work.Configuration;
|
|
6
7
|
import androidx.work.Constraints;
|
|
@@ -8,9 +9,18 @@ import androidx.work.Data;
|
|
|
8
9
|
import androidx.work.ExistingWorkPolicy;
|
|
9
10
|
import androidx.work.NetworkType;
|
|
10
11
|
import androidx.work.OneTimeWorkRequest;
|
|
12
|
+
import androidx.work.OutOfQuotaPolicy;
|
|
13
|
+
import androidx.work.WorkInfo;
|
|
11
14
|
import androidx.work.WorkManager;
|
|
12
15
|
import androidx.work.WorkRequest;
|
|
16
|
+
import java.util.HashSet;
|
|
17
|
+
import java.util.List;
|
|
18
|
+
import java.util.Set;
|
|
19
|
+
import java.util.concurrent.ExecutorService;
|
|
20
|
+
import java.util.concurrent.Executors;
|
|
21
|
+
import java.util.concurrent.Future;
|
|
13
22
|
import java.util.concurrent.TimeUnit;
|
|
23
|
+
import java.util.concurrent.TimeoutException;
|
|
14
24
|
|
|
15
25
|
public class DownloadWorkerManager {
|
|
16
26
|
|
|
@@ -21,6 +31,7 @@ public class DownloadWorkerManager {
|
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
private static volatile boolean isInitialized = false;
|
|
34
|
+
private static final ExecutorService cancelExecutor = Executors.newSingleThreadExecutor();
|
|
24
35
|
|
|
25
36
|
private static synchronized void initializeIfNeeded(Context context) {
|
|
26
37
|
if (!isInitialized) {
|
|
@@ -120,6 +131,11 @@ public class DownloadWorkerManager {
|
|
|
120
131
|
.addTag(id)
|
|
121
132
|
.addTag(version)
|
|
122
133
|
.addTag("capacitor_updater_download");
|
|
134
|
+
// Android 12+ expedited jobs skip the WorkManager delay without a
|
|
135
|
+
// foreground service. Older APIs require getForegroundInfo().
|
|
136
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
137
|
+
workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST);
|
|
138
|
+
}
|
|
123
139
|
|
|
124
140
|
// More aggressive retry policy for emulators
|
|
125
141
|
if (isEmulator) {
|
|
@@ -142,17 +158,101 @@ public class DownloadWorkerManager {
|
|
|
142
158
|
|
|
143
159
|
public static void cancelVersionDownload(Context context, String version) {
|
|
144
160
|
initializeIfNeeded(context.getApplicationContext());
|
|
145
|
-
|
|
161
|
+
cancelExecutor.execute(() -> cancelVersionDownloadInternal(context, version, false));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public static boolean cancelVersionDownloadAndAwait(Context context, String version) {
|
|
165
|
+
initializeIfNeeded(context.getApplicationContext());
|
|
166
|
+
Future<?> future = cancelExecutor.submit(() -> cancelVersionDownloadInternal(context, version, true));
|
|
167
|
+
try {
|
|
168
|
+
future.get(10, TimeUnit.SECONDS);
|
|
169
|
+
return true;
|
|
170
|
+
} catch (TimeoutException e) {
|
|
171
|
+
future.cancel(true);
|
|
172
|
+
logger.error("Timed out awaiting version download cancel");
|
|
173
|
+
return false;
|
|
174
|
+
} catch (Exception e) {
|
|
175
|
+
logger.error("Error awaiting version download cancel: " + e.getMessage());
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private static Set<String> collectManifestIdsForVersion(WorkManager workManager, String version) {
|
|
181
|
+
Set<String> downloadIds = new HashSet<>();
|
|
182
|
+
try {
|
|
183
|
+
List<WorkInfo> workInfos = workManager.getWorkInfosByTag(version).get();
|
|
184
|
+
for (WorkInfo workInfo : workInfos) {
|
|
185
|
+
for (String tag : workInfo.getTags()) {
|
|
186
|
+
if (!"capacitor_updater_download".equals(tag) && !version.equals(tag)) {
|
|
187
|
+
downloadIds.add(tag);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
} catch (InterruptedException e) {
|
|
192
|
+
Thread.currentThread().interrupt();
|
|
193
|
+
throw new IllegalStateException("Interrupted while collecting manifest ids before version cancel", e);
|
|
194
|
+
} catch (Exception e) {
|
|
195
|
+
logger.error("Error collecting manifest ids before version cancel: " + e.getMessage());
|
|
196
|
+
}
|
|
197
|
+
return downloadIds;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private static void clearManifestIds(Set<String> downloadIds) {
|
|
201
|
+
for (String downloadId : downloadIds) {
|
|
202
|
+
DataManager.getInstance().clearManifest(downloadId);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private static void cancelVersionDownloadInternal(Context context, String version, boolean awaitFinished) {
|
|
207
|
+
if (Thread.currentThread().isInterrupted()) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
WorkManager workManager = WorkManager.getInstance(context);
|
|
211
|
+
Set<String> downloadIds = collectManifestIdsForVersion(workManager, version);
|
|
212
|
+
workManager.cancelAllWorkByTag(version);
|
|
213
|
+
clearManifestIds(downloadIds);
|
|
214
|
+
if (awaitFinished) {
|
|
215
|
+
awaitVersionWorkFinished(workManager, version);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private static void awaitVersionWorkFinished(WorkManager workManager, String version) {
|
|
220
|
+
for (int i = 0; i < 100; i++) {
|
|
221
|
+
if (Thread.currentThread().isInterrupted()) {
|
|
222
|
+
throw new IllegalStateException("Interrupted while waiting for version download cancel");
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
boolean anyActive = workManager
|
|
226
|
+
.getWorkInfosByTag(version)
|
|
227
|
+
.get()
|
|
228
|
+
.stream()
|
|
229
|
+
.anyMatch((workInfo) -> !workInfo.getState().isFinished());
|
|
230
|
+
if (!anyActive) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
Thread.sleep(100);
|
|
234
|
+
} catch (InterruptedException e) {
|
|
235
|
+
Thread.currentThread().interrupt();
|
|
236
|
+
throw new IllegalStateException("Interrupted while waiting for download cancel", e);
|
|
237
|
+
} catch (Exception e) {
|
|
238
|
+
throw new IllegalStateException("Error waiting for download cancel: " + e.getMessage(), e);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
throw new IllegalStateException("Timed out waiting for version download cancel: " + version);
|
|
146
242
|
}
|
|
147
243
|
|
|
148
244
|
public static void cancelBundleDownload(Context context, String id, String version) {
|
|
149
245
|
String uniqueWorkName = "bundle_" + id + "_" + version;
|
|
150
246
|
initializeIfNeeded(context.getApplicationContext());
|
|
151
|
-
WorkManager.getInstance(context)
|
|
247
|
+
WorkManager workManager = WorkManager.getInstance(context);
|
|
248
|
+
workManager.cancelUniqueWork(uniqueWorkName);
|
|
249
|
+
DataManager.getInstance().clearManifest(id);
|
|
152
250
|
}
|
|
153
251
|
|
|
154
252
|
public static void cancelAllDownloads(Context context) {
|
|
155
253
|
initializeIfNeeded(context.getApplicationContext());
|
|
156
|
-
WorkManager.getInstance(context)
|
|
254
|
+
WorkManager workManager = WorkManager.getInstance(context);
|
|
255
|
+
workManager.cancelAllWorkByTag("capacitor_updater_download");
|
|
256
|
+
DataManager.getInstance().clearAllManifests();
|
|
157
257
|
}
|
|
158
258
|
}
|
|
@@ -238,6 +238,9 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
|
|
|
238
238
|
|
|
239
239
|
private void setPreviewMenuButtonsEnabled(List<Button> buttons, boolean enabled) {
|
|
240
240
|
for (Button button : buttons) {
|
|
241
|
+
if (!enabled && "Close menu".equals(button.getText().toString())) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
241
244
|
button.setEnabled(enabled);
|
|
242
245
|
}
|
|
243
246
|
}
|
package/dist/docs.json
CHANGED
|
@@ -4583,7 +4583,7 @@
|
|
|
4583
4583
|
"name": "example"
|
|
4584
4584
|
}
|
|
4585
4585
|
],
|
|
4586
|
-
"docs": "Configure the number of seconds the native plugin should wait before considering
|
|
4586
|
+
"docs": "Configure the number of seconds the native plugin should wait before considering an HTTP timeout.\nApplies to update checks and file downloads. On Android these are idle connect/read/write\ntimeouts and do not cap total download time; on iOS the request timeout also bounds the\ntotal download duration.\n\nOnly available for Android and iOS.",
|
|
4587
4587
|
"complexTypes": [],
|
|
4588
4588
|
"type": "number | undefined"
|
|
4589
4589
|
},
|
|
@@ -15,7 +15,10 @@ declare module '@capacitor/cli' {
|
|
|
15
15
|
*/
|
|
16
16
|
appReadyTimeout?: number;
|
|
17
17
|
/**
|
|
18
|
-
* Configure the number of seconds the native plugin should wait before considering
|
|
18
|
+
* Configure the number of seconds the native plugin should wait before considering an HTTP timeout.
|
|
19
|
+
* Applies to update checks and file downloads. On Android these are idle connect/read/write
|
|
20
|
+
* timeouts and do not cap total download time; on iOS the request timeout also bounds the
|
|
21
|
+
* total download duration.
|
|
19
22
|
*
|
|
20
23
|
* Only available for Android and iOS.
|
|
21
24
|
*
|