@capawesome/capacitor-live-update 6.0.2 → 6.0.4-dev.39b851d.1715623818
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 +130 -18
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +11 -1
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +1 -1
- package/dist/docs.json +1 -1
- package/dist/esm/definitions.d.ts +3 -0
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Plugin/LiveUpdate.swift +2 -6
- package/ios/Plugin/LiveUpdatePlugin.swift +1 -1
- package/ios/Plugin/LiveUpdatePreferences.swift +0 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Capacitor plugin to update your app remotely in real-time.
|
|
4
4
|
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔋 Supports **Android and iOS**
|
|
8
|
+
- ⚡️ **Capacitor 6** support
|
|
9
|
+
- 📦 **Bundle Management**: Download, set, and delete bundles.
|
|
10
|
+
- ☁️ **Cloud Support**: Use the [Capawesome Cloud](https://capawesome.io/cloud) to manage your app updates.
|
|
11
|
+
- 📺 **Channel Support**: Set a channel for the app to manage different versions.
|
|
12
|
+
- 🔄 **Auto Update**: Automatically download and set the latest bundle for the app.
|
|
13
|
+
- 🛟 **Rollback**: Reset the app to the default bundle if an incompatible bundle has been set.
|
|
14
|
+
|
|
5
15
|
## Installation
|
|
6
16
|
|
|
7
17
|
```bash
|
|
@@ -18,6 +28,35 @@ This plugin will use the following project variables (defined in your app’s `v
|
|
|
18
28
|
- `$okhttp3Version` version of `com.squareup.okhttp3:okhttp` (default: `22.3.1`)
|
|
19
29
|
- `$zip4jVersion` version of `net.lingala.zip4j:zip4j` (default: `2.11.5`)
|
|
20
30
|
|
|
31
|
+
### iOS
|
|
32
|
+
|
|
33
|
+
#### Privacy manifest
|
|
34
|
+
|
|
35
|
+
Add the `NSPrivacyAccessedAPICategoryUserDefaults` dictionary key to your [Privacy Manifest](https://capacitorjs.com/docs/ios/privacy-manifest) (usually `ios/App/PrivacyInfo.xcprivacy`):
|
|
36
|
+
|
|
37
|
+
```xml
|
|
38
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
39
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
40
|
+
<plist version="1.0">
|
|
41
|
+
<dict>
|
|
42
|
+
<key>NSPrivacyAccessedAPITypes</key>
|
|
43
|
+
<array>
|
|
44
|
+
<!-- Add this dict entry to the array if the file already exists. -->
|
|
45
|
+
<dict>
|
|
46
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
47
|
+
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
|
48
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
49
|
+
<array>
|
|
50
|
+
<string>CA92.1</string>
|
|
51
|
+
</array>
|
|
52
|
+
</dict>
|
|
53
|
+
</array>
|
|
54
|
+
</dict>
|
|
55
|
+
</plist>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
We recommend to declare [`CA92.1`](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api#4278401) as the reason for accessing the [`UserDefaults`](https://developer.apple.com/documentation/foundation/userdefaults) API.
|
|
59
|
+
|
|
21
60
|
## Configuration
|
|
22
61
|
|
|
23
62
|
<docgen-config>
|
|
@@ -77,30 +116,85 @@ export default config;
|
|
|
77
116
|
|
|
78
117
|
A working example can be found here: [robingenz/capacitor-plugin-demo](https://github.com/robingenz/capacitor-plugin-demo)
|
|
79
118
|
|
|
119
|
+
## Guides
|
|
120
|
+
|
|
121
|
+
- [Announcing the Capacitor Live Update Plugin](https://capawesome.io/blog/announcing-the-capacitor-live-update-plugin/)
|
|
122
|
+
|
|
80
123
|
## Usage
|
|
81
124
|
|
|
82
125
|
```typescript
|
|
83
126
|
import { LiveUpdate } from '@capawesome/capacitor-live-update';
|
|
84
127
|
|
|
128
|
+
const deleteBundle = async () => {
|
|
129
|
+
await LiveUpdate.deleteBundle({ bundleId: 'my-bundle' });
|
|
130
|
+
};
|
|
131
|
+
|
|
85
132
|
const downloadBundle = async () => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
133
|
+
await LiveUpdate.downloadBundle({ url: 'https://example.com/1.0.0.zip', bundleId: '1.0.0' });
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const getBundle = async () => {
|
|
137
|
+
const result = await LiveUpdate.getBundle();
|
|
138
|
+
return result.bundleId;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const getBundles = async () => {
|
|
142
|
+
const result = await LiveUpdate.getBundles();
|
|
143
|
+
return result.bundleIds;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const getChannel = async () => {
|
|
147
|
+
const result = await LiveUpdate.getChannel();
|
|
148
|
+
return result.channel;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const getCustomId = async () => {
|
|
152
|
+
const result = await LiveUpdate.getCustomId();
|
|
153
|
+
return result.customId;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const getDeviceId = async () => {
|
|
157
|
+
const result = await LiveUpdate.getDeviceId();
|
|
158
|
+
return result.deviceId;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const getVersionCode = async () => {
|
|
162
|
+
const result = await LiveUpdate.getVersionCode();
|
|
163
|
+
return result.versionCode;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const getVersionName = async () => {
|
|
167
|
+
const result = await LiveUpdate.getVersionName();
|
|
168
|
+
return result.versionName;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const ready = async () => {
|
|
172
|
+
await LiveUpdate.ready();
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const reload = async () => {
|
|
176
|
+
await LiveUpdate.reload();
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const reset = async () => {
|
|
180
|
+
await LiveUpdate.reset();
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const setBundle = async () => {
|
|
184
|
+
await LiveUpdate.setBundle({ bundleId: '1.0.0' });
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const setChannel = async () => {
|
|
188
|
+
await LiveUpdate.setChannel({ channel: 'beta' });
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const setCustomId = async () => {
|
|
192
|
+
await LiveUpdate.setCustomId({ customId: 'my-custom-id' });
|
|
95
193
|
};
|
|
96
194
|
|
|
97
195
|
const sync = async () => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (result.nextBundleId) {
|
|
101
|
-
// Reload the app to apply the new bundle
|
|
102
|
-
await LiveUpdate.reload();
|
|
103
|
-
}
|
|
196
|
+
const result = await LiveUpdate.sync();
|
|
197
|
+
return result.nextBundleId;
|
|
104
198
|
};
|
|
105
199
|
```
|
|
106
200
|
|
|
@@ -461,9 +555,9 @@ Only available on Android and iOS.
|
|
|
461
555
|
|
|
462
556
|
#### GetDeviceIdResult
|
|
463
557
|
|
|
464
|
-
| Prop | Type | Description
|
|
465
|
-
| -------------- | ------------------- |
|
|
466
|
-
| **`deviceId`** | <code>string</code> | The unique identifier of the device. | 5.0.0 |
|
|
558
|
+
| Prop | Type | Description | Since |
|
|
559
|
+
| -------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
|
|
560
|
+
| **`deviceId`** | <code>string</code> | The unique identifier of the device. On iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used. The value of this property is the same for apps that come from the same vendor running on the same device. | 5.0.0 |
|
|
467
561
|
|
|
468
562
|
|
|
469
563
|
#### GetVersionCodeResult
|
|
@@ -509,6 +603,24 @@ Only available on Android and iOS.
|
|
|
509
603
|
|
|
510
604
|
</docgen-api>
|
|
511
605
|
|
|
606
|
+
## Testing
|
|
607
|
+
|
|
608
|
+
When testing the plugin, you must make sure that you do not use the [Live Reload](https://ionicframework.com/docs/cli/livereload) option, as in this case a development server is used to load the bundle.
|
|
609
|
+
|
|
610
|
+
Therefore, simply start your app without the live reload option, for example with the following command:
|
|
611
|
+
|
|
612
|
+
```bash
|
|
613
|
+
npx ionic cap run android --open
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
If you want to disable the plugin to test other parts of your app, you can set the [`enabled`](#configuration) configuration option to `false`.
|
|
617
|
+
|
|
618
|
+
## Limitations
|
|
619
|
+
|
|
620
|
+
Live updates are only supported for [binary-compatible changes](https://capawesome.io/cloud/live-updates/faq/#what-are-binary-compatible-changes) (e.g. HTML, CSS, JavaScript).
|
|
621
|
+
If you change native code, such as adding a new plugin, you need to resubmit your app to the app stores.
|
|
622
|
+
For this reason, you must be careful to limit live updates to compatible native versions of your app.
|
|
623
|
+
|
|
512
624
|
## Changelog
|
|
513
625
|
|
|
514
626
|
See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/live-update/CHANGELOG.md).
|
|
@@ -265,6 +265,9 @@ public class LiveUpdate {
|
|
|
265
265
|
throw new Exception(LiveUpdatePlugin.ERROR_BUNDLE_INDEX_HTML_MISSING);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
// Create the bundles directory if it does not exist
|
|
269
|
+
createBundlesDirectory();
|
|
270
|
+
|
|
268
271
|
// Move the bundle directory to the bundles directory
|
|
269
272
|
File bundleDirectory = buildBundleDirectoryFor(bundleId);
|
|
270
273
|
indexHtmlFile.getParentFile().renameTo(bundleDirectory);
|
|
@@ -288,6 +291,13 @@ public class LiveUpdate {
|
|
|
288
291
|
return new File(plugin.getContext().getFilesDir(), bundlesDirectory + "/" + bundle);
|
|
289
292
|
}
|
|
290
293
|
|
|
294
|
+
private void createBundlesDirectory() {
|
|
295
|
+
File bundlesDirectory = buildBundlesDirectory();
|
|
296
|
+
if (!bundlesDirectory.exists()) {
|
|
297
|
+
bundlesDirectory.mkdir();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
291
301
|
private void deleteBundle(@NonNull String bundleId) {
|
|
292
302
|
File bundleDirectory = buildBundleDirectoryFor(bundleId);
|
|
293
303
|
deleteFileRecursively(bundleDirectory);
|
|
@@ -477,7 +487,7 @@ public class LiveUpdate {
|
|
|
477
487
|
private String getDeviceId() {
|
|
478
488
|
String deviceId = preferences.getDeviceIdForApp(config.getAppId());
|
|
479
489
|
if (deviceId == null) {
|
|
480
|
-
deviceId = UUID.randomUUID().toString();
|
|
490
|
+
deviceId = UUID.randomUUID().toString().toLowerCase();
|
|
481
491
|
preferences.setDeviceIdForApp(config.getAppId(), deviceId);
|
|
482
492
|
}
|
|
483
493
|
return deviceId;
|
package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java
CHANGED
|
@@ -19,7 +19,7 @@ import io.capawesome.capacitorjs.plugins.liveupdate.interfaces.Result;
|
|
|
19
19
|
public class LiveUpdatePlugin extends Plugin {
|
|
20
20
|
|
|
21
21
|
public static final String TAG = "LiveUpdate";
|
|
22
|
-
public static final String VERSION = "6.0.
|
|
22
|
+
public static final String VERSION = "6.0.4";
|
|
23
23
|
public static final String SHARED_PREFERENCES_NAME = "CapawesomeLiveUpdate"; // DO NOT CHANGE
|
|
24
24
|
public static final String ERROR_APP_ID_MISSING = "appId must be configured.";
|
|
25
25
|
public static final String ERROR_BUNDLE_EXISTS = "bundle already exists.";
|
package/dist/docs.json
CHANGED
|
@@ -516,7 +516,7 @@
|
|
|
516
516
|
"name": "example"
|
|
517
517
|
}
|
|
518
518
|
],
|
|
519
|
-
"docs": "The unique identifier of the device.",
|
|
519
|
+
"docs": "The unique identifier of the device.\n\nOn iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used.\nThe value of this property is the same for apps that come from the same vendor running on the same device.",
|
|
520
520
|
"complexTypes": [],
|
|
521
521
|
"type": "string"
|
|
522
522
|
}
|
|
@@ -253,6 +253,9 @@ export interface GetDeviceIdResult {
|
|
|
253
253
|
/**
|
|
254
254
|
* The unique identifier of the device.
|
|
255
255
|
*
|
|
256
|
+
* On iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used.
|
|
257
|
+
* The value of this property is the same for apps that come from the same vendor running on the same device.
|
|
258
|
+
*
|
|
256
259
|
* @since 5.0.0
|
|
257
260
|
*
|
|
258
261
|
* @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n LiveUpdate?: {\n /**\n * The app ID is used to identify the app when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * @since 5.0.0\n * @example '4100e356-e851-47fe-9d3c-b411eb325a99'\n */\n appId?: string;\n /**\n * Whether or not to automatically delete unused bundles.\n *\n * When enabled, the plugin will automatically delete unused bundles after calling `ready()`.\n *\n * @since 5.0.0\n * @default false\n */\n autoDeleteBundles?: boolean;\n /**\n * Whether or not the plugin is enabled.\n *\n * @since 5.0.0\n * @default true\n */\n enabled?: boolean;\n /**\n * The timeout in milliseconds to wait for the app to be ready before resetting to the default bundle.\n *\n * @since 5.0.0\n * @default 10000\n */\n readyTimeout?: number;\n /**\n * Whether or not the app should be reset to the default bundle during an update.\n *\n * @since 5.0.0\n * @default true\n */\n resetOnUpdate?: boolean;\n };\n }\n}\n\nexport interface LiveUpdatePlugin {\n /**\n * Delete a bundle from the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n deleteBundle(options: DeleteBundleOptions): Promise<void>;\n /**\n * Download a bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n downloadBundle(options: DownloadBundleOptions): Promise<void>;\n /**\n * Get the active bundle identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundle(): Promise<GetBundleResult>;\n /**\n * Get all available bundle identifiers.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundles(): Promise<GetBundlesResult>;\n /**\n * Get the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getChannel(): Promise<GetChannelResult>;\n /**\n * Get the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getCustomId(): Promise<GetCustomIdResult>;\n /**\n * Get the device identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getDeviceId(): Promise<GetDeviceIdResult>;\n /**\n * Get the version code of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionCode(): Promise<GetVersionCodeResult>;\n /**\n * Get the version name of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionName(): Promise<GetVersionNameResult>;\n /**\n * Notify the plugin that the app is ready to use and no rollback is needed.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n ready(): Promise<void>;\n /**\n * Reload the app to apply the new bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reload(): Promise<void>;\n /**\n * Reset the app to the default bundle.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reset(): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setBundle(options: SetBundleOptions): Promise<void>;\n /**\n * Set the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setChannel(options: SetChannelOptions): Promise<void>;\n /**\n * Set the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n /**\n * Automatically download and set the latest bundle for the app using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n sync(): Promise<SyncResult>;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface DeleteBundleOptions {\n /**\n * The unique identifier of the bundle to delete.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\nexport interface DownloadBundleOptions {\n /**\n * The URL of the bundle to download.\n *\n * The bundle must be a ZIP file containing at least a `index.html` file.\n *\n * @since 5.0.0\n * @example 'https://example.com/bundle.zip'\n */\n url: string;\n /**\n * The unique identifier of the bundle.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundleResult {\n /**\n * The unique identifier of the active bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundlesResult {\n /**\n * An array of unique identifiers of all available bundles.\n *\n * @since 5.0.0\n */\n bundleIds: string[];\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetChannelResult {\n /**\n * The channel of the app.\n *\n * If `null`, the app is using the default channel.\n *\n * @since 5.0.0\n * @example 'production'\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetDeviceIdResult {\n /**\n * The unique identifier of the device.\n *\n * @since 5.0.0\n *\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n deviceId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionCodeResult {\n /**\n * The version code of the app.\n *\n * On **Android**, this is the `versionCode` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleVersion` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1\"\n */\n versionCode: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionNameResult {\n /**\n * The version name of the app.\n *\n * On **Android**, this is the `versionName` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleShortVersionString` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1.0.0\"\n */\n versionName: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetCustomIdResult {\n /**\n * The custom identifier of the app.\n *\n * If `null`, no custom identifier is set.\n *\n * @since 5.0.0\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetChannelOptions {\n /**\n * The channel of the app.\n *\n * Set `null` to remove the channel.\n *\n * @since 5.0.0\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetCustomIdOptions {\n /**\n * The custom identifier of the app.\n *\n * Set `null` to remove the custom identifier.\n *\n * @since 5.0.0\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SyncResult {\n /**\n * The identifier of the next bundle to use.\n *\n * If `null`, the app is up-to-date and no new bundle is available.\n *\n * @since 5.0.0\n */\n nextBundleId: string | null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n LiveUpdate?: {\n /**\n * The app ID is used to identify the app when using [Capawesome Cloud](https://capawesome.io/cloud).\n *\n * @since 5.0.0\n * @example '4100e356-e851-47fe-9d3c-b411eb325a99'\n */\n appId?: string;\n /**\n * Whether or not to automatically delete unused bundles.\n *\n * When enabled, the plugin will automatically delete unused bundles after calling `ready()`.\n *\n * @since 5.0.0\n * @default false\n */\n autoDeleteBundles?: boolean;\n /**\n * Whether or not the plugin is enabled.\n *\n * @since 5.0.0\n * @default true\n */\n enabled?: boolean;\n /**\n * The timeout in milliseconds to wait for the app to be ready before resetting to the default bundle.\n *\n * @since 5.0.0\n * @default 10000\n */\n readyTimeout?: number;\n /**\n * Whether or not the app should be reset to the default bundle during an update.\n *\n * @since 5.0.0\n * @default true\n */\n resetOnUpdate?: boolean;\n };\n }\n}\n\nexport interface LiveUpdatePlugin {\n /**\n * Delete a bundle from the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n deleteBundle(options: DeleteBundleOptions): Promise<void>;\n /**\n * Download a bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n downloadBundle(options: DownloadBundleOptions): Promise<void>;\n /**\n * Get the active bundle identifier.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundle(): Promise<GetBundleResult>;\n /**\n * Get all available bundle identifiers.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getBundles(): Promise<GetBundlesResult>;\n /**\n * Get the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getChannel(): Promise<GetChannelResult>;\n /**\n * Get the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getCustomId(): Promise<GetCustomIdResult>;\n /**\n * Get the device identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getDeviceId(): Promise<GetDeviceIdResult>;\n /**\n * Get the version code of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionCode(): Promise<GetVersionCodeResult>;\n /**\n * Get the version name of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n getVersionName(): Promise<GetVersionNameResult>;\n /**\n * Notify the plugin that the app is ready to use and no rollback is needed.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n ready(): Promise<void>;\n /**\n * Reload the app to apply the new bundle.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reload(): Promise<void>;\n /**\n * Reset the app to the default bundle.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n reset(): Promise<void>;\n /**\n * Set the next bundle to use for the app.\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setBundle(options: SetBundleOptions): Promise<void>;\n /**\n * Set the channel of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setChannel(options: SetChannelOptions): Promise<void>;\n /**\n * Set the custom identifier of the app.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n setCustomId(options: SetCustomIdOptions): Promise<void>;\n /**\n * Automatically download and set the latest bundle for the app using the [Capawesome Cloud](https://capawesome.io/cloud/).\n *\n * Call `reload()` or restart the app to apply the changes.\n *\n * Only available on Android and iOS.\n *\n * @since 5.0.0\n */\n sync(): Promise<SyncResult>;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface DeleteBundleOptions {\n /**\n * The unique identifier of the bundle to delete.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\nexport interface DownloadBundleOptions {\n /**\n * The URL of the bundle to download.\n *\n * The bundle must be a ZIP file containing at least a `index.html` file.\n *\n * @since 5.0.0\n * @example 'https://example.com/bundle.zip'\n */\n url: string;\n /**\n * The unique identifier of the bundle.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundleResult {\n /**\n * The unique identifier of the active bundle.\n *\n * If `null`, the default bundle is being used.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetBundlesResult {\n /**\n * An array of unique identifiers of all available bundles.\n *\n * @since 5.0.0\n */\n bundleIds: string[];\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetChannelResult {\n /**\n * The channel of the app.\n *\n * If `null`, the app is using the default channel.\n *\n * @since 5.0.0\n * @example 'production'\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetDeviceIdResult {\n /**\n * The unique identifier of the device.\n *\n * On iOS, [`identifierForVendor`](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) is used.\n * The value of this property is the same for apps that come from the same vendor running on the same device.\n *\n * @since 5.0.0\n *\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n deviceId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionCodeResult {\n /**\n * The version code of the app.\n *\n * On **Android**, this is the `versionCode` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleVersion` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1\"\n */\n versionCode: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetVersionNameResult {\n /**\n * The version name of the app.\n *\n * On **Android**, this is the `versionName` from the `android/app/build.gradle` file.\n * On **iOS**, this is the `CFBundleShortVersionString` from the `Info.plist` file.\n *\n * @since 5.0.0\n * @example \"1.0.0\"\n */\n versionName: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface GetCustomIdResult {\n /**\n * The custom identifier of the app.\n *\n * If `null`, no custom identifier is set.\n *\n * @since 5.0.0\n * @example '50d2a548-80b7-4dad-adc7-97c0e79d8a89'\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetBundleOptions {\n /**\n * The unique identifier of the bundle to use.\n *\n * @since 5.0.0\n * @example '1.0.0'\n */\n bundleId: string;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetChannelOptions {\n /**\n * The channel of the app.\n *\n * Set `null` to remove the channel.\n *\n * @since 5.0.0\n */\n channel: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SetCustomIdOptions {\n /**\n * The custom identifier of the app.\n *\n * Set `null` to remove the custom identifier.\n *\n * @since 5.0.0\n */\n customId: string | null;\n}\n\n/**\n * @since 5.0.0\n */\nexport interface SyncResult {\n /**\n * The identifier of the next bundle to use.\n *\n * If `null`, the app is up-to-date and no new bundle is available.\n *\n * @since 5.0.0\n */\n nextBundleId: string | null;\n}\n"]}
|
|
@@ -386,12 +386,8 @@ import Alamofire
|
|
|
386
386
|
}
|
|
387
387
|
|
|
388
388
|
private func getDeviceId() -> String {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
let deviceId = UUID().uuidString
|
|
393
|
-
preferences.setDeviceIdForApp(appId: config.appId, deviceId)
|
|
394
|
-
return deviceId
|
|
389
|
+
let deviceId = UIDevice.current.identifierForVendor?.uuidString ?? ""
|
|
390
|
+
return deviceId.lowercased()
|
|
395
391
|
}
|
|
396
392
|
|
|
397
393
|
private func getNextBundleId() -> String? {
|
|
@@ -8,7 +8,7 @@ import Capacitor
|
|
|
8
8
|
@objc(LiveUpdatePlugin)
|
|
9
9
|
public class LiveUpdatePlugin: CAPPlugin {
|
|
10
10
|
public static let tag = "LiveUpdate"
|
|
11
|
-
public static let version = "6.0.
|
|
11
|
+
public static let version = "6.0.4"
|
|
12
12
|
public static let userDefaultsPrefix = "CapawesomeLiveUpdate" // DO NOT CHANGE
|
|
13
13
|
|
|
14
14
|
private var config: LiveUpdateConfig?
|
|
@@ -2,7 +2,6 @@ import Foundation
|
|
|
2
2
|
|
|
3
3
|
public class LiveUpdatePreferences: NSObject {
|
|
4
4
|
private let channelKey = "channel" // DO NOT CHANGE
|
|
5
|
-
private let deviceIdKey = "deviceId" // DO NOT CHANGE
|
|
6
5
|
private let customIdKey = "customId" // DO NOT CHANGE
|
|
7
6
|
private let lastBundleVersionKey = "lastBundleVersion" // DO NOT CHANGE
|
|
8
7
|
|
|
@@ -10,14 +9,6 @@ public class LiveUpdatePreferences: NSObject {
|
|
|
10
9
|
return UserDefaults.standard.string(forKey: applyPrefix(to: channelKey))
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
public func getDeviceIdForApp(appId: String?) -> String? {
|
|
14
|
-
if let appId = appId {
|
|
15
|
-
return UserDefaults.standard.string(forKey: applyPrefix(to: deviceIdKey + "_" + appId))
|
|
16
|
-
} else {
|
|
17
|
-
return UserDefaults.standard.string(forKey: applyPrefix(to: deviceIdKey))
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
12
|
public func getCustomId() -> String? {
|
|
22
13
|
return UserDefaults.standard.string(forKey: applyPrefix(to: customIdKey))
|
|
23
14
|
}
|
|
@@ -35,15 +26,6 @@ public class LiveUpdatePreferences: NSObject {
|
|
|
35
26
|
UserDefaults.standard.synchronize()
|
|
36
27
|
}
|
|
37
28
|
|
|
38
|
-
public func setDeviceIdForApp(appId: String?, _ value: String) {
|
|
39
|
-
if let appId = appId {
|
|
40
|
-
UserDefaults.standard.set(value, forKey: applyPrefix(to: deviceIdKey + "_" + appId))
|
|
41
|
-
} else {
|
|
42
|
-
UserDefaults.standard.set(value, forKey: applyPrefix(to: deviceIdKey))
|
|
43
|
-
}
|
|
44
|
-
UserDefaults.standard.synchronize()
|
|
45
|
-
}
|
|
46
|
-
|
|
47
29
|
public func setCustomId(_ value: String) {
|
|
48
30
|
UserDefaults.standard.set(value, forKey: applyPrefix(to: customIdKey))
|
|
49
31
|
UserDefaults.standard.synchronize()
|
package/package.json
CHANGED