@capgo/capacitor-updater 6.14.36 → 6.25.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +4 -4
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +11 -3
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +101 -2
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadWorkerManager.java +19 -2
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +3 -3
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +22 -3
- package/package.json +1 -1
|
@@ -71,7 +71,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
71
71
|
private static final String[] BREAKING_EVENT_NAMES = { "breakingAvailable", "majorAvailable" };
|
|
72
72
|
private static final String LAST_FAILED_BUNDLE_PREF_KEY = "CapacitorUpdater.lastFailedBundle";
|
|
73
73
|
|
|
74
|
-
private final String
|
|
74
|
+
private final String pluginVersion = "6.25.3";
|
|
75
75
|
private static final String DELAY_CONDITION_PREFERENCES = "";
|
|
76
76
|
|
|
77
77
|
private SharedPreferences.Editor editor;
|
|
@@ -220,7 +220,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
220
220
|
this.implementation.activity = this.getActivity();
|
|
221
221
|
this.implementation.versionBuild = this.getConfig().getString("version", pInfo.versionName);
|
|
222
222
|
this.implementation.CAP_SERVER_PATH = WebView.CAP_SERVER_PATH;
|
|
223
|
-
this.implementation.
|
|
223
|
+
this.implementation.pluginVersion = this.pluginVersion;
|
|
224
224
|
this.implementation.versionCode = Integer.toString(pInfo.versionCode);
|
|
225
225
|
// Removed unused OkHttpClient creation - using shared client in DownloadService instead
|
|
226
226
|
// Handle directUpdate configuration - support string values and backward compatibility
|
|
@@ -334,7 +334,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
334
334
|
this.implementation.deviceID = DeviceIdHelper.getOrCreateDeviceId(this.getContext(), this.prefs);
|
|
335
335
|
|
|
336
336
|
// Update User-Agent for shared OkHttpClient with OS version
|
|
337
|
-
DownloadService.updateUserAgent(this.implementation.appId, this.
|
|
337
|
+
DownloadService.updateUserAgent(this.implementation.appId, this.pluginVersion, this.implementation.versionOs);
|
|
338
338
|
|
|
339
339
|
if (Boolean.TRUE.equals(this.persistCustomId)) {
|
|
340
340
|
final String storedCustomId = this.prefs.getString(CUSTOM_ID_PREF_KEY, "");
|
|
@@ -841,7 +841,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
841
841
|
public void getPluginVersion(final PluginCall call) {
|
|
842
842
|
try {
|
|
843
843
|
final JSObject ret = new JSObject();
|
|
844
|
-
ret.put("version", this.
|
|
844
|
+
ret.put("version", this.pluginVersion);
|
|
845
845
|
call.resolve(ret);
|
|
846
846
|
} catch (final Exception e) {
|
|
847
847
|
logger.error("Could not get plugin version " + e.getMessage());
|
|
@@ -66,7 +66,7 @@ public class CapgoUpdater {
|
|
|
66
66
|
public File documentsDir;
|
|
67
67
|
public Boolean directUpdate = false;
|
|
68
68
|
public Activity activity;
|
|
69
|
-
public String
|
|
69
|
+
public String pluginVersion = "";
|
|
70
70
|
public String versionBuild = "";
|
|
71
71
|
public String versionCode = "";
|
|
72
72
|
public String versionOs = "";
|
|
@@ -355,7 +355,15 @@ public class CapgoUpdater {
|
|
|
355
355
|
manifest != null,
|
|
356
356
|
this.isEmulator(),
|
|
357
357
|
this.appId,
|
|
358
|
-
this.
|
|
358
|
+
this.pluginVersion,
|
|
359
|
+
this.isProd(),
|
|
360
|
+
this.statsUrl,
|
|
361
|
+
this.deviceID,
|
|
362
|
+
this.versionBuild,
|
|
363
|
+
this.versionCode,
|
|
364
|
+
this.versionOs,
|
|
365
|
+
this.customId,
|
|
366
|
+
this.defaultChannel
|
|
359
367
|
);
|
|
360
368
|
|
|
361
369
|
if (manifest != null) {
|
|
@@ -782,7 +790,7 @@ public class CapgoUpdater {
|
|
|
782
790
|
json.put("version_code", this.versionCode);
|
|
783
791
|
json.put("version_os", this.versionOs);
|
|
784
792
|
json.put("version_name", this.getCurrentBundle().getVersionName());
|
|
785
|
-
json.put("plugin_version", this.
|
|
793
|
+
json.put("plugin_version", this.pluginVersion);
|
|
786
794
|
json.put("is_emulator", this.isEmulator());
|
|
787
795
|
json.put("is_prod", this.isProd());
|
|
788
796
|
json.put("defaultChannel", this.defaultChannel);
|
|
@@ -28,10 +28,14 @@ import java.util.concurrent.Future;
|
|
|
28
28
|
import java.util.concurrent.TimeUnit;
|
|
29
29
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
30
30
|
import java.util.concurrent.atomic.AtomicLong;
|
|
31
|
+
import okhttp3.Call;
|
|
32
|
+
import okhttp3.Callback;
|
|
31
33
|
import okhttp3.Interceptor;
|
|
34
|
+
import okhttp3.MediaType;
|
|
32
35
|
import okhttp3.OkHttpClient;
|
|
33
36
|
import okhttp3.Protocol;
|
|
34
37
|
import okhttp3.Request;
|
|
38
|
+
import okhttp3.RequestBody;
|
|
35
39
|
import okhttp3.Response;
|
|
36
40
|
import okhttp3.ResponseBody;
|
|
37
41
|
import okio.Buffer;
|
|
@@ -63,7 +67,16 @@ public class DownloadService extends Worker {
|
|
|
63
67
|
public static final String PUBLIC_KEY = "publickey";
|
|
64
68
|
public static final String IS_MANIFEST = "is_manifest";
|
|
65
69
|
public static final String APP_ID = "app_id";
|
|
66
|
-
public static final String
|
|
70
|
+
public static final String pluginVersion = "plugin_version";
|
|
71
|
+
public static final String STATS_URL = "stats_url";
|
|
72
|
+
public static final String DEVICE_ID = "device_id";
|
|
73
|
+
public static final String CUSTOM_ID = "custom_id";
|
|
74
|
+
public static final String VERSION_BUILD = "version_build";
|
|
75
|
+
public static final String VERSION_CODE = "version_code";
|
|
76
|
+
public static final String VERSION_OS = "version_os";
|
|
77
|
+
public static final String DEFAULT_CHANNEL = "default_channel";
|
|
78
|
+
public static final String IS_PROD = "is_prod";
|
|
79
|
+
public static final String IS_EMULATOR = "is_emulator";
|
|
67
80
|
private static final String UPDATE_FILE = "update.dat";
|
|
68
81
|
|
|
69
82
|
// Shared OkHttpClient to prevent resource leaks
|
|
@@ -130,6 +143,11 @@ public class DownloadService extends Worker {
|
|
|
130
143
|
return Result.success(output);
|
|
131
144
|
}
|
|
132
145
|
|
|
146
|
+
private String getInputString(String key, String fallback) {
|
|
147
|
+
String value = getInputData().getString(key);
|
|
148
|
+
return value != null ? value : fallback;
|
|
149
|
+
}
|
|
150
|
+
|
|
133
151
|
@NonNull
|
|
134
152
|
@Override
|
|
135
153
|
public Result doWork() {
|
|
@@ -174,6 +192,62 @@ public class DownloadService extends Worker {
|
|
|
174
192
|
return percent;
|
|
175
193
|
}
|
|
176
194
|
|
|
195
|
+
private void sendStatsAsync(String action, String version) {
|
|
196
|
+
try {
|
|
197
|
+
String statsUrl = getInputData().getString(STATS_URL);
|
|
198
|
+
if (statsUrl == null || statsUrl.isEmpty()) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
JSONObject json = new JSONObject();
|
|
203
|
+
json.put("platform", "android");
|
|
204
|
+
json.put("app_id", getInputString(APP_ID, "unknown"));
|
|
205
|
+
json.put("plugin_version", getInputString(pluginVersion, "unknown"));
|
|
206
|
+
json.put("version_name", version != null ? version : "");
|
|
207
|
+
json.put("old_version_name", "");
|
|
208
|
+
json.put("action", action);
|
|
209
|
+
json.put("device_id", getInputString(DEVICE_ID, ""));
|
|
210
|
+
json.put("custom_id", getInputString(CUSTOM_ID, ""));
|
|
211
|
+
json.put("version_build", getInputString(VERSION_BUILD, ""));
|
|
212
|
+
json.put("version_code", getInputString(VERSION_CODE, ""));
|
|
213
|
+
json.put("version_os", getInputString(VERSION_OS, currentVersionOs));
|
|
214
|
+
json.put("defaultChannel", getInputString(DEFAULT_CHANNEL, ""));
|
|
215
|
+
json.put("is_prod", getInputData().getBoolean(IS_PROD, true));
|
|
216
|
+
json.put("is_emulator", getInputData().getBoolean(IS_EMULATOR, false));
|
|
217
|
+
|
|
218
|
+
Request request = new Request.Builder()
|
|
219
|
+
.url(statsUrl)
|
|
220
|
+
.post(RequestBody.create(json.toString(), MediaType.get("application/json")))
|
|
221
|
+
.build();
|
|
222
|
+
|
|
223
|
+
sharedClient
|
|
224
|
+
.newCall(request)
|
|
225
|
+
.enqueue(
|
|
226
|
+
new Callback() {
|
|
227
|
+
@Override
|
|
228
|
+
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
|
229
|
+
if (logger != null) {
|
|
230
|
+
logger.error("Failed to send stats: " + e.getMessage());
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@Override
|
|
235
|
+
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
|
236
|
+
try (ResponseBody body = response.body()) {
|
|
237
|
+
// nothing else to do, just closing body
|
|
238
|
+
} catch (Exception ignored) {} finally {
|
|
239
|
+
response.close();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
} catch (Exception e) {
|
|
245
|
+
if (logger != null) {
|
|
246
|
+
logger.error("sendStatsAsync error: " + e.getMessage());
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
177
251
|
private void handleManifestDownload(
|
|
178
252
|
String id,
|
|
179
253
|
String documentsDir,
|
|
@@ -185,6 +259,10 @@ public class DownloadService extends Worker {
|
|
|
185
259
|
) {
|
|
186
260
|
try {
|
|
187
261
|
logger.debug("handleManifestDownload");
|
|
262
|
+
|
|
263
|
+
// Send stats for manifest download start
|
|
264
|
+
sendStatsAsync("download_manifest_start", version);
|
|
265
|
+
|
|
188
266
|
JSONArray manifest = new JSONArray(manifestString);
|
|
189
267
|
File destFolder = new File(documentsDir, dest);
|
|
190
268
|
File cacheFolder = new File(getApplicationContext().getCacheDir(), "capgo_downloads");
|
|
@@ -252,6 +330,7 @@ public class DownloadService extends Worker {
|
|
|
252
330
|
setProgress(percent);
|
|
253
331
|
} catch (Exception e) {
|
|
254
332
|
logger.error("Error processing file: " + fileName + " " + e.getMessage());
|
|
333
|
+
sendStatsAsync("download_manifest_file_fail", version + ":" + fileName);
|
|
255
334
|
hasError.set(true);
|
|
256
335
|
}
|
|
257
336
|
});
|
|
@@ -282,6 +361,9 @@ public class DownloadService extends Worker {
|
|
|
282
361
|
logger.error("One or more files failed to download");
|
|
283
362
|
throw new IOException("One or more files failed to download");
|
|
284
363
|
}
|
|
364
|
+
|
|
365
|
+
// Send stats for manifest download complete
|
|
366
|
+
sendStatsAsync("download_manifest_complete", version);
|
|
285
367
|
} catch (Exception e) {
|
|
286
368
|
logger.error("Error in handleManifestDownload " + e.getMessage());
|
|
287
369
|
throw new RuntimeException(e.getLocalizedMessage());
|
|
@@ -297,6 +379,9 @@ public class DownloadService extends Worker {
|
|
|
297
379
|
String sessionKey,
|
|
298
380
|
String checksum
|
|
299
381
|
) {
|
|
382
|
+
// Send stats for zip download start
|
|
383
|
+
sendStatsAsync("download_zip_start", version);
|
|
384
|
+
|
|
300
385
|
File target = new File(documentsDir, dest);
|
|
301
386
|
File infoFile = new File(documentsDir, UPDATE_FILE);
|
|
302
387
|
File tempFile = new File(documentsDir, "temp" + ".tmp");
|
|
@@ -404,6 +489,9 @@ public class DownloadService extends Worker {
|
|
|
404
489
|
throw new RuntimeException("Failed to rename temp file to final destination");
|
|
405
490
|
}
|
|
406
491
|
infoFile.delete();
|
|
492
|
+
|
|
493
|
+
// Send stats for zip download complete
|
|
494
|
+
sendStatsAsync("download_zip_complete", version);
|
|
407
495
|
} catch (OutOfMemoryError e) {
|
|
408
496
|
logger.error("Out of memory during download: " + e.getMessage());
|
|
409
497
|
// Try to free some memory
|
|
@@ -503,6 +591,7 @@ public class DownloadService extends Worker {
|
|
|
503
591
|
|
|
504
592
|
try (Response response = sharedClient.newCall(request).execute()) {
|
|
505
593
|
if (!response.isSuccessful()) {
|
|
594
|
+
sendStatsAsync("download_manifest_file_fail", getInputData().getString(VERSION) + ":" + finalTargetFile.getName());
|
|
506
595
|
throw new IOException("Unexpected response code: " + response.code());
|
|
507
596
|
}
|
|
508
597
|
|
|
@@ -526,7 +615,16 @@ public class DownloadService extends Worker {
|
|
|
526
615
|
try (FileInputStream fis = new FileInputStream(compressedFile)) {
|
|
527
616
|
byte[] compressedData = new byte[(int) compressedFile.length()];
|
|
528
617
|
fis.read(compressedData);
|
|
529
|
-
byte[] decompressedData
|
|
618
|
+
byte[] decompressedData;
|
|
619
|
+
try {
|
|
620
|
+
decompressedData = decompressBrotli(compressedData, targetFile.getName());
|
|
621
|
+
} catch (IOException e) {
|
|
622
|
+
sendStatsAsync(
|
|
623
|
+
"download_manifest_brotli_fail",
|
|
624
|
+
getInputData().getString(VERSION) + ":" + finalTargetFile.getName()
|
|
625
|
+
);
|
|
626
|
+
throw e;
|
|
627
|
+
}
|
|
530
628
|
|
|
531
629
|
// Write decompressed data atomically
|
|
532
630
|
try (java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(decompressedData)) {
|
|
@@ -552,6 +650,7 @@ public class DownloadService extends Worker {
|
|
|
552
650
|
}
|
|
553
651
|
} else {
|
|
554
652
|
finalTargetFile.delete();
|
|
653
|
+
sendStatsAsync("download_manifest_checksum_fail", getInputData().getString(VERSION) + ":" + finalTargetFile.getName());
|
|
555
654
|
throw new IOException(
|
|
556
655
|
"Checksum verification failed for: " +
|
|
557
656
|
downloadUrl +
|
|
@@ -61,7 +61,15 @@ public class DownloadWorkerManager {
|
|
|
61
61
|
boolean isManifest,
|
|
62
62
|
boolean isEmulator,
|
|
63
63
|
String appId,
|
|
64
|
-
String pluginVersion
|
|
64
|
+
String pluginVersion,
|
|
65
|
+
boolean isProd,
|
|
66
|
+
String statsUrl,
|
|
67
|
+
String deviceId,
|
|
68
|
+
String versionBuild,
|
|
69
|
+
String versionCode,
|
|
70
|
+
String versionOs,
|
|
71
|
+
String customId,
|
|
72
|
+
String defaultChannel
|
|
65
73
|
) {
|
|
66
74
|
initializeIfNeeded(context.getApplicationContext());
|
|
67
75
|
|
|
@@ -80,7 +88,16 @@ public class DownloadWorkerManager {
|
|
|
80
88
|
.putBoolean(DownloadService.IS_MANIFEST, isManifest)
|
|
81
89
|
.putString(DownloadService.PUBLIC_KEY, publicKey)
|
|
82
90
|
.putString(DownloadService.APP_ID, appId)
|
|
83
|
-
.putString(DownloadService.
|
|
91
|
+
.putString(DownloadService.pluginVersion, pluginVersion)
|
|
92
|
+
.putString(DownloadService.STATS_URL, statsUrl)
|
|
93
|
+
.putString(DownloadService.DEVICE_ID, deviceId)
|
|
94
|
+
.putString(DownloadService.VERSION_BUILD, versionBuild)
|
|
95
|
+
.putString(DownloadService.VERSION_CODE, versionCode)
|
|
96
|
+
.putString(DownloadService.VERSION_OS, versionOs)
|
|
97
|
+
.putString(DownloadService.CUSTOM_ID, customId)
|
|
98
|
+
.putString(DownloadService.DEFAULT_CHANNEL, defaultChannel)
|
|
99
|
+
.putBoolean(DownloadService.IS_PROD, isProd)
|
|
100
|
+
.putBoolean(DownloadService.IS_EMULATOR, isEmulator)
|
|
84
101
|
.build();
|
|
85
102
|
|
|
86
103
|
// Create network constraints - be more lenient on emulators
|
|
@@ -54,7 +54,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
54
54
|
CAPPluginMethod(name: "isShakeMenuEnabled", returnType: CAPPluginReturnPromise)
|
|
55
55
|
]
|
|
56
56
|
public var implementation = CapgoUpdater()
|
|
57
|
-
private let
|
|
57
|
+
private let pluginVersion: String = "6.25.3"
|
|
58
58
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
59
59
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|
|
60
60
|
static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
|
|
@@ -193,7 +193,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
193
193
|
implementation.hasOldPrivateKeyPropertyInConfig = true
|
|
194
194
|
}
|
|
195
195
|
implementation.notifyDownloadRaw = notifyDownload
|
|
196
|
-
implementation.
|
|
196
|
+
implementation.pluginVersion = self.pluginVersion
|
|
197
197
|
|
|
198
198
|
// Set logger for shared classes
|
|
199
199
|
implementation.setLogger(logger)
|
|
@@ -448,7 +448,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
@objc func getPluginVersion(_ call: CAPPluginCall) {
|
|
451
|
-
call.resolve(["version": self.
|
|
451
|
+
call.resolve(["version": self.pluginVersion])
|
|
452
452
|
}
|
|
453
453
|
|
|
454
454
|
@objc func download(_ call: CAPPluginCall) {
|
|
@@ -33,7 +33,7 @@ import UIKit
|
|
|
33
33
|
public let CAP_SERVER_PATH: String = "serverBasePath"
|
|
34
34
|
public var versionBuild: String = ""
|
|
35
35
|
public var customId: String = ""
|
|
36
|
-
public var
|
|
36
|
+
public var pluginVersion: String = ""
|
|
37
37
|
public var timeout: Double = 20
|
|
38
38
|
public var statsUrl: String = ""
|
|
39
39
|
public var channelUrl: String = ""
|
|
@@ -51,7 +51,7 @@ import UIKit
|
|
|
51
51
|
private static var rateLimitStatisticSent = false
|
|
52
52
|
|
|
53
53
|
private var userAgent: String {
|
|
54
|
-
let safePluginVersion =
|
|
54
|
+
let safePluginVersion = pluginVersion.isEmpty ? "unknown" : pluginVersion
|
|
55
55
|
let safeAppId = appId.isEmpty ? "unknown" : appId
|
|
56
56
|
return "CapacitorUpdater/\(safePluginVersion) (\(safeAppId)) ios/\(versionOs)"
|
|
57
57
|
}
|
|
@@ -315,7 +315,7 @@ import UIKit
|
|
|
315
315
|
version_code: self.versionCode,
|
|
316
316
|
version_os: self.versionOs,
|
|
317
317
|
version_name: self.getCurrentBundle().getVersionName(),
|
|
318
|
-
plugin_version: self.
|
|
318
|
+
plugin_version: self.pluginVersion,
|
|
319
319
|
is_emulator: self.isEmulator(),
|
|
320
320
|
is_prod: self.isProd(),
|
|
321
321
|
action: nil,
|
|
@@ -411,6 +411,9 @@ import UIKit
|
|
|
411
411
|
let bundleInfo = BundleInfo(id: id, version: version, status: BundleStatus.DOWNLOADING, downloaded: Date(), checksum: "")
|
|
412
412
|
self.saveBundleInfo(id: id, bundle: bundleInfo)
|
|
413
413
|
|
|
414
|
+
// Send stats for manifest download start
|
|
415
|
+
self.sendStats(action: "download_manifest_start", versionName: version)
|
|
416
|
+
|
|
414
417
|
// Notify the start of the download process
|
|
415
418
|
self.notifyDownload(id: id, percent: 0, ignoreMultipleOfTen: true)
|
|
416
419
|
|
|
@@ -473,6 +476,7 @@ import UIKit
|
|
|
473
476
|
do {
|
|
474
477
|
let statusCode = response.response?.statusCode ?? 200
|
|
475
478
|
if statusCode < 200 || statusCode >= 300 {
|
|
479
|
+
self.sendStats(action: "download_manifest_file_fail", versionName: "\(version):\(fileName)")
|
|
476
480
|
if let stringData = String(data: data, encoding: .utf8) {
|
|
477
481
|
throw NSError(domain: "StatusCodeError", code: 2, userInfo: [NSLocalizedDescriptionKey: "Failed to fetch. Status code (\(statusCode)) invalid. Data: \(stringData) for file \(fileName) at url \(downloadUrl)"])
|
|
478
482
|
} else {
|
|
@@ -515,6 +519,7 @@ import UIKit
|
|
|
515
519
|
if isBrotli {
|
|
516
520
|
// Decompress the Brotli data
|
|
517
521
|
guard let decompressedData = self.decompressBrotli(data: finalData, fileName: fileName) else {
|
|
522
|
+
self.sendStats(action: "download_manifest_brotli_fail", versionName: "\(version):\(finalFileName)")
|
|
518
523
|
throw NSError(domain: "BrotliDecompressionError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to decompress Brotli data for file \(fileName) at url \(downloadUrl)"])
|
|
519
524
|
}
|
|
520
525
|
finalData = decompressedData
|
|
@@ -525,6 +530,7 @@ import UIKit
|
|
|
525
530
|
// assume that calcChecksum != null
|
|
526
531
|
let calculatedChecksum = CryptoCipherV2.calcChecksum(filePath: destFilePath)
|
|
527
532
|
if calculatedChecksum != fileHash {
|
|
533
|
+
self.sendStats(action: "download_manifest_checksum_fail", versionName: "\(version):\(finalFileName)")
|
|
528
534
|
throw NSError(domain: "ChecksumError", code: 1, userInfo: [NSLocalizedDescriptionKey: "Computed checksum is not equal to required checksum (\(calculatedChecksum) != \(fileHash)) for file \(fileName) at url \(downloadUrl)"])
|
|
529
535
|
}
|
|
530
536
|
}
|
|
@@ -540,6 +546,8 @@ import UIKit
|
|
|
540
546
|
self.logger.error("downloadManifest \(id) \(fileName) error: \(error.localizedDescription)")
|
|
541
547
|
}
|
|
542
548
|
case .failure(let error):
|
|
549
|
+
downloadError = error
|
|
550
|
+
self.sendStats(action: "download_manifest_file_fail", versionName: "\(version):\(fileName)")
|
|
543
551
|
self.logger.error("downloadManifest \(id) \(fileName) download error: \(error.localizedDescription). Debug response: \(response.debugDescription).")
|
|
544
552
|
}
|
|
545
553
|
}
|
|
@@ -559,6 +567,9 @@ import UIKit
|
|
|
559
567
|
let updatedBundle = bundleInfo.setStatus(status: BundleStatus.PENDING.localizedString)
|
|
560
568
|
self.saveBundleInfo(id: id, bundle: updatedBundle)
|
|
561
569
|
|
|
570
|
+
// Send stats for manifest download complete
|
|
571
|
+
self.sendStats(action: "download_manifest_complete", versionName: version)
|
|
572
|
+
|
|
562
573
|
logger.info("downloadManifest done \(id)")
|
|
563
574
|
return updatedBundle
|
|
564
575
|
}
|
|
@@ -689,6 +700,10 @@ import UIKit
|
|
|
689
700
|
var lastSentProgress = 0
|
|
690
701
|
var totalReceivedBytes: Int64 = loadDownloadProgress() // Retrieving the amount of already downloaded data if exist, defined at 0 otherwise
|
|
691
702
|
let requestHeaders: HTTPHeaders = ["Range": "bytes=\(totalReceivedBytes)-"]
|
|
703
|
+
|
|
704
|
+
// Send stats for zip download start
|
|
705
|
+
self.sendStats(action: "download_zip_start", versionName: version)
|
|
706
|
+
|
|
692
707
|
// Opening connection for streaming the bytes
|
|
693
708
|
if totalReceivedBytes == 0 {
|
|
694
709
|
self.notifyDownload(id: id, percent: 0, ignoreMultipleOfTen: true)
|
|
@@ -803,6 +818,10 @@ import UIKit
|
|
|
803
818
|
let info = BundleInfo(id: id, version: version, status: BundleStatus.PENDING, downloaded: Date(), checksum: checksum)
|
|
804
819
|
self.saveBundleInfo(id: id, bundle: info)
|
|
805
820
|
self.cleanDownloadData()
|
|
821
|
+
|
|
822
|
+
// Send stats for zip download complete
|
|
823
|
+
self.sendStats(action: "download_zip_complete", versionName: version)
|
|
824
|
+
|
|
806
825
|
self.notifyDownload(id: id, percent: 100)
|
|
807
826
|
logger.info("Downloading: 100% (complete)")
|
|
808
827
|
return info
|