@capgo/capacitor-updater 8.47.8 → 8.47.10
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 +8 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +53 -43
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +108 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/ShakeDetector.java +3 -3
- package/android/src/main/java/ee/forgr/capacitor_updater/ShakeMenu.java +2 -0
- package/dist/docs.json +2 -2
- package/dist/esm/definitions.d.ts +8 -0
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +89 -46
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +24 -2
- package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +49 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -633,6 +633,11 @@ The bundle must include an `index.html` file at the root level.
|
|
|
633
633
|
For encrypted bundles, provide the `sessionKey` and `checksum` parameters.
|
|
634
634
|
For multi-file delta updates, provide the `manifest` array.
|
|
635
635
|
|
|
636
|
+
**Android Background Runner note:** `@capacitor/background-runner` loads its
|
|
637
|
+
configured runner script from native APK assets. Live updates cannot replace
|
|
638
|
+
that runner script. Keep it stable across OTA updates and ship a native app
|
|
639
|
+
update when the runner code changes.
|
|
640
|
+
|
|
636
641
|
| Param | Type | Description |
|
|
637
642
|
| ------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
638
643
|
| **`options`** | <code><a href="#downloadoptions">DownloadOptions</a></code> | The {@link <a href="#downloadoptions">DownloadOptions</a>} for downloading a new bundle zip. |
|
|
@@ -1188,6 +1193,9 @@ Use this to:
|
|
|
1188
1193
|
- Check if a device is on a specific channel before showing features
|
|
1189
1194
|
- Verify channel assignment after calling {@link setChannel}
|
|
1190
1195
|
|
|
1196
|
+
On native platforms, a successful response also refreshes the locally persisted
|
|
1197
|
+
default channel used by update checks.
|
|
1198
|
+
|
|
1191
1199
|
**Returns:** <code>Promise<<a href="#getchannelres">GetChannelRes</a>></code>
|
|
1192
1200
|
|
|
1193
1201
|
**Since:** 4.8.0
|
|
@@ -129,7 +129,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
129
129
|
static final int APPLICATION_EXIT_REASON_USER_REQUESTED = 10;
|
|
130
130
|
static final int APPLICATION_EXIT_REASON_DEPENDENCY_DIED = 12;
|
|
131
131
|
|
|
132
|
-
private final String pluginVersion = "8.47.
|
|
132
|
+
private final String pluginVersion = "8.47.9";
|
|
133
133
|
private static final String DELAY_CONDITION_PREFERENCES = "";
|
|
134
134
|
|
|
135
135
|
private SharedPreferences.Editor editor;
|
|
@@ -1995,6 +1995,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
1995
1995
|
CapacitorUpdaterPlugin.this.editor,
|
|
1996
1996
|
DEFAULT_CHANNEL_PREF_KEY,
|
|
1997
1997
|
CapacitorUpdaterPlugin.this.allowSetDefaultChannel,
|
|
1998
|
+
CapacitorUpdaterPlugin.this.getConfig().getString("defaultChannel", ""),
|
|
1998
1999
|
(res) -> {
|
|
1999
2000
|
JSObject jsRes = InternalUtils.mapToJSObject(res);
|
|
2000
2001
|
if (jsRes.has("error")) {
|
|
@@ -2043,21 +2044,25 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2043
2044
|
try {
|
|
2044
2045
|
logger.info("getChannel");
|
|
2045
2046
|
startNewThread(() ->
|
|
2046
|
-
CapacitorUpdaterPlugin.this.implementation.getChannel(
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2047
|
+
CapacitorUpdaterPlugin.this.implementation.getChannel(
|
|
2048
|
+
(res) -> {
|
|
2049
|
+
JSObject jsRes = InternalUtils.mapToJSObject(res);
|
|
2050
|
+
if (jsRes.has("error")) {
|
|
2051
|
+
String errorMessage = jsRes.has("message") ? jsRes.getString("message") : jsRes.getString("error");
|
|
2052
|
+
String errorCode = jsRes.getString("error");
|
|
2051
2053
|
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2054
|
+
JSObject errorObj = new JSObject();
|
|
2055
|
+
errorObj.put("message", errorMessage);
|
|
2056
|
+
errorObj.put("error", errorCode);
|
|
2055
2057
|
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2058
|
+
call.reject(errorMessage, "GETCHANNEL_FAILED", null, errorObj);
|
|
2059
|
+
} else {
|
|
2060
|
+
call.resolve(jsRes);
|
|
2061
|
+
}
|
|
2062
|
+
},
|
|
2063
|
+
CapacitorUpdaterPlugin.this.editor,
|
|
2064
|
+
DEFAULT_CHANNEL_PREF_KEY
|
|
2065
|
+
)
|
|
2061
2066
|
);
|
|
2062
2067
|
} catch (final Exception e) {
|
|
2063
2068
|
logger.error("Failed to getChannel " + e.getMessage());
|
|
@@ -2514,7 +2519,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2514
2519
|
}
|
|
2515
2520
|
|
|
2516
2521
|
final BundleInfo previewFallbackBundle = this.implementation.getPreviewFallbackBundle();
|
|
2517
|
-
this.endPreviewSession();
|
|
2522
|
+
this.endPreviewSession(true);
|
|
2518
2523
|
final BundleInfo restoredNextBundle = this.implementation.getNextBundle();
|
|
2519
2524
|
this.deletePreviewBundleIfUnused(previewBundle, previewFallbackBundle, restoredNextBundle);
|
|
2520
2525
|
return true;
|
|
@@ -2523,16 +2528,11 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2523
2528
|
private boolean leavePreviewSessionForIncomingPreviewLink() {
|
|
2524
2529
|
this.showPreviewTransitionLoader("incoming-preview-deeplink");
|
|
2525
2530
|
final BundleInfo previewBundle = this.implementation.getCurrentBundle();
|
|
2526
|
-
final BundleInfo previewFallbackBundle = this.
|
|
2531
|
+
final BundleInfo previewFallbackBundle = this.resolvePreviewFallbackBundle("incoming preview deeplink");
|
|
2527
2532
|
boolean didReload = false;
|
|
2528
2533
|
|
|
2529
2534
|
try {
|
|
2530
|
-
if (previewFallbackBundle == null
|
|
2531
|
-
logger.error("No preview fallback bundle available");
|
|
2532
|
-
return false;
|
|
2533
|
-
}
|
|
2534
|
-
if (!this.implementation.canSet(previewFallbackBundle)) {
|
|
2535
|
-
logger.error("Preview fallback bundle is not installable");
|
|
2535
|
+
if (previewFallbackBundle == null) {
|
|
2536
2536
|
return false;
|
|
2537
2537
|
}
|
|
2538
2538
|
|
|
@@ -2542,7 +2542,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2542
2542
|
return false;
|
|
2543
2543
|
}
|
|
2544
2544
|
|
|
2545
|
-
if (!this.
|
|
2545
|
+
if (!this.reloadWithoutWaitingForAppReady()) {
|
|
2546
2546
|
this.implementation.restoreResetState(previousState);
|
|
2547
2547
|
this.restoreLiveBundleStateAfterFailedReload();
|
|
2548
2548
|
return false;
|
|
@@ -2590,13 +2590,8 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2590
2590
|
|
|
2591
2591
|
private boolean leavePreviewSessionWithoutReload(final boolean keepPreviewGuard) {
|
|
2592
2592
|
final BundleInfo previewBundle = this.implementation.getCurrentBundle();
|
|
2593
|
-
final BundleInfo previewFallbackBundle = this.
|
|
2594
|
-
if (previewFallbackBundle == null
|
|
2595
|
-
logger.error("No preview fallback bundle available");
|
|
2596
|
-
return false;
|
|
2597
|
-
}
|
|
2598
|
-
if (!this.implementation.canSet(previewFallbackBundle)) {
|
|
2599
|
-
logger.error("Preview fallback bundle is not installable");
|
|
2593
|
+
final BundleInfo previewFallbackBundle = this.resolvePreviewFallbackBundle("preview deeplink launch");
|
|
2594
|
+
if (previewFallbackBundle == null) {
|
|
2600
2595
|
return false;
|
|
2601
2596
|
}
|
|
2602
2597
|
if (!this.implementation.stagePreviewFallbackReload(previewFallbackBundle)) {
|
|
@@ -2649,20 +2644,15 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2649
2644
|
}
|
|
2650
2645
|
|
|
2651
2646
|
private boolean resetToPreviewFallbackBundle() {
|
|
2652
|
-
final BundleInfo fallback = this.
|
|
2653
|
-
if (fallback == null
|
|
2654
|
-
logger.error("No preview fallback bundle available");
|
|
2655
|
-
return false;
|
|
2656
|
-
}
|
|
2657
|
-
if (!this.implementation.canSet(fallback)) {
|
|
2658
|
-
logger.error("Preview fallback bundle is not installable");
|
|
2647
|
+
final BundleInfo fallback = this.resolvePreviewFallbackBundle("leave preview");
|
|
2648
|
+
if (fallback == null) {
|
|
2659
2649
|
return false;
|
|
2660
2650
|
}
|
|
2661
2651
|
|
|
2662
2652
|
final CapgoUpdater.ResetState previousState = this.implementation.captureResetState();
|
|
2663
2653
|
final String previousBundleName = this.implementation.getCurrentBundle().getVersionName();
|
|
2664
2654
|
logger.info("Resetting to preview fallback bundle: " + fallback.getVersionName());
|
|
2665
|
-
if (this.implementation.stagePreviewFallbackReload(fallback) && this.
|
|
2655
|
+
if (this.implementation.stagePreviewFallbackReload(fallback) && this.reloadWithoutWaitingForAppReady()) {
|
|
2666
2656
|
this.implementation.finalizeResetTransition(previousBundleName, false);
|
|
2667
2657
|
this.notifyBundleSet(fallback);
|
|
2668
2658
|
return true;
|
|
@@ -2672,6 +2662,29 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2672
2662
|
return false;
|
|
2673
2663
|
}
|
|
2674
2664
|
|
|
2665
|
+
private BundleInfo resolvePreviewFallbackBundle(final String reason) {
|
|
2666
|
+
final BundleInfo fallback = this.implementation.getPreviewFallbackBundle();
|
|
2667
|
+
if (fallback != null && !fallback.isErrorStatus() && this.implementation.canSet(fallback)) {
|
|
2668
|
+
return fallback;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
if (fallback == null) {
|
|
2672
|
+
logger.warn("No preview fallback bundle available for " + reason + ". Falling back to builtin bundle.");
|
|
2673
|
+
} else if (fallback.isErrorStatus()) {
|
|
2674
|
+
logger.warn("Preview fallback bundle is in error state for " + reason + ". Falling back to builtin bundle.");
|
|
2675
|
+
} else {
|
|
2676
|
+
logger.warn("Preview fallback bundle is not installable for " + reason + ". Falling back to builtin bundle.");
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
final BundleInfo builtin = this.implementation.getBundleInfo(BundleInfo.ID_BUILTIN);
|
|
2680
|
+
if (builtin != null && !builtin.isErrorStatus() && this.implementation.canSet(builtin)) {
|
|
2681
|
+
return builtin;
|
|
2682
|
+
}
|
|
2683
|
+
|
|
2684
|
+
logger.error("Builtin bundle is not available to leave preview for " + reason);
|
|
2685
|
+
return null;
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2675
2688
|
private void endPreviewSession() {
|
|
2676
2689
|
this.endPreviewSession(false);
|
|
2677
2690
|
}
|
|
@@ -2706,11 +2719,8 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2706
2719
|
|
|
2707
2720
|
private void clearPreviewSessionBecauseDisabled() {
|
|
2708
2721
|
logger.info("Preview session disabled by config; restoring preview fallback");
|
|
2709
|
-
final BundleInfo
|
|
2710
|
-
|
|
2711
|
-
fallback == null || fallback.isErrorStatus() ? this.implementation.getBundleInfo(BundleInfo.ID_BUILTIN) : fallback;
|
|
2712
|
-
|
|
2713
|
-
if (this.implementation.canSet(bundleToRestore)) {
|
|
2722
|
+
final BundleInfo bundleToRestore = this.resolvePreviewFallbackBundle("preview disabled");
|
|
2723
|
+
if (bundleToRestore != null) {
|
|
2714
2724
|
this.implementation.stagePreviewFallbackReload(bundleToRestore);
|
|
2715
2725
|
} else {
|
|
2716
2726
|
logger.warn("Could not restore preview fallback while disabling preview");
|
|
@@ -18,12 +18,15 @@ import androidx.work.WorkManager;
|
|
|
18
18
|
import com.google.common.util.concurrent.Futures;
|
|
19
19
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
20
20
|
import java.io.BufferedInputStream;
|
|
21
|
+
import java.io.BufferedReader;
|
|
21
22
|
import java.io.File;
|
|
22
23
|
import java.io.FileInputStream;
|
|
23
24
|
import java.io.FileNotFoundException;
|
|
24
25
|
import java.io.FileOutputStream;
|
|
25
26
|
import java.io.FilenameFilter;
|
|
26
27
|
import java.io.IOException;
|
|
28
|
+
import java.io.InputStreamReader;
|
|
29
|
+
import java.nio.charset.StandardCharsets;
|
|
27
30
|
import java.security.SecureRandom;
|
|
28
31
|
import java.util.ArrayList;
|
|
29
32
|
import java.util.Date;
|
|
@@ -63,6 +66,8 @@ public class CapgoUpdater {
|
|
|
63
66
|
private static final String PREVIEW_FALLBACK_VERSION = "previewFallbackVersion";
|
|
64
67
|
private static final String bundleDirectory = "versions";
|
|
65
68
|
private static final String TEMP_UNZIP_PREFIX = "capgo_unzip_";
|
|
69
|
+
private static final String CAPACITOR_CONFIG_ASSET = "capacitor.config.json";
|
|
70
|
+
private static final String BACKGROUND_RUNNER_CONFIG_KEY = "BackgroundRunner";
|
|
66
71
|
|
|
67
72
|
public static final String TAG = "Capacitor-updater";
|
|
68
73
|
public SharedPreferences.Editor editor;
|
|
@@ -920,6 +925,7 @@ public class CapgoUpdater {
|
|
|
920
925
|
}
|
|
921
926
|
|
|
922
927
|
private void setCurrentBundle(final File bundle) {
|
|
928
|
+
this.cancelBackgroundRunnerWorkBeforeBundleSwitch();
|
|
923
929
|
this.editor.putString(this.CAP_SERVER_PATH, bundle.getPath());
|
|
924
930
|
logger.info("Current bundle set to: " + bundle);
|
|
925
931
|
this.editor.commit();
|
|
@@ -929,6 +935,73 @@ public class CapgoUpdater {
|
|
|
929
935
|
return bundlePath != null && !bundlePath.trim().isEmpty() && !isBuiltin && !hasStoredBundleInfo;
|
|
930
936
|
}
|
|
931
937
|
|
|
938
|
+
static String getBackgroundRunnerLabelFromConfig(final String configJson) {
|
|
939
|
+
if (configJson == null || configJson.trim().isEmpty()) {
|
|
940
|
+
return null;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
try {
|
|
944
|
+
final JSONObject config = new JSONObject(configJson);
|
|
945
|
+
final JSONObject plugins = config.optJSONObject("plugins");
|
|
946
|
+
if (plugins == null) {
|
|
947
|
+
return null;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
final JSONObject backgroundRunner = plugins.optJSONObject(BACKGROUND_RUNNER_CONFIG_KEY);
|
|
951
|
+
if (backgroundRunner == null) {
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
final String label = backgroundRunner.optString("label", "").trim();
|
|
956
|
+
return label.isEmpty() ? null : label;
|
|
957
|
+
} catch (JSONException ignored) {
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
private String readAssetAsString(final String assetPath) throws IOException {
|
|
963
|
+
final StringBuilder buffer = new StringBuilder();
|
|
964
|
+
try (
|
|
965
|
+
final BufferedReader reader = new BufferedReader(
|
|
966
|
+
new InputStreamReader(this.activity.getAssets().open(assetPath), StandardCharsets.UTF_8)
|
|
967
|
+
)
|
|
968
|
+
) {
|
|
969
|
+
String line;
|
|
970
|
+
while ((line = reader.readLine()) != null) {
|
|
971
|
+
buffer.append(line).append('\n');
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return buffer.toString();
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
private void cancelBackgroundRunnerWorkBeforeBundleSwitch() {
|
|
978
|
+
if (this.activity == null) {
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
final String label;
|
|
983
|
+
try {
|
|
984
|
+
label = getBackgroundRunnerLabelFromConfig(this.readAssetAsString(CAPACITOR_CONFIG_ASSET));
|
|
985
|
+
} catch (IOException ignored) {
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
if (label == null) {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
try {
|
|
994
|
+
final WorkManager workManager = WorkManager.getInstance(this.activity.getApplicationContext());
|
|
995
|
+
workManager.cancelUniqueWork(label);
|
|
996
|
+
workManager.cancelAllWorkByTag(label);
|
|
997
|
+
logger.info("Cancelled Background Runner work before bundle switch.");
|
|
998
|
+
logger.debug("Background Runner label: " + label);
|
|
999
|
+
} catch (Exception e) {
|
|
1000
|
+
logger.warn("Failed to cancel Background Runner work before bundle switch.");
|
|
1001
|
+
logger.debug("Background Runner cancellation error: " + e.getMessage());
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
932
1005
|
private boolean hasStoredBundleInfo(final String id) {
|
|
933
1006
|
return (
|
|
934
1007
|
id != null &&
|
|
@@ -1614,6 +1687,17 @@ public class CapgoUpdater {
|
|
|
1614
1687
|
final String defaultChannelKey,
|
|
1615
1688
|
final boolean allowSetDefaultChannel,
|
|
1616
1689
|
final Callback callback
|
|
1690
|
+
) {
|
|
1691
|
+
this.setChannel(channel, editor, defaultChannelKey, allowSetDefaultChannel, "", callback);
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
public void setChannel(
|
|
1695
|
+
final String channel,
|
|
1696
|
+
final SharedPreferences.Editor editor,
|
|
1697
|
+
final String defaultChannelKey,
|
|
1698
|
+
final boolean allowSetDefaultChannel,
|
|
1699
|
+
final String configDefaultChannel,
|
|
1700
|
+
final Callback callback
|
|
1617
1701
|
) {
|
|
1618
1702
|
// Check if setting defaultChannel is allowed
|
|
1619
1703
|
if (!allowSetDefaultChannel) {
|
|
@@ -1666,6 +1750,7 @@ public class CapgoUpdater {
|
|
|
1666
1750
|
// Clear persisted defaultChannel and revert to config value
|
|
1667
1751
|
editor.remove(defaultChannelKey);
|
|
1668
1752
|
editor.apply();
|
|
1753
|
+
this.defaultChannel = configDefaultChannel;
|
|
1669
1754
|
logger.info("Public channel requested, channel override removed");
|
|
1670
1755
|
callback.callback(res);
|
|
1671
1756
|
} else {
|
|
@@ -1680,6 +1765,10 @@ public class CapgoUpdater {
|
|
|
1680
1765
|
}
|
|
1681
1766
|
|
|
1682
1767
|
public void getChannel(final Callback callback) {
|
|
1768
|
+
this.getChannel(callback, null, null);
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
public void getChannel(final Callback callback, final SharedPreferences.Editor editor, final String defaultChannelKey) {
|
|
1683
1772
|
// Check if rate limit was exceeded
|
|
1684
1773
|
if (rateLimitExceeded) {
|
|
1685
1774
|
logger.debug("Skipping getChannel due to rate limit (429). Requests will resume after app restart.");
|
|
@@ -1798,6 +1887,7 @@ public class CapgoUpdater {
|
|
|
1798
1887
|
ret.put(key, jsonResponse.get(key));
|
|
1799
1888
|
}
|
|
1800
1889
|
}
|
|
1890
|
+
persistDefaultChannelFromResponse(ret.get("channel"), editor, defaultChannelKey);
|
|
1801
1891
|
logger.info("Channel get to \"" + ret);
|
|
1802
1892
|
callback.callback(ret);
|
|
1803
1893
|
} catch (JSONException e) {
|
|
@@ -1811,6 +1901,24 @@ public class CapgoUpdater {
|
|
|
1811
1901
|
);
|
|
1812
1902
|
}
|
|
1813
1903
|
|
|
1904
|
+
void persistDefaultChannelFromResponse(final Object channel, final SharedPreferences.Editor editor, final String defaultChannelKey) {
|
|
1905
|
+
if (!(channel instanceof String)) {
|
|
1906
|
+
return;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
final String channelName = ((String) channel).trim();
|
|
1910
|
+
if (channelName.isEmpty() || BundleInfo.ID_BUILTIN.equals(channelName)) {
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
this.defaultChannel = channelName;
|
|
1915
|
+
if (editor != null && defaultChannelKey != null && !defaultChannelKey.isEmpty()) {
|
|
1916
|
+
editor.putString(defaultChannelKey, channelName);
|
|
1917
|
+
editor.apply();
|
|
1918
|
+
}
|
|
1919
|
+
logger.info("defaultChannel synchronized from getChannel(): " + channelName);
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1814
1922
|
public void listChannels(final Callback callback) {
|
|
1815
1923
|
// Check if rate limit was exceeded
|
|
1816
1924
|
if (rateLimitExceeded) {
|
|
@@ -17,8 +17,8 @@ public class ShakeDetector implements SensorEventListener {
|
|
|
17
17
|
void onShakeDetected();
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
private static final float SHAKE_THRESHOLD =
|
|
21
|
-
private static final int SHAKE_TIMEOUT =
|
|
20
|
+
private static final float SHAKE_THRESHOLD = 16.0f; // Acceleration threshold for shake detection
|
|
21
|
+
private static final int SHAKE_TIMEOUT = 1000; // Minimum time between shake events (ms)
|
|
22
22
|
|
|
23
23
|
private Listener listener;
|
|
24
24
|
private SensorManager sensorManager;
|
|
@@ -34,7 +34,7 @@ public class ShakeDetector implements SensorEventListener {
|
|
|
34
34
|
this.accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
|
35
35
|
|
|
36
36
|
if (accelerometer != null) {
|
|
37
|
-
sensorManager.registerListener(this, accelerometer, SensorManager.
|
|
37
|
+
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -542,6 +542,7 @@ public class ShakeMenu implements ShakeDetector.Listener {
|
|
|
542
542
|
new Thread(() -> {
|
|
543
543
|
final CapgoUpdater updater = plugin.implementation;
|
|
544
544
|
final Bridge bridge = activity.getBridge();
|
|
545
|
+
final String configDefaultChannel = plugin.getConfig().getString("defaultChannel", "");
|
|
545
546
|
|
|
546
547
|
// Set the channel - respect plugin's allowSetDefaultChannel config
|
|
547
548
|
updater.setChannel(
|
|
@@ -549,6 +550,7 @@ public class ShakeMenu implements ShakeDetector.Listener {
|
|
|
549
550
|
updater.editor,
|
|
550
551
|
"CapacitorUpdater.defaultChannel",
|
|
551
552
|
plugin.allowSetDefaultChannel,
|
|
553
|
+
configDefaultChannel,
|
|
552
554
|
(setRes) -> {
|
|
553
555
|
if (setRes == null) {
|
|
554
556
|
activity.runOnUiThread(() -> {
|
package/dist/docs.json
CHANGED
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"text": "{Error} If the download fails or the bundle is invalid."
|
|
157
157
|
}
|
|
158
158
|
],
|
|
159
|
-
"docs": "Download a new bundle from the provided URL for later installation.\n\nThe downloaded bundle is stored locally but not activated. To use it:\n- Call {@link next} to set it for installation on next app backgrounding/restart\n- Call {@link set} to activate it immediately (destroys current JavaScript context)\n\nThe URL should point to a zip file containing either:\n- Your app files directly in the zip root, or\n- A single folder containing all your app files\n\nThe bundle must include an `index.html` file at the root level.\n\nFor encrypted bundles, provide the `sessionKey` and `checksum` parameters.\nFor multi-file delta updates, provide the `manifest` array.",
|
|
159
|
+
"docs": "Download a new bundle from the provided URL for later installation.\n\nThe downloaded bundle is stored locally but not activated. To use it:\n- Call {@link next} to set it for installation on next app backgrounding/restart\n- Call {@link set} to activate it immediately (destroys current JavaScript context)\n\nThe URL should point to a zip file containing either:\n- Your app files directly in the zip root, or\n- A single folder containing all your app files\n\nThe bundle must include an `index.html` file at the root level.\n\nFor encrypted bundles, provide the `sessionKey` and `checksum` parameters.\nFor multi-file delta updates, provide the `manifest` array.\n\n**Android Background Runner note:** `@capacitor/background-runner` loads its\nconfigured runner script from native APK assets. Live updates cannot replace\nthat runner script. Keep it stable across OTA updates and ship a native app\nupdate when the runner code changes.",
|
|
160
160
|
"complexTypes": [
|
|
161
161
|
"BundleInfo",
|
|
162
162
|
"DownloadOptions"
|
|
@@ -720,7 +720,7 @@
|
|
|
720
720
|
"text": "4.8.0"
|
|
721
721
|
}
|
|
722
722
|
],
|
|
723
|
-
"docs": "Get the current channel assigned to this device.\n\nReturns information about:\n- `channel`: The currently assigned channel name (if any)\n- `allowSet`: Whether the channel allows self-assignment\n- `status`: Operation status\n- `error`/`message`: Additional information (if applicable)\n\nUse this to:\n- Display current channel to users (e.g., \"You're on the Beta channel\")\n- Check if a device is on a specific channel before showing features\n- Verify channel assignment after calling {@link setChannel}",
|
|
723
|
+
"docs": "Get the current channel assigned to this device.\n\nReturns information about:\n- `channel`: The currently assigned channel name (if any)\n- `allowSet`: Whether the channel allows self-assignment\n- `status`: Operation status\n- `error`/`message`: Additional information (if applicable)\n\nUse this to:\n- Display current channel to users (e.g., \"You're on the Beta channel\")\n- Check if a device is on a specific channel before showing features\n- Verify channel assignment after calling {@link setChannel}\n\nOn native platforms, a successful response also refreshes the locally persisted\ndefault channel used by update checks.",
|
|
724
724
|
"complexTypes": [
|
|
725
725
|
"GetChannelRes"
|
|
726
726
|
],
|
|
@@ -467,6 +467,11 @@ export interface CapacitorUpdaterPlugin {
|
|
|
467
467
|
* For encrypted bundles, provide the `sessionKey` and `checksum` parameters.
|
|
468
468
|
* For multi-file delta updates, provide the `manifest` array.
|
|
469
469
|
*
|
|
470
|
+
* **Android Background Runner note:** `@capacitor/background-runner` loads its
|
|
471
|
+
* configured runner script from native APK assets. Live updates cannot replace
|
|
472
|
+
* that runner script. Keep it stable across OTA updates and ship a native app
|
|
473
|
+
* update when the runner code changes.
|
|
474
|
+
*
|
|
470
475
|
* @example
|
|
471
476
|
* const bundle = await CapacitorUpdater.download({
|
|
472
477
|
* url: `https://example.com/versions/${version}/dist.zip`,
|
|
@@ -909,6 +914,9 @@ export interface CapacitorUpdaterPlugin {
|
|
|
909
914
|
* - Check if a device is on a specific channel before showing features
|
|
910
915
|
* - Verify channel assignment after calling {@link setChannel}
|
|
911
916
|
*
|
|
917
|
+
* On native platforms, a successful response also refreshes the locally persisted
|
|
918
|
+
* default channel used by update checks.
|
|
919
|
+
*
|
|
912
920
|
* @returns {Promise<GetChannelRes>} The current channel information.
|
|
913
921
|
* @throws {Error} If the operation fails.
|
|
914
922
|
* @since 4.8.0
|