@capgo/capacitor-updater 8.51.1 → 8.51.2

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
@@ -300,46 +300,47 @@ Downgrading to a previous version of the updater plugin is not supported.
300
300
 
301
301
  CapacitorUpdater can be configured with these options:
302
302
 
303
- | Prop | Type | Description | Default | Since |
304
- | ------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
305
- | **`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> | |
306
- | **`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> | |
307
- | **`autoDeleteFailed`** | <code>boolean</code> | Configure whether the plugin should use automatically delete failed bundles. Only available for Android and iOS. | <code>true</code> | |
308
- | **`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> | |
309
- | **`autoUpdate`** | <code>boolean \| 'always' \| 'off' \| 'atBackground' \| 'atInstall' \| 'onLaunch' \| 'onlyDownload'</code> | Configure how the plugin checks for, downloads, and applies live updates. The plugin checks for updates when the app moves to the foreground. When {@link periodCheckDelay} is greater than 0, it also checks on a repeating timer while the app stays open. Boolean values keep their existing behavior: - `true`: Same as `"atBackground"`. - `false`: Same as `"off"`. String values merge the previous Auto Update and Direct Update configuration: - `"off"`: Disable automatic update checks. - `"atBackground"`: Check and download automatically on each foreground check, then apply the update the next time the app moves to background. - `"atInstall"`: Apply immediately only after a fresh install or native app store update; otherwise use `"atBackground"` behavior. - `"onLaunch"`: Apply immediately only when the app is brought to the foreground from a killed state (cold start). After that first check, fall back to `"atBackground"` behavior. - `"always"`: Check on every foreground transition and apply immediately whenever an update is available. - `"onlyDownload"`: Check and download automatically, emit `updateAvailable`, and never set the next bundle or apply an update automatically. Only available for Android and iOS. | <code>true</code> | |
310
- | **`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> | |
311
- | **`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> | |
312
- | **`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> | |
313
- | **`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. Native stats include update lifecycle events, app health signals such as crashes, Android ANRs, low-memory exits, iOS memory warnings, and WebView health signals such as JavaScript errors, unhandled promise rejections, resource load failures, WebView renderer exits, unclean WebView restarts, app launch readiness timing, and WebView load milestones when available. | <code>https://plugin.capgo.app/stats</code> | |
314
- | **`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 |
315
- | **`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 |
316
- | **`directUpdate`** | <code>boolean \| 'always' \| 'atInstall' \| 'onLaunch'</code> | Configure when the plugin should direct install updates. Only for autoUpdate mode. | <code>false</code> | 5.1.0 |
317
- | **`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 autoUpdate is set to "atInstall", "always", or "onLaunch", or when the deprecated directUpdate option is set to "atInstall", "always", "onLaunch", or true. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Requires Auto Update and Direct Update behavior to be enabled. Only available for Android and iOS. | <code>false</code> | 7.6.0 |
318
- | **`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 |
319
- | **`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 |
320
- | **`periodCheckDelay`** | <code>number</code> | Configure the interval in seconds for repeating update checks while the app stays open. Foreground checks still run when this is 0. Values below 600 are normalized to 600. Only available for Android and iOS. Cannot be less than 600 seconds (10 minutes). | <code>0 (disabled)</code> | |
321
- | **`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 |
322
- | **`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 |
323
- | **`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 |
324
- | **`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 |
325
- | **`localSupaAnon`** | <code>string</code> | Configure the CLI to use a local server for testing. | <code>undefined</code> | 4.17.48 |
326
- | **`localApi`** | <code>string</code> | Configure the CLI to use a local api for testing. | <code>undefined</code> | 6.3.3 |
327
- | **`localApiFiles`** | <code>string</code> | Configure the CLI to use a local file api for testing. | <code>undefined</code> | 6.3.3 |
328
- | **`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 |
329
- | **`allowModifyAppId`** | <code>boolean</code> | Allow the plugin to modify the appId dynamically from the JavaScript side. | <code>false</code> | 7.14.0 |
330
- | **`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 |
331
- | **`allowPreview`** | <code>boolean</code> | Allow JavaScript to start a native preview session and temporarily request updates for another app id. This is intended for trusted container apps that implement Expo Go-style preview flows. Only available for Android and iOS. | <code>false</code> | 8.47.0 |
332
- | **`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 |
333
- | **`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 |
334
- | **`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 |
335
- | **`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 |
336
- | **`appId`** | <code>string</code> | Configure the app id for the app in the config. | <code>undefined</code> | 6.0.0 |
337
- | **`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 |
338
- | **`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 |
339
- | **`osLogging`** | <code>boolean</code> | Enable OS-level logging. When enabled, logs are written to the system log which can be inspected in production builds. - **iOS**: Uses os_log instead of Swift.print, logs accessible via Console.app or Instruments - **Android**: Logs to Logcat (android.util.Log) When set to false, system logging is disabled on both platforms (only JavaScript console logging will occur if enabled). This is useful for debugging production apps (App Store/TestFlight builds on iOS, or production APKs on Android). | <code>true</code> | 8.42.0 |
340
- | **`shakeMenu`** | <code>boolean</code> | Enable the native preview menu gesture while a preview session is active. Outside preview sessions this preview menu is ignored, unless {@link PluginsConfig.CapacitorUpdater.allowShakeChannelSelector} is enabled. | <code>false</code> | 7.5.0 |
341
- | **`shakeMenuGesture`** | <code><a href="#shakemenugesture">ShakeMenuGesture</a></code> | Choose which native gesture opens the preview/channel menu. This applies to both {@link PluginsConfig.CapacitorUpdater.shakeMenu} and {@link PluginsConfig.CapacitorUpdater.allowShakeChannelSelector}. Only available for Android and iOS. | <code>'shake'</code> | 8.48.0 |
342
- | **`allowShakeChannelSelector`** | <code>boolean</code> | Enable the native menu gesture to show a channel selector menu for switching between update channels. If {@link PluginsConfig.CapacitorUpdater.shakeMenu} is also enabled while a preview session is active, the shake menu includes both preview actions and channel switching. The native gesture can be changed with {@link PluginsConfig.CapacitorUpdater.shakeMenuGesture}. Only available for Android and iOS. | <code>false</code> | 8.43.0 |
303
+ | Prop | Type | Description | Default | Since |
304
+ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
305
+ | **`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> | |
306
+ | **`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> | |
307
+ | **`autoDeleteFailed`** | <code>boolean</code> | Configure whether the plugin should use automatically delete failed bundles. Only available for Android and iOS. | <code>true</code> | |
308
+ | **`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> | |
309
+ | **`autoUpdate`** | <code>boolean \| 'always' \| 'off' \| 'atBackground' \| 'atInstall' \| 'onLaunch' \| 'onlyDownload'</code> | Configure how the plugin checks for, downloads, and applies live updates. The plugin checks for updates when the app moves to the foreground. When {@link periodCheckDelay} is greater than 0, it also checks on a repeating timer while the app stays open. Boolean values keep their existing behavior: - `true`: Same as `"atBackground"`. - `false`: Same as `"off"`. String values merge the previous Auto Update and Direct Update configuration: - `"off"`: Disable automatic update checks. - `"atBackground"`: Check and download automatically on each foreground check, then apply the update the next time the app moves to background. - `"atInstall"`: Apply immediately only after a fresh install or native app store update; otherwise use `"atBackground"` behavior. - `"onLaunch"`: Apply immediately only when the app is brought to the foreground from a killed state (cold start). After that first check, fall back to `"atBackground"` behavior. - `"always"`: Check on every foreground transition and apply immediately whenever an update is available. - `"onlyDownload"`: Check and download automatically, emit `updateAvailable`, and never set the next bundle or apply an update automatically. Only available for Android and iOS. | <code>true</code> | |
310
+ | **`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> | |
311
+ | **`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> | |
312
+ | **`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> | |
313
+ | **`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. Native stats include update lifecycle events, app health signals such as crashes, Android ANRs, low-memory exits, iOS memory warnings, and WebView health signals such as JavaScript errors, unhandled promise rejections, resource load failures, WebView renderer exits, unclean WebView restarts, app launch readiness timing, and WebView load milestones when available. | <code>https://plugin.capgo.app/stats</code> | |
314
+ | **`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 |
315
+ | **`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 |
316
+ | **`directUpdate`** | <code>boolean \| 'always' \| 'atInstall' \| 'onLaunch'</code> | Configure when the plugin should direct install updates. Only for autoUpdate mode. | <code>false</code> | 5.1.0 |
317
+ | **`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 autoUpdate is set to "atInstall", "always", or "onLaunch", or when the deprecated directUpdate option is set to "atInstall", "always", "onLaunch", or true. Requires the @capacitor/splash-screen plugin to be installed and configured with launchAutoHide: false. Requires Auto Update and Direct Update behavior to be enabled. Only available for Android and iOS. | <code>false</code> | 7.6.0 |
318
+ | **`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 |
319
+ | **`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 |
320
+ | **`periodCheckDelay`** | <code>number</code> | Configure the interval in seconds for repeating update checks while the app stays open. Foreground checks still run when this is 0. Values below 600 are normalized to 600. Only available for Android and iOS. Cannot be less than 600 seconds (10 minutes). | <code>0 (disabled)</code> | |
321
+ | **`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 |
322
+ | **`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 |
323
+ | **`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 |
324
+ | **`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 |
325
+ | **`localSupaAnon`** | <code>string</code> | Configure the CLI to use a local server for testing. | <code>undefined</code> | 4.17.48 |
326
+ | **`localApi`** | <code>string</code> | Configure the CLI to use a local api for testing. | <code>undefined</code> | 6.3.3 |
327
+ | **`localApiFiles`** | <code>string</code> | Configure the CLI to use a local file api for testing. | <code>undefined</code> | 6.3.3 |
328
+ | **`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 |
329
+ | **`allowModifyAppId`** | <code>boolean</code> | Allow the plugin to modify the appId dynamically from the JavaScript side. | <code>false</code> | 7.14.0 |
330
+ | **`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 |
331
+ | **`allowPreview`** | <code>boolean</code> | Allow JavaScript to start a native preview session and temporarily request updates for another app id. This is intended for trusted container apps that implement Expo Go-style preview flows. Only available for Android and iOS. | <code>false</code> | 8.47.0 |
332
+ | **`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 |
333
+ | **`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 |
334
+ | **`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 |
335
+ | **`persistDefaultChannelOnReinstall`** | <code>boolean</code> | Keep the default channel stored by {@link CapacitorUpdaterPlugin.setChannel} or refreshed by {@link CapacitorUpdaterPlugin.getChannel} when app data is restored into a new app install. `setChannel()` and a successful `getChannel()` still persist the selected channel across app restarts. When this option is `false`, native startup clears that persisted channel when it detects app data restored into a new installation. Native build cleanup clears the persisted channel only when `persistDefaultChannelOnReinstall` is `false`, `resetWhenUpdate` is `true`, and the native build version has changed. Only available for Android and iOS. | <code>true</code> | 8.51.0 |
336
+ | **`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 |
337
+ | **`appId`** | <code>string</code> | Configure the app id for the app in the config. | <code>undefined</code> | 6.0.0 |
338
+ | **`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 |
339
+ | **`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 |
340
+ | **`osLogging`** | <code>boolean</code> | Enable OS-level logging. When enabled, logs are written to the system log which can be inspected in production builds. - **iOS**: Uses os_log instead of Swift.print, logs accessible via Console.app or Instruments - **Android**: Logs to Logcat (android.util.Log) When set to false, system logging is disabled on both platforms (only JavaScript console logging will occur if enabled). This is useful for debugging production apps (App Store/TestFlight builds on iOS, or production APKs on Android). | <code>true</code> | 8.42.0 |
341
+ | **`shakeMenu`** | <code>boolean</code> | Enable the native preview menu gesture while a preview session is active. Outside preview sessions this preview menu is ignored, unless {@link PluginsConfig.CapacitorUpdater.allowShakeChannelSelector} is enabled. | <code>false</code> | 7.5.0 |
342
+ | **`shakeMenuGesture`** | <code><a href="#shakemenugesture">ShakeMenuGesture</a></code> | Choose which native gesture opens the preview/channel menu. This applies to both {@link PluginsConfig.CapacitorUpdater.shakeMenu} and {@link PluginsConfig.CapacitorUpdater.allowShakeChannelSelector}. Only available for Android and iOS. | <code>'shake'</code> | 8.48.0 |
343
+ | **`allowShakeChannelSelector`** | <code>boolean</code> | Enable the native menu gesture to show a channel selector menu for switching between update channels. If {@link PluginsConfig.CapacitorUpdater.shakeMenu} is also enabled while a preview session is active, the shake menu includes both preview actions and channel switching. The native gesture can be changed with {@link PluginsConfig.CapacitorUpdater.shakeMenuGesture}. Only available for Android and iOS. | <code>false</code> | 8.43.0 |
343
344
 
