@capgo/capacitor-updater 7.40.0 → 7.40.5

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/README.md CHANGED
@@ -257,7 +257,142 @@ Capacitor Updater works by unzipping a compiled app bundle to the native device
257
257
  <docgen-config>
258
258
  <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
259
259
 
260
+ CapacitorUpdater can be configured with these options:
261
+
262
+ | Prop | Type | Description | Default | Since |
263
+ | ----------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
264
+ | **`appReadyTimeout`** | <code>number</code> | Configure the number of milliseconds the native plugin should wait before considering an update 'failed'. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | |
265
+ | **`responseTimeout`** | <code>number</code> | Configure the number of seconds the native plugin should wait before considering API timeout. Only available for Android and iOS. | <code>20 // (20 second)</code> | |
266
+ | **`autoDeleteFailed`** | <code>boolean</code> | Configure whether the plugin should use automatically delete failed bundles. Only available for Android and iOS. | <code>true</code> | |
267
+ | **`autoDeletePrevious`** | <code>boolean</code> | Configure whether the plugin should use automatically delete previous bundles after a successful update. Only available for Android and iOS. | <code>true</code> | |
268
+ | **`autoUpdate`** | <code>boolean</code> | Configure whether the plugin should use Auto Update via an update server. Only available for Android and iOS. | <code>true</code> | |
269
+ | **`resetWhenUpdate`** | <code>boolean</code> | Automatically delete previous downloaded bundles when a newer native app bundle is installed to the device. Setting this to false can broke the auto update flow if the user download from the store a native app bundle that is older than the current downloaded bundle. Upload will be prevented by channel setting downgrade_under_native. Only available for Android and iOS. | <code>true</code> | |
270
+ | **`updateUrl`** | <code>string</code> | Configure the URL / endpoint to which update checks are sent. Only available for Android and iOS. | <code>https://plugin.capgo.app/updates</code> | |
271
+ | **`channelUrl`** | <code>string</code> | Configure the URL / endpoint for channel operations. Only available for Android and iOS. | <code>https://plugin.capgo.app/channel_self</code> | |
272
+ | **`statsUrl`** | <code>string</code> | Configure the URL / endpoint to which update statistics are sent. Only available for Android and iOS. Set to "" to disable stats reporting. | <code>https://plugin.capgo.app/stats</code> | |
273
+ | **`publicKey`** | <code>string</code> | Configure the public key for end to end live update encryption Version 2 Only available for Android and iOS. | <code>undefined</code> | 6.2.0 |
274
+ | **`version`** | <code>string</code> | Configure the current version of the app. This will be used for the first update request. If not set, the plugin will get the version from the native code. Only available for Android and iOS. | <code>undefined</code> | 4.17.48 |
275
+ | **`directUpdate`** | <code>boolean \| 'always' \| 'atInstall' \| 'onLaunch'</code> | Configure when the plugin should direct install updates. Only for autoUpdate mode. Works well for apps less than 10MB and with uploads done using --partial flag. Zip or apps more than 10MB will be relatively slow for users to update. - false: Never do direct updates (use default behavior: download at start, set when backgrounded) - atInstall: Direct update only when app is installed, updated from store, otherwise act as directUpdate = false - onLaunch: Direct update only on app installed, updated from store or after app kill, otherwise act as directUpdate = false - always: Direct update in all previous cases (app installed, updated from store, after app kill or app resume), never act as directUpdate = false - true: (deprecated) Same as "always" for backward compatibility Only available for Android and iOS. | <code>false</code> | 5.1.0 |
276
+ | **`autoSplashscreen`** | <code>boolean</code> | Automatically handle splashscreen hiding when using directUpdate. When enabled, the plugin will automatically hide the splashscreen after updates are applied or when no update is needed. This removes the need to manually listen for appReady events and call SplashScreen.hide(). Only works when directUpdate is set to "atInstall", "always", "onLaunch", or true. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Requires autoUpdate and directUpdate to be enabled. Only available for Android and iOS. | <code>false</code> | 7.6.0 |
277
+ | **`autoSplashscreenLoader`** | <code>boolean</code> | Display a native loading indicator on top of the splashscreen while automatic direct updates are running. Only takes effect when {@link autoSplashscreen} is enabled. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Only available for Android and iOS. | <code>false</code> | 7.19.0 |
278
+ | **`autoSplashscreenTimeout`** | <code>number</code> | Automatically hide the splashscreen after the specified number of milliseconds when using automatic direct updates. If the timeout elapses, the update continues to download in the background while the splashscreen is dismissed. Set to `0` (zero) to disable the timeout. When the timeout fires, the direct update flow is skipped and the downloaded bundle is installed on the next background/launch. Requires {@link autoSplashscreen} to be enabled. Only available for Android and iOS. | <code>10000 // (10 seconds)</code> | 7.19.0 |
279
+ | **`periodCheckDelay`** | <code>number</code> | Configure the delay period for period update check. the unit is in seconds. Only available for Android and iOS. Cannot be less than 600 seconds (10 minutes). | <code>0 (disabled)</code> | |
280
+ | **`localS3`** | <code>boolean</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
281
+ | **`localHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
282
+ | **`localWebHost`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
283
+ | **`localSupa`** | <code>string</code> | Configure the CLI to use a local server for testing or self-hosted update server. | <code>undefined</code> | 4.17.48 |
284
+ | **`localSupaAnon`** | <code>string</code> | Configure the CLI to use a local server for testing. | <code>undefined</code> | 4.17.48 |
285
+ | **`localApi`** | <code>string</code> | Configure the CLI to use a local api for testing. | <code>undefined</code> | 6.3.3 |
286
+ | **`localApiFiles`** | <code>string</code> | Configure the CLI to use a local file api for testing. | <code>undefined</code> | 6.3.3 |
287
+ | **`allowModifyUrl`** | <code>boolean</code> | Allow the plugin to modify the updateUrl, statsUrl and channelUrl dynamically from the JavaScript side. | <code>false</code> | 5.4.0 |
288
+ | **`allowModifyAppId`** | <code>boolean</code> | Allow the plugin to modify the appId dynamically from the JavaScript side. | <code>false</code> | 7.14.0 |
289
+ | **`allowManualBundleError`** | <code>boolean</code> | Allow marking bundles as errored from JavaScript while using manual update flows. When enabled, {@link CapacitorUpdaterPlugin.setBundleError} can change a bundle status to `error`. | <code>false</code> | 7.20.0 |
290
+ | **`persistCustomId`** | <code>boolean</code> | Persist the customId set through {@link CapacitorUpdaterPlugin.setCustomId} across app restarts. Only available for Android and iOS. | <code>false (will be true by default in a future major release v8.x.x)</code> | 7.17.3 |
291
+ | **`persistModifyUrl`** | <code>boolean</code> | Persist the updateUrl, statsUrl and channelUrl set through {@link CapacitorUpdaterPlugin.setUpdateUrl}, {@link CapacitorUpdaterPlugin.setStatsUrl} and {@link CapacitorUpdaterPlugin.setChannelUrl} across app restarts. Only available for Android and iOS. | <code>false</code> | 7.20.0 |
292
+ | **`allowSetDefaultChannel`** | <code>boolean</code> | Allow or disallow the {@link CapacitorUpdaterPlugin.setChannel} method to modify the defaultChannel. When set to `false`, calling `setChannel()` will return an error with code `disabled_by_config`. | <code>true</code> | 7.34.0 |
293
+ | **`defaultChannel`** | <code>string</code> | Set the default channel for the app in the config. Case sensitive. This will setting will override the default channel set in the cloud, but will still respect overrides made in the cloud. This requires the channel to allow devices to self dissociate/associate in the channel settings. https://capgo.app/docs/public-api/channels/#channel-configuration-options | <code>undefined</code> | 5.5.0 |
294
+ | **`appId`** | <code>string</code> | Configure the app id for the app in the config. | <code>undefined</code> | 6.0.0 |
295
+ | **`keepUrlPathAfterReload`** | <code>boolean</code> | Configure the plugin to keep the URL path after a reload. WARNING: When a reload is triggered, 'window.history' will be cleared. | <code>false</code> | 6.8.0 |
296
+ | **`disableJSLogging`** | <code>boolean</code> | Disable the JavaScript logging of the plugin. if true, the plugin will not log to the JavaScript console. only the native log will be done | <code>false</code> | 7.3.0 |
297
+ | **`shakeMenu`** | <code>boolean</code> | Enable shake gesture to show update menu for debugging/testing purposes | <code>false</code> | 7.5.0 |
298
+
299
+ ### Examples
300
+
301
+ In `capacitor.config.json`:
260
302
 
303
+ ```json
304
+ {
305
+ "plugins": {
306
+ "CapacitorUpdater": {
307
+ "appReadyTimeout": 1000 // (1 second, minimum 1000),
308
+ "responseTimeout": 10 // (10 second),
309
+ "autoDeleteFailed": false,
310
+ "autoDeletePrevious": false,
311
+ "autoUpdate": false,
312
+ "resetWhenUpdate": false,
313
+ "updateUrl": https://example.com/api/auto_update,
314
+ "channelUrl": https://example.com/api/channel,
315
+ "statsUrl": https://example.com/api/stats,
316
+ "publicKey": undefined,
317
+ "version": undefined,
318
+ "directUpdate": undefined,
319
+ "autoSplashscreen": undefined,
320
+ "autoSplashscreenLoader": undefined,
321
+ "autoSplashscreenTimeout": undefined,
322
+ "periodCheckDelay": 3600 (1 hour),
323
+ "localS3": undefined,
324
+ "localHost": undefined,
325
+ "localWebHost": undefined,
326
+ "localSupa": undefined,
327
+ "localSupaAnon": undefined,
328
+ "localApi": undefined,
329
+ "localApiFiles": undefined,
330
+ "allowModifyUrl": undefined,
331
+ "allowModifyAppId": undefined,
332
+ "allowManualBundleError": undefined,
333
+ "persistCustomId": undefined,
334
+ "persistModifyUrl": undefined,
335
+ "allowSetDefaultChannel": undefined,
336
+ "defaultChannel": undefined,
337
+ "appId": undefined,
338
+ "keepUrlPathAfterReload": undefined,
339
+ "disableJSLogging": undefined,
340
+ "shakeMenu": undefined
341
+ }
342
+ }
343
+ }
344
+ ```
345
+
346
+ In `capacitor.config.ts`:
347
+
348
+ ```ts
349
+ /// <reference types="@capgo/capacitor-updater" />
350
+
351
+ import { CapacitorConfig } from '@capacitor/cli';
352
+
353
+ const config: CapacitorConfig = {
354
+ plugins: {
355
+ CapacitorUpdater: {
356
+ appReadyTimeout: 1000 // (1 second, minimum 1000),
357
+ responseTimeout: 10 // (10 second),
358
+ autoDeleteFailed: false,
359
+ autoDeletePrevious: false,
360
+ autoUpdate: false,
361
+ resetWhenUpdate: false,
362
+ updateUrl: https://example.com/api/auto_update,
363
+ channelUrl: https://example.com/api/channel,
364
+ statsUrl: https://example.com/api/stats,
365
+ publicKey: undefined,
366
+ version: undefined,
367
+ directUpdate: undefined,
368
+ autoSplashscreen: undefined,
369
+ autoSplashscreenLoader: undefined,
370
+ autoSplashscreenTimeout: undefined,
371
+ periodCheckDelay: 3600 (1 hour),
372
+ localS3: undefined,
373
+ localHost: undefined,
374
+ localWebHost: undefined,
375
+ localSupa: undefined,
376
+ localSupaAnon: undefined,
377
+ localApi: undefined,
378
+ localApiFiles: undefined,
379
+ allowModifyUrl: undefined,
380
+ allowModifyAppId: undefined,
381
+ allowManualBundleError: undefined,
382
+ persistCustomId: undefined,
383
+ persistModifyUrl: undefined,
384
+ allowSetDefaultChannel: undefined,
385
+ defaultChannel: undefined,
386
+ appId: undefined,
387
+ keepUrlPathAfterReload: undefined,
388
+ disableJSLogging: undefined,
389
+ shakeMenu: undefined,
390
+ },
391
+ },
392
+ };
393
+
394
+ export default config;
395
+ ```
261
396
 
262
397
  </docgen-config>
263
398
 
@@ -85,7 +85,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
85
85
  private static final String[] BREAKING_EVENT_NAMES = { "breakingAvailable", "majorAvailable" };
86
86
  private static final String LAST_FAILED_BUNDLE_PREF_KEY = "CapacitorUpdater.lastFailedBundle";
87
87
 
88
- private final String pluginVersion = "7.40.0";
88
+ private final String pluginVersion = "7.40.5";
89
89
  private static final String DELAY_CONDITION_PREFERENCES = "";
90
90
 
91
91
  private SharedPreferences.Editor editor;
@@ -105,7 +105,10 @@ public class CapgoUpdater {
105
105
 
106
106
  private boolean isProd() {
107
107
  try {
108
- return !Objects.requireNonNull(getClass().getPackage()).getName().contains(".debug");
108
+ if (activity == null) {
109
+ return true; // Default to production if no activity context
110
+ }
111
+ return (activity.getApplicationInfo().flags & android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) == 0;
109
112
  } catch (Exception e) {
110
113
  return true; // Default to production if we can't determine
111
114
  }
@@ -179,7 +182,8 @@ public class CapgoUpdater {
179
182
  ZipEntry entry;
180
183
  while ((entry = zis.getNextEntry()) != null) {
181
184
  if (entry.getName().contains("\\")) {
182
- logger.error("unzip: Windows path is not supported, please use unix path as require by zip RFC: " + entry.getName());
185
+ logger.error("Unzip failed: Windows path not supported");
186
+ logger.debug("Invalid path: " + entry.getName());
183
187
  this.sendStats("windows_path_fail");
184
188
  }
185
189
  final File file = new File(targetDirectory, entry.getName());
@@ -275,7 +279,8 @@ public class CapgoUpdater {
275
279
  boolean success = finishDownload(id, dest, version, sessionKey, checksum, true, isManifest);
276
280
  BundleInfo resultBundle;
277
281
  if (!success) {
278
- logger.error("Finish download failed: " + version);
282
+ logger.error("Finish download failed");
283
+ logger.debug("Version: " + version);
279
284
  resultBundle = new BundleInfo(
280
285
  id,
281
286
  version,
@@ -307,7 +312,8 @@ public class CapgoUpdater {
307
312
  case FAILED:
308
313
  Data failedData = workInfo.getOutputData();
309
314
  String error = failedData.getString(DownloadService.ERROR);
310
- logger.error("Download failed: " + error + " " + workInfo.getState());
315
+ logger.error("Download failed");
316
+ logger.debug("Error: " + error + ", State: " + workInfo.getState());
311
317
  String failedVersion = failedData.getString(DownloadService.VERSION);
312
318
 
313
319
  io.execute(() -> {
@@ -423,7 +429,8 @@ public class CapgoUpdater {
423
429
  CryptoCipher.logChecksumInfo("Calculated checksum", checksum);
424
430
  CryptoCipher.logChecksumInfo("Expected checksum", checksumDecrypted);
425
431
  if ((!checksumDecrypted.isEmpty() || !this.publicKey.isEmpty()) && !checksumDecrypted.equals(checksum)) {
426
- logger.error("Error checksum '" + checksumDecrypted + "' '" + checksum + "' '");
432
+ logger.error("Checksum mismatch");
433
+ logger.debug("Expected: " + checksumDecrypted + ", Got: " + checksum);
427
434
  this.sendStats("checksum_fail");
428
435
  throw new IOException("Checksum failed: " + id);
429
436
  }
@@ -435,7 +442,8 @@ public class CapgoUpdater {
435
442
  }
436
443
  final Boolean res = this.delete(id);
437
444
  if (!res) {
438
- logger.info("Double error, cannot cleanup: " + version);
445
+ logger.info("Failed to cleanup after error");
446
+ logger.debug("Version: " + version);
439
447
  }
440
448
 
441
449
  final Map<String, Object> ret = new HashMap<>();
@@ -536,7 +544,8 @@ public class CapgoUpdater {
536
544
  this.deleteDirectory(cacheFolder, threadToCheck);
537
545
  logger.info("Cleaned up delta cache folder");
538
546
  } catch (IOException e) {
539
- logger.error("Failed to cleanup delta cache: " + e.getMessage());
547
+ logger.error("Failed to cleanup delta cache");
548
+ logger.debug("Error: " + e.getMessage());
540
549
  }
541
550
  }
542
551
 
@@ -577,9 +586,11 @@ public class CapgoUpdater {
577
586
  try {
578
587
  this.deleteDirectory(entry, threadToCheck);
579
588
  this.removeBundleInfo(id);
580
- logger.info("Deleted orphan bundle directory: " + id);
589
+ logger.info("Deleted orphan bundle directory");
590
+ logger.debug("Bundle ID: " + id);
581
591
  } catch (IOException e) {
582
- logger.error("Failed to delete orphan bundle directory: " + id + " " + e.getMessage());
592
+ logger.error("Failed to delete orphan bundle directory");
593
+ logger.debug("Bundle ID: " + id + ", Error: " + e.getMessage());
583
594
  }
584
595
  }
585
596
  }
@@ -616,9 +627,11 @@ public class CapgoUpdater {
616
627
 
617
628
  try {
618
629
  this.deleteDirectory(entry, threadToCheck);
619
- logger.info("Deleted orphaned temp unzip folder: " + folderName);
630
+ logger.info("Deleted orphaned temp unzip folder");
631
+ logger.debug("Folder: " + folderName);
620
632
  } catch (IOException e) {
621
- logger.error("Failed to delete orphaned temp folder: " + folderName + " " + e.getMessage());
633
+ logger.error("Failed to delete orphaned temp folder");
634
+ logger.debug("Folder: " + folderName + ", Error: " + e.getMessage());
622
635
  }
623
636
  }
624
637
  }
@@ -705,7 +718,8 @@ public class CapgoUpdater {
705
718
  } catch (Exception e) {
706
719
  // Clean up on failure
707
720
  downloadFutures.remove(id);
708
- logger.error("Error waiting for download: " + e.getMessage());
721
+ logger.error("Error waiting for download");
722
+ logger.debug("Error: " + e.getMessage());
709
723
  BundleInfo errorBundle = new BundleInfo(id, version, BundleStatus.ERROR, new Date(System.currentTimeMillis()), "");
710
724
  saveBundleInfo(id, errorBundle);
711
725
  if (e instanceof IOException) {
@@ -745,12 +759,14 @@ public class CapgoUpdater {
745
759
  public Boolean delete(final String id, final Boolean removeInfo) throws IOException {
746
760
  final BundleInfo deleted = this.getBundleInfo(id);
747
761
  if (deleted.isBuiltin() || this.getCurrentBundleId().equals(id)) {
748
- logger.error("Cannot delete " + id);
762
+ logger.error("Cannot delete current or builtin bundle");
763
+ logger.debug("Bundle ID: " + id);
749
764
  return false;
750
765
  }
751
766
  final BundleInfo next = this.getNextBundle();
752
767
  if (next != null && !next.isDeleted() && !next.isErrorStatus() && next.getId().equals(id)) {
753
- logger.error("Cannot delete the next bundle" + id);
768
+ logger.error("Cannot delete the next bundle");
769
+ logger.debug("Bundle ID: " + id);
754
770
  return false;
755
771
  }
756
772
  // Cancel download for this version if active
@@ -767,7 +783,8 @@ public class CapgoUpdater {
767
783
  }
768
784
  return true;
769
785
  }
770
- logger.error("bundle removed: " + deleted.getVersionName());
786
+ logger.info("Bundle not found on disk");
787
+ logger.debug("Version: " + deleted.getVersionName());
771
788
  // perhaps we did not find the bundle in the files, but if the user requested a delete, we delete
772
789
  if (removeInfo) {
773
790
  this.removeBundleInfo(id);
@@ -938,11 +955,13 @@ public class CapgoUpdater {
938
955
  if (response.isSuccessful()) {
939
956
  logger.info("Rate limit statistic sent");
940
957
  } else {
941
- logger.error("Error sending rate limit statistic: " + response.code());
958
+ logger.error("Error sending rate limit statistic");
959
+ logger.debug("Response code: " + response.code());
942
960
  }
943
961
  }
944
962
  } catch (final Exception e) {
945
- logger.error("Failed to send rate limit statistic: " + e.getMessage());
963
+ logger.error("Failed to send rate limit statistic");
964
+ logger.debug("Error: " + e.getMessage());
946
965
  }
947
966
  }
948
967
 
@@ -1039,7 +1058,8 @@ public class CapgoUpdater {
1039
1058
  json.put("defaultChannel", channel);
1040
1059
  }
1041
1060
  } catch (JSONException e) {
1042
- logger.error("Error getLatest JSONException " + e.getMessage());
1061
+ logger.error("Error getting latest version");
1062
+ logger.debug("JSONException: " + e.getMessage());
1043
1063
  final Map<String, Object> retError = new HashMap<>();
1044
1064
  retError.put("message", "Cannot get info: " + e);
1045
1065
  retError.put("error", "json_error");
@@ -1111,7 +1131,8 @@ public class CapgoUpdater {
1111
1131
  json = this.createInfoObject();
1112
1132
  json.put("channel", channel);
1113
1133
  } catch (JSONException e) {
1114
- logger.error("Error setChannel JSONException " + e.getMessage());
1134
+ logger.error("Error setting channel");
1135
+ logger.debug("JSONException: " + e.getMessage());
1115
1136
  final Map<String, Object> retError = new HashMap<>();
1116
1137
  retError.put("message", "Cannot get info: " + e);
1117
1138
  retError.put("error", "json_error");
@@ -1157,7 +1178,8 @@ public class CapgoUpdater {
1157
1178
  try {
1158
1179
  json = this.createInfoObject();
1159
1180
  } catch (JSONException e) {
1160
- logger.error("Error getChannel JSONException " + e.getMessage());
1181
+ logger.error("Error getting channel");
1182
+ logger.debug("JSONException: " + e.getMessage());
1161
1183
  final Map<String, Object> retError = new HashMap<>();
1162
1184
  retError.put("message", "Cannot get info: " + e);
1163
1185
  retError.put("error", "json_error");
@@ -1279,7 +1301,8 @@ public class CapgoUpdater {
1279
1301
  try {
1280
1302
  json = this.createInfoObject();
1281
1303
  } catch (JSONException e) {
1282
- logger.error("Error creating info object: " + e.getMessage());
1304
+ logger.error("Error creating info object");
1305
+ logger.debug("JSONException: " + e.getMessage());
1283
1306
  final Map<String, Object> retError = new HashMap<>();
1284
1307
  retError.put("message", "Cannot get info: " + e);
1285
1308
  retError.put("error", "json_error");
@@ -1299,7 +1322,8 @@ public class CapgoUpdater {
1299
1322
  }
1300
1323
  }
1301
1324
  } catch (JSONException e) {
1302
- logger.error("Error adding query parameters: " + e.getMessage());
1325
+ logger.error("Error adding query parameters");
1326
+ logger.debug("JSONException: " + e.getMessage());
1303
1327
  }
1304
1328
 
1305
1329
  Request request = new Request.Builder().url(urlBuilder.build()).get().build();
@@ -1420,7 +1444,8 @@ public class CapgoUpdater {
1420
1444
  json.put("old_version_name", oldVersionName);
1421
1445
  json.put("action", action);
1422
1446
  } catch (JSONException e) {
1423
- logger.error("Error sendStats JSONException " + e.getMessage());
1447
+ logger.error("Error preparing stats");
1448
+ logger.debug("JSONException: " + e.getMessage());
1424
1449
  return;
1425
1450
  }
1426
1451
 
@@ -1435,7 +1460,8 @@ public class CapgoUpdater {
1435
1460
  new okhttp3.Callback() {
1436
1461
  @Override
1437
1462
  public void onFailure(@NonNull Call call, @NonNull IOException e) {
1438
- logger.error("Failed to send stats: " + e.getMessage());
1463
+ logger.error("Failed to send stats");
1464
+ logger.debug("Error: " + e.getMessage());
1439
1465
  }
1440
1466
 
1441
1467
  @Override
@@ -1447,9 +1473,11 @@ public class CapgoUpdater {
1447
1473
  }
1448
1474
 
1449
1475
  if (response.isSuccessful()) {
1450
- logger.info("Stats send for \"" + action + "\", version " + versionName);
1476
+ logger.info("Stats sent successfully");
1477
+ logger.debug("Action: " + action + ", Version: " + versionName);
1451
1478
  } else {
1452
- logger.error("Error sending stats: " + response.code());
1479
+ logger.error("Error sending stats");
1480
+ logger.debug("Response code: " + response.code());
1453
1481
  }
1454
1482
  }
1455
1483
  }
@@ -1476,14 +1504,8 @@ public class CapgoUpdater {
1476
1504
  result = BundleInfo.fromJSON(stored);
1477
1505
  }
1478
1506
  } catch (JSONException e) {
1479
- logger.error(
1480
- "Failed to parse info for bundle [" +
1481
- trueId +
1482
- "] stored value: '" +
1483
- this.prefs.getString(trueId + INFO_SUFFIX, "") +
1484
- "' error: " +
1485
- e.getMessage()
1486
- );
1507
+ logger.error("Failed to parse bundle info");
1508
+ logger.debug("Bundle ID: " + trueId + ", Error: " + e.getMessage());
1487
1509
  // Clear corrupted data
1488
1510
  this.editor.remove(trueId + INFO_SUFFIX);
1489
1511
  this.editor.commit();
@@ -235,14 +235,11 @@ public class CryptoCipher {
235
235
  detectedAlgorithm = "SHA-256";
236
236
  } else if (decryptedChecksum.length == 4) {
237
237
  detectedAlgorithm = "CRC32 (deprecated)";
238
- logger.error(
239
- "CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums."
240
- );
238
+ logger.error("CRC32 checksum detected - deprecated algorithm");
241
239
  } else {
242
240
  detectedAlgorithm = "unknown (" + decryptedChecksum.length + " bytes)";
243
- logger.error(
244
- "Unknown checksum algorithm detected with " + decryptedChecksum.length + " bytes. Expected SHA-256 (32 bytes)."
245
- );
241
+ logger.error("Unknown checksum algorithm detected");
242
+ logger.debug("Byte count: " + decryptedChecksum.length + ", Expected: 32 (SHA-256)");
246
243
  }
247
244
  logger.debug(
248
245
  "Decrypted checksum: " +
@@ -255,7 +252,8 @@ public class CryptoCipher {
255
252
  );
256
253
  return result;
257
254
  } catch (GeneralSecurityException e) {
258
- logger.error("decryptChecksum fail: " + e.getMessage());
255
+ logger.error("Checksum decryption failed");
256
+ logger.debug("Error: " + e.getMessage());
259
257
  throw new IOException("Decryption failed: " + e.getMessage());
260
258
  }
261
259
  }
@@ -286,13 +284,10 @@ public class CryptoCipher {
286
284
  String algorithm = detectChecksumAlgorithm(hexChecksum);
287
285
  logger.debug(label + ": " + algorithm + " hex format (length: " + hexChecksum.length() + " chars)");
288
286
  if (algorithm.contains("CRC32")) {
289
- logger.error(
290
- "CRC32 checksum detected. This algorithm is deprecated and no longer supported. Please update your CLI to use SHA-256 checksums."
291
- );
287
+ logger.error("CRC32 checksum detected - deprecated algorithm");
292
288
  } else if (algorithm.contains("unknown")) {
293
- logger.error(
294
- "Unknown checksum algorithm detected. Expected SHA-256 (64 hex chars) but got " + hexChecksum.length() + " chars."
295
- );
289
+ logger.error("Unknown checksum algorithm detected");
290
+ logger.debug("Char count: " + hexChecksum.length() + ", Expected: 64 (SHA-256)");
296
291
  }
297
292
  }
298
293
 
@@ -321,7 +316,8 @@ public class CryptoCipher {
321
316
  }
322
317
  return hexString.toString();
323
318
  } catch (IOException e) {
324
- logger.error("Cannot calc checksum v2: " + file.getPath() + " " + e.getMessage());
319
+ logger.error("Cannot calculate checksum");
320
+ logger.debug("Path: " + file.getPath() + ", Error: " + e.getMessage());
325
321
  return "";
326
322
  }
327
323
  }