344
345
  ### Examples
345
346
 
@@ -379,6 +380,7 @@ In `capacitor.config.json`:
379
380
  "persistCustomId": undefined,
380
381
  "persistModifyUrl": undefined,
381
382
  "allowSetDefaultChannel": undefined,
383
+ "persistDefaultChannelOnReinstall": undefined,
382
384
  "defaultChannel": undefined,
383
385
  "appId": undefined,
384
386
  "keepUrlPathAfterReload": undefined,
@@ -432,6 +434,7 @@ const config: CapacitorConfig = {
432
434
  persistCustomId: undefined,
433
435
  persistModifyUrl: undefined,
434
436
  allowSetDefaultChannel: undefined,
437
+ persistDefaultChannelOnReinstall: undefined,
435
438
  defaultChannel: undefined,
436
439
  appId: undefined,
437
440
  keepUrlPathAfterReload: undefined,
@@ -1263,9 +1266,9 @@ Channels allow you to distribute different bundle versions to different groups o
1263
1266
  (e.g., "production", "beta", "staging"). This method switches the device to a new channel.
1264
1267
 
1265
1268
  **Device Override UI:** `setChannel()` validates the channel with the backend, then stores the
1266
- selected channel locally on the device. It does not create or update a backend Device Override,
1267
- so the device will not appear as overridden in the Capgo dashboard. Only assignments created
1268
- from the dashboard or the Public API are shown in the Device Override UI.
1269
+ selected channel locally on the device for future app restarts. It does not create or update
1270
+ a backend Device Override, so the device will not appear as overridden in the Capgo dashboard.
1271
+ Only assignments created from the dashboard or the Public API are shown in the Device Override UI.
1269
1272
 
1270
1273
  **Requirements:**
1271
1274
  - The target channel must allow self-assignment (configured in your Capgo dashboard or backend)
@@ -1294,7 +1297,7 @@ CapacitorUpdater.addListener('channelPrivate', (data) =&gt; {
1294
1297
  ```
1295
1298
 
1296
1299
  This sends a request to the Capgo backend to validate the specified channel, then stores the
1297
- channel locally on the device.
1300
+ channel locally on the device for future app restarts.
1298
1301
 
1299
1302
  | Param | Type | Description |
1300
1303
  | ------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
@@ -1353,8 +1356,8 @@ Use this to:
1353
1356
  - Check if a device is on a specific channel before showing features
1354
1357
  - Verify channel assignment after calling {@link setChannel}
1355
1358
 
1356
- On native platforms, a successful response also refreshes the locally persisted
1357
- default channel used by update checks.
1359
+ On native platforms, a successful response also refreshes the default channel used by update checks.
1360
+ This refresh is persisted across app restarts.
1358
1361
 
1359
1362
  **Returns:** <code>Promise&lt;<a href="#getchannelres">GetChannelRes</a>&gt;</code>
1360
1363
 
@@ -50,6 +50,7 @@ import com.google.android.play.core.install.model.InstallStatus;
50
50
  import com.google.android.play.core.install.model.UpdateAvailability;
51
51
  import io.github.g00fy2.versioncompare.Version;
52
52
  import java.io.ByteArrayOutputStream;
53
+ import java.io.File;
53
54
  import java.io.IOException;
54
55
  import java.io.InputStream;
55
56
  import java.net.HttpURLConnection;
@@ -104,6 +105,8 @@ public class CapacitorUpdaterPlugin extends Plugin {
104
105
  private static final String CHANNEL_URL_PREF_KEY = "CapacitorUpdater.channelUrl";
105
106
  private static final String DEFAULT_CHANNEL_PREF_KEY = "CapacitorUpdater.defaultChannel";
106
107
  private static final String PREVIEW_SESSION_PREF_KEY = "CapacitorUpdater.previewSession";
108
+ private static final String DEFAULT_CHANNEL_INSTALL_MARKER_PREF_KEY = "CapacitorUpdater.defaultChannelInstallMarkerCreated";
109
+ private static final String DEFAULT_CHANNEL_INSTALL_MARKER_FILE = "CapacitorUpdater.defaultChannelInstallMarker";
107
110
  private static final String PREVIEW_PREVIOUS_SHAKE_MENU_PREF_KEY = "CapacitorUpdater.previewPreviousShakeMenu";
108
111
  private static final String PREVIEW_PREVIOUS_SHAKE_CHANNEL_SELECTOR_PREF_KEY = "CapacitorUpdater.previewPreviousShakeChannelSelector";
109
112
  private static final String PREVIEW_PREVIOUS_NEXT_BUNDLE_PREF_KEY = "CapacitorUpdater.previewPreviousNextBundle";
@@ -143,7 +146,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
143
146
  static final int APPLICATION_EXIT_REASON_USER_REQUESTED = 10;
144
147
  static final int APPLICATION_EXIT_REASON_DEPENDENCY_DIED = 12;
145
148
 
146
- private final String pluginVersion = "8.51.1";
149
+ private final String pluginVersion = "8.51.2";
147
150
  private static final String DELAY_CONDITION_PREFERENCES = "";
148
151
 
149
152
  private SharedPreferences.Editor editor;
@@ -152,6 +155,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
152
155
  protected CapgoUpdater implementation;
153
156
  private Boolean persistCustomId = false;
154
157
  private Boolean persistModifyUrl = false;
158
+ private Boolean persistDefaultChannelOnReinstall = true;
155
159
 
156
160
  private Integer appReadyTimeout = 10000;
157
161
  private Integer periodCheckDelay = 0;
@@ -234,6 +238,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
234
238
  private volatile CountDownLatch cleanupLatch = new CountDownLatch(0);
235
239
  private volatile boolean cleanupComplete = false;
236
240
  private volatile Thread cleanupThread = null;
241
+ private volatile boolean defaultChannelCleanupMustRetry = false;
237
242
 
238
243
  private int lastNotifiedStatPercent = 0;
239
244
 
@@ -756,6 +761,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
756
761
 
757
762
  this.persistCustomId = this.getConfig().getBoolean("persistCustomId", false);
758
763
  this.persistModifyUrl = this.getConfig().getBoolean("persistModifyUrl", false);
764
+ this.persistDefaultChannelOnReinstall = this.getConfig().getBoolean("persistDefaultChannelOnReinstall", true);
759
765
  this.allowSetDefaultChannel = this.getConfig().getBoolean("allowSetDefaultChannel", true);
760
766
  this.implementation.setPublicKey(this.getConfig().getString("publicKey", ""));
761
767
  // Log public key prefix if encryption is enabled
@@ -782,6 +788,35 @@ public class CapacitorUpdaterPlugin extends Plugin {
782
788
  }
783
789
  }
784
790
 
791
+ final boolean resetWhenUpdate = this.getConfig().getBoolean("resetWhenUpdate", true);
792
+ final boolean nativeBuildVersionChanged = this.hasNativeBuildVersionChanged();
793
+ final boolean defaultChannelPersistenceDisabled = !Boolean.TRUE.equals(this.persistDefaultChannelOnReinstall);
794
+ final boolean restoredReinstall = defaultChannelPersistenceDisabled && this.isRestoredReinstall();
795
+ boolean installMarkerCanBePrepared = true;
796
+ if (
797
+ shouldClearPersistedDefaultChannel(
798
+ Boolean.TRUE.equals(this.persistDefaultChannelOnReinstall),
799
+ resetWhenUpdate,
800
+ nativeBuildVersionChanged,
801
+ restoredReinstall
802
+ )
803
+ ) {
804
+ installMarkerCanBePrepared = clearPersistedDefaultChannel(this.editor);
805
+ if (installMarkerCanBePrepared) {
806
+ logger.info("Cleared persisted defaultChannel because reinstall persistence is disabled");
807
+ } else {
808
+ logger.warn("Cannot durably clear persisted defaultChannel");
809
+ this.defaultChannelCleanupMustRetry = true;
810
+ if (!invalidateDefaultChannelInstallMarker(this.defaultChannelInstallMarker())) {
811
+ logger.warn("Cannot invalidate default channel install marker for cleanup retry");
812
+ }
813
+ }
814
+ }
815
+ if (defaultChannelPersistenceDisabled && installMarkerCanBePrepared) {
816
+ this.prepareDefaultChannelInstallMarker();
817
+ }
818
+
819
+ final String configDefaultChannel = this.getConfig().getString("defaultChannel", "");
785
820
  // Load defaultChannel: first try from persistent storage (set via setChannel), then fall back to config
786
821
  if (this.prefs.contains(DEFAULT_CHANNEL_PREF_KEY)) {
787
822
  final String storedDefaultChannel = this.prefs.getString(DEFAULT_CHANNEL_PREF_KEY, "");
@@ -789,10 +824,10 @@ public class CapacitorUpdaterPlugin extends Plugin {
789
824
  this.implementation.defaultChannel = storedDefaultChannel;
790
825
  logger.info("Loaded persisted defaultChannel from setChannel()");
791
826
  } else {
792
- this.implementation.defaultChannel = this.getConfig().getString("defaultChannel", "");
827
+ this.implementation.defaultChannel = configDefaultChannel;
793
828
  }
794
829
  } else {
795
- this.implementation.defaultChannel = this.getConfig().getString("defaultChannel", "");
830
+ this.implementation.defaultChannel = configDefaultChannel;
796
831
  }
797
832
 
798
833
  this.periodCheckDelay = normalizedPeriodCheckDelayMs(this.getConfig().getInt("periodCheckDelay", 0));
@@ -861,11 +896,9 @@ public class CapacitorUpdaterPlugin extends Plugin {
861
896
  ? this.prefs.getBoolean(PREVIEW_PREVIOUS_SHAKE_CHANNEL_SELECTOR_PREF_KEY, false)
862
897
  : this.shakeChannelSelectorEnabled;
863
898
  }
864
- boolean resetWhenUpdate = this.getConfig().getBoolean("resetWhenUpdate", true);
865
899
 
866
900
  // Check if app was recently installed/updated BEFORE cleanupObsoleteVersions updates LatestVersionNative
867
901
  this.wasRecentlyInstalledOrUpdated = this.checkIfRecentlyInstalledOrUpdated();
868
- final boolean nativeBuildVersionChanged = this.hasNativeBuildVersionChanged();
869
902
 
870
903
  this.implementation.autoReset(this.currentBuildVersion, resetWhenUpdate);
871
904
  if (nativeBuildVersionChanged) {
@@ -1363,6 +1396,74 @@ public class CapacitorUpdaterPlugin extends Plugin {
1363
1396
  return false;
1364
1397
  }
1365
1398
 
1399
+ static boolean shouldClearPersistedDefaultChannel(
1400
+ final boolean persistDefaultChannelOnReinstall,
1401
+ final boolean resetWhenUpdate,
1402
+ final boolean nativeBuildVersionChanged,
1403
+ final boolean restoredReinstall
1404
+ ) {
1405
+ return !persistDefaultChannelOnReinstall && (restoredReinstall || (resetWhenUpdate && nativeBuildVersionChanged));
1406
+ }
1407
+
1408
+ static boolean clearPersistedDefaultChannel(final SharedPreferences.Editor editor) {
1409
+ editor.remove(DEFAULT_CHANNEL_PREF_KEY);
1410
+ editor.remove(PREVIEW_PREVIOUS_DEFAULT_CHANNEL_PREF_KEY);
1411
+ editor.remove(PREVIEW_PREVIOUS_DEFAULT_CHANNEL_WAS_SET_PREF_KEY);
1412
+ return editor.commit();
1413
+ }
1414
+
1415
+ private File defaultChannelInstallMarker() {
1416
+ return new File(this.getContext().getNoBackupFilesDir(), DEFAULT_CHANNEL_INSTALL_MARKER_FILE);
1417
+ }
1418
+
1419
+ static boolean invalidateDefaultChannelInstallMarker(final File marker) {
1420
+ return !marker.exists() || marker.delete();
1421
+ }
1422
+
1423
+ private boolean isRestoredReinstall() {
1424
+ return isRestoredReinstall(
1425
+ this.defaultChannelInstallMarker(),
1426
+ this.prefs.getBoolean(DEFAULT_CHANNEL_INSTALL_MARKER_PREF_KEY, false)
1427
+ );
1428
+ }
1429
+
1430
+ static boolean isRestoredReinstall(final File marker, final boolean markerWasCreated) {
1431
+ return markerWasCreated && !marker.exists();
1432
+ }
1433
+
1434
+ private void prepareDefaultChannelInstallMarker() {
1435
+ prepareDefaultChannelInstallMarker(
1436
+ this.defaultChannelInstallMarker(),
1437
+ this.prefs.getBoolean(DEFAULT_CHANNEL_INSTALL_MARKER_PREF_KEY, false),
1438
+ this.editor,
1439
+ this.logger
1440
+ );
1441
+ }
1442
+
1443
+ static void prepareDefaultChannelInstallMarker(
1444
+ final File marker,
1445
+ final boolean markerWasCreated,
1446
+ final SharedPreferences.Editor editor,
1447
+ final Logger logger
1448
+ ) {
1449
+ if (!marker.exists()) {
1450
+ try {
1451
+ if (!marker.createNewFile() && !marker.exists()) {
1452
+ throw new IOException("Marker file was not created");
1453
+ }
1454
+ } catch (final IOException e) {
1455
+ logger.warn("Cannot create default channel install marker: " + e.getMessage());
1456
+ editor.remove(DEFAULT_CHANNEL_INSTALL_MARKER_PREF_KEY);
1457
+ editor.commit();
1458
+ return;
1459
+ }
1460
+ }
1461
+ if (!markerWasCreated) {
1462
+ editor.putBoolean(DEFAULT_CHANNEL_INSTALL_MARKER_PREF_KEY, true);
1463
+ editor.apply();
1464
+ }
1465
+ }
1466
+
1366
1467
  private boolean hasNativeBuildVersionChanged() {
1367
1468
  final String lastKnownVersion = this.getStoredNativeBuildVersion();
1368
1469
  return !lastKnownVersion.isEmpty() && !lastKnownVersion.equals(this.currentBuildVersion);
@@ -2321,8 +2422,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
2321
2422
  this.implementation.cleanupDownloadDirectories(allowedIds);
2322
2423
  this.implementation.cleanupOrphanedTempFolders(null);
2323
2424
 
2324
- this.editor.putString("LatestNativeBuildVersion", this.currentBuildVersion);
2325
- this.editor.apply();
2425
+ this.persistCurrentNativeBuildVersion();
2326
2426
  } catch (Exception e) {
2327
2427
  logger.error("Error during cleanupObsoleteVersions: " + e.getMessage());
2328
2428
  } finally {
@@ -2345,6 +2445,10 @@ public class CapacitorUpdaterPlugin extends Plugin {
2345
2445
  }
2346
2446
 
2347
2447
  void persistCurrentNativeBuildVersion() {
2448
+ if (this.defaultChannelCleanupMustRetry) {
2449
+ logger.warn("Keeping the previous native build version so default channel cleanup retries");
2450
+ return;
2451
+ }
2348
2452
  this.editor.putString("LatestNativeBuildVersion", this.currentBuildVersion);
2349
2453
  this.editor.apply();
2350
2454
  }
@@ -2194,7 +2194,6 @@ public class CapgoUpdater {
2194
2194
  logger.info("Public channel requested, channel override removed");
2195
2195
  callback.callback(res);
2196
2196
  } else {
2197
- // Success - persist defaultChannel
2198
2197
  this.defaultChannel = channel;
2199
2198
  editor.putString(defaultChannelKey, channel);
2200
2199
  editor.apply();