native-update 1.0.6 → 1.0.7
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 +21 -13
- package/android/build.gradle +15 -15
- package/android/variables.gradle +5 -0
- package/docs/BUNDLE_SIGNING.md +1 -1
- package/docs/api/live-update-api.md +1 -1
- package/docs/examples/advanced-scenarios.md +1 -1
- package/docs/features/app-reviews.md +11 -11
- package/docs/features/app-updates.md +20 -20
- package/docs/features/live-updates.md +30 -30
- package/docs/getting-started/configuration.md +3 -3
- package/docs/getting-started/installation.md +2 -2
- package/docs/getting-started/quick-start.md +23 -23
- package/docs/guides/testing-guide.md +2 -2
- package/package.json +1 -1
package/Readme.md
CHANGED
|
@@ -112,18 +112,26 @@ async function initializeApp() {
|
|
|
112
112
|
// Check and apply live updates
|
|
113
113
|
async function checkLiveUpdates() {
|
|
114
114
|
try {
|
|
115
|
-
const
|
|
115
|
+
const result = await NativeUpdate.sync();
|
|
116
116
|
|
|
117
|
-
if (
|
|
118
|
-
// Download update with progress
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
if (result.status === 'UPDATE_AVAILABLE') {
|
|
118
|
+
// Download update with progress tracking
|
|
119
|
+
const listener = NativeUpdate.addListener('downloadProgress', (progress) => {
|
|
120
|
+
console.log(`Downloading: ${progress.percent}%`);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Download the update
|
|
124
|
+
const bundle = await NativeUpdate.download({
|
|
125
|
+
url: result.url,
|
|
126
|
+
version: result.version,
|
|
127
|
+
checksum: result.checksum
|
|
123
128
|
});
|
|
124
129
|
|
|
125
|
-
//
|
|
126
|
-
await NativeUpdate.
|
|
130
|
+
// Set the bundle and reload
|
|
131
|
+
await NativeUpdate.set(bundle);
|
|
132
|
+
await NativeUpdate.reload();
|
|
133
|
+
|
|
134
|
+
listener.remove();
|
|
127
135
|
}
|
|
128
136
|
} catch (error) {
|
|
129
137
|
console.error('Update failed:', error);
|
|
@@ -136,7 +144,7 @@ async function checkLiveUpdates() {
|
|
|
136
144
|
```typescript
|
|
137
145
|
// Check for app store updates
|
|
138
146
|
async function checkNativeUpdates() {
|
|
139
|
-
const result = await NativeUpdate.
|
|
147
|
+
const result = await NativeUpdate.getAppUpdateInfo();
|
|
140
148
|
|
|
141
149
|
if (result.updateAvailable) {
|
|
142
150
|
if (result.immediateUpdateAllowed) {
|
|
@@ -220,9 +228,9 @@ export class AppComponent implements OnInit {
|
|
|
220
228
|
}
|
|
221
229
|
|
|
222
230
|
async installLiveUpdate() {
|
|
223
|
-
//
|
|
224
|
-
|
|
225
|
-
await NativeUpdate.
|
|
231
|
+
// The sync method already handles download if needed
|
|
232
|
+
// Just reload to apply the update
|
|
233
|
+
await NativeUpdate.reload(); // App restarts
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
// Request review after positive events
|
package/android/build.gradle
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
buildscript {
|
|
2
|
-
ext {
|
|
3
|
-
kotlinVersion = '1.9.22'
|
|
4
|
-
}
|
|
5
2
|
repositories {
|
|
6
3
|
google()
|
|
7
4
|
mavenCentral()
|
|
8
5
|
}
|
|
9
6
|
dependencies {
|
|
10
7
|
classpath 'com.android.tools.build:gradle:8.7.2'
|
|
11
|
-
classpath
|
|
8
|
+
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22'
|
|
12
9
|
}
|
|
13
10
|
}
|
|
14
11
|
|
|
15
12
|
ext {
|
|
13
|
+
kotlinVersion = '1.9.22'
|
|
16
14
|
compileSdkVersion = 34
|
|
17
15
|
targetSdkVersion = 34
|
|
18
16
|
minSdkVersion = 21
|
|
@@ -20,7 +18,9 @@ ext {
|
|
|
20
18
|
androidxCoreVersion = '1.13.1'
|
|
21
19
|
androidxWorkVersion = '2.9.0'
|
|
22
20
|
playAppUpdateVersion = '2.1.0'
|
|
21
|
+
playAppUpdateKtxVersion = '2.1.0'
|
|
23
22
|
playReviewVersion = '2.0.1'
|
|
23
|
+
playReviewKtxVersion = '2.0.1'
|
|
24
24
|
okhttpVersion = '4.12.0'
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -70,22 +70,22 @@ dependencies {
|
|
|
70
70
|
implementation project(':capacitor-android')
|
|
71
71
|
|
|
72
72
|
// Kotlin
|
|
73
|
-
implementation
|
|
73
|
+
implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.9.22'
|
|
74
74
|
|
|
75
75
|
// AndroidX
|
|
76
|
-
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
77
|
-
implementation "androidx.core:core-ktx:$androidxCoreVersion"
|
|
78
|
-
implementation "androidx.work:work-runtime-ktx:$androidxWorkVersion"
|
|
76
|
+
implementation "androidx.appcompat:appcompat:${androidxAppCompatVersion}"
|
|
77
|
+
implementation "androidx.core:core-ktx:${androidxCoreVersion}"
|
|
78
|
+
implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}"
|
|
79
79
|
|
|
80
|
-
// Google Play Services
|
|
81
|
-
implementation
|
|
82
|
-
implementation
|
|
83
|
-
implementation
|
|
84
|
-
implementation
|
|
80
|
+
// Google Play Services - Using explicit versions to avoid resolution issues
|
|
81
|
+
implementation 'com.google.android.play:app-update:2.1.0'
|
|
82
|
+
implementation 'com.google.android.play:app-update-ktx:2.1.0'
|
|
83
|
+
implementation 'com.google.android.play:review:2.0.1'
|
|
84
|
+
implementation 'com.google.android.play:review-ktx:2.0.1'
|
|
85
85
|
|
|
86
86
|
// OkHttp for secure network requests
|
|
87
|
-
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
|
88
|
-
implementation "com.squareup.okhttp3:okhttp-tls:$okhttpVersion"
|
|
87
|
+
implementation "com.squareup.okhttp3:okhttp:${okhttpVersion}"
|
|
88
|
+
implementation "com.squareup.okhttp3:okhttp-tls:${okhttpVersion}"
|
|
89
89
|
|
|
90
90
|
// Security
|
|
91
91
|
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
package/docs/BUNDLE_SIGNING.md
CHANGED
|
@@ -242,7 +242,7 @@ Response: {
|
|
|
242
242
|
```typescript
|
|
243
243
|
// Signature verification is handled automatically during sync/download
|
|
244
244
|
// Use validateUpdate for manual verification
|
|
245
|
-
const result = await NativeUpdate.
|
|
245
|
+
const result = await NativeUpdate.validateUpdate({
|
|
246
246
|
bundlePath: '/path/to/bundle.zip',
|
|
247
247
|
checksum: 'expected-sha256-checksum',
|
|
248
248
|
signature: 'base64-signature' // Optional
|
|
@@ -170,7 +170,7 @@ await NativeUpdate.setUpdateUrl(url: string);
|
|
|
170
170
|
Validate a bundle's integrity.
|
|
171
171
|
|
|
172
172
|
```typescript
|
|
173
|
-
const result = await NativeUpdate.
|
|
173
|
+
const result = await NativeUpdate.validateUpdate({
|
|
174
174
|
bundlePath: string;
|
|
175
175
|
checksum: string;
|
|
176
176
|
signature?: string;
|
|
@@ -312,7 +312,7 @@ async function downloadWithIntegrityCheck(url: string, expectedHash: string) {
|
|
|
312
312
|
});
|
|
313
313
|
|
|
314
314
|
// Additional verification
|
|
315
|
-
const verified = await NativeUpdate.
|
|
315
|
+
const verified = await NativeUpdate.validateUpdate({
|
|
316
316
|
bundlePath: download.path,
|
|
317
317
|
checksum: download.checksum,
|
|
318
318
|
signature: 'bundle-signature'
|
|
@@ -75,11 +75,11 @@ await NativeUpdate.configure({
|
|
|
75
75
|
async function requestReview() {
|
|
76
76
|
try {
|
|
77
77
|
// Check if we can request a review
|
|
78
|
-
const canRequest = await NativeUpdate.
|
|
78
|
+
const canRequest = await NativeUpdate.canRequestReview();
|
|
79
79
|
|
|
80
80
|
if (canRequest.allowed) {
|
|
81
81
|
// Request the review
|
|
82
|
-
const result = await NativeUpdate.
|
|
82
|
+
const result = await NativeUpdate.requestReview();
|
|
83
83
|
|
|
84
84
|
if (result.shown) {
|
|
85
85
|
console.log('Review dialog was shown');
|
|
@@ -182,7 +182,7 @@ class AppReviewManager {
|
|
|
182
182
|
|
|
183
183
|
private async analyzeReviewReadiness() {
|
|
184
184
|
// Check basic eligibility
|
|
185
|
-
const canRequest = await NativeUpdate.
|
|
185
|
+
const canRequest = await NativeUpdate.canRequestReview();
|
|
186
186
|
|
|
187
187
|
if (!canRequest.allowed) {
|
|
188
188
|
return {
|
|
@@ -243,7 +243,7 @@ class AppReviewManager {
|
|
|
243
243
|
|
|
244
244
|
async requestReview() {
|
|
245
245
|
try {
|
|
246
|
-
const result = await NativeUpdate.
|
|
246
|
+
const result = await NativeUpdate.requestReview();
|
|
247
247
|
|
|
248
248
|
// Track the request
|
|
249
249
|
this.trackReviewRequest(result);
|
|
@@ -367,7 +367,7 @@ class ReviewFatigueManager {
|
|
|
367
367
|
async canRequestReview(): Promise<boolean> {
|
|
368
368
|
// Check platform limits
|
|
369
369
|
const platformCheck =
|
|
370
|
-
await NativeUpdate.
|
|
370
|
+
await NativeUpdate.canRequestReview();
|
|
371
371
|
|
|
372
372
|
if (!platformCheck.allowed) {
|
|
373
373
|
return false;
|
|
@@ -596,7 +596,7 @@ class iOSReviewManager {
|
|
|
596
596
|
async requestReview(): Promise<ReviewResult> {
|
|
597
597
|
try {
|
|
598
598
|
// Use StoreKit review controller
|
|
599
|
-
const result = await NativeUpdate.
|
|
599
|
+
const result = await NativeUpdate.requestReview();
|
|
600
600
|
|
|
601
601
|
// iOS handles everything natively
|
|
602
602
|
return {
|
|
@@ -614,7 +614,7 @@ class iOSReviewManager {
|
|
|
614
614
|
|
|
615
615
|
private async fallbackToAppStore() {
|
|
616
616
|
// Open App Store page
|
|
617
|
-
await NativeUpdate.
|
|
617
|
+
await NativeUpdate.openAppStore();
|
|
618
618
|
|
|
619
619
|
return {
|
|
620
620
|
shown: true,
|
|
@@ -633,7 +633,7 @@ class AndroidReviewManager {
|
|
|
633
633
|
async requestReview(): Promise<ReviewResult> {
|
|
634
634
|
try {
|
|
635
635
|
// Use Play Core in-app review
|
|
636
|
-
const result = await NativeUpdate.
|
|
636
|
+
const result = await NativeUpdate.requestReview();
|
|
637
637
|
|
|
638
638
|
return {
|
|
639
639
|
shown: result.shown,
|
|
@@ -650,7 +650,7 @@ class AndroidReviewManager {
|
|
|
650
650
|
|
|
651
651
|
private async fallbackToPlayStore() {
|
|
652
652
|
// Open Play Store page
|
|
653
|
-
await NativeUpdate.
|
|
653
|
+
await NativeUpdate.openAppStore();
|
|
654
654
|
|
|
655
655
|
return {
|
|
656
656
|
shown: true,
|
|
@@ -921,10 +921,10 @@ const debugConfig = {
|
|
|
921
921
|
// Test different scenarios
|
|
922
922
|
async function testReviewScenarios() {
|
|
923
923
|
// Test immediate request
|
|
924
|
-
await NativeUpdate.
|
|
924
|
+
await NativeUpdate.requestReview();
|
|
925
925
|
|
|
926
926
|
// Test eligibility check
|
|
927
|
-
const canRequest = await NativeUpdate.
|
|
927
|
+
const canRequest = await NativeUpdate.canRequestReview();
|
|
928
928
|
console.log('Can request review:', canRequest);
|
|
929
929
|
|
|
930
930
|
// Test custom triggers
|
|
@@ -44,7 +44,7 @@ While Live Updates handle web assets, App Updates manage the native app binary i
|
|
|
44
44
|
// Check for app updates on startup
|
|
45
45
|
async function checkForAppUpdates() {
|
|
46
46
|
try {
|
|
47
|
-
const updateInfo = await NativeUpdate.
|
|
47
|
+
const updateInfo = await NativeUpdate.getAppUpdateInfo();
|
|
48
48
|
|
|
49
49
|
if (updateInfo.updateAvailable) {
|
|
50
50
|
console.log(`Update available: ${updateInfo.availableVersion}`);
|
|
@@ -52,7 +52,7 @@ async function checkForAppUpdates() {
|
|
|
52
52
|
// Handle based on priority
|
|
53
53
|
if (updateInfo.updatePriority >= 4) {
|
|
54
54
|
// High priority - immediate update
|
|
55
|
-
await NativeUpdate.
|
|
55
|
+
await NativeUpdate.performImmediateUpdate();
|
|
56
56
|
} else {
|
|
57
57
|
// Optional update - show custom UI
|
|
58
58
|
showUpdateDialog(updateInfo);
|
|
@@ -94,7 +94,7 @@ class AppUpdateManager {
|
|
|
94
94
|
|
|
95
95
|
private setupUpdateListeners() {
|
|
96
96
|
// Android flexible update state changes
|
|
97
|
-
NativeUpdate.
|
|
97
|
+
NativeUpdate.addListener(
|
|
98
98
|
'flexibleUpdateStateChanged',
|
|
99
99
|
(state) => {
|
|
100
100
|
this.handleFlexibleUpdateState(state);
|
|
@@ -102,7 +102,7 @@ class AppUpdateManager {
|
|
|
102
102
|
);
|
|
103
103
|
|
|
104
104
|
// Download progress for flexible updates
|
|
105
|
-
NativeUpdate.
|
|
105
|
+
NativeUpdate.addListener(
|
|
106
106
|
'flexibleUpdateProgress',
|
|
107
107
|
(progress) => {
|
|
108
108
|
this.downloadProgress = progress.percent;
|
|
@@ -114,7 +114,7 @@ class AppUpdateManager {
|
|
|
114
114
|
async checkForUpdates() {
|
|
115
115
|
try {
|
|
116
116
|
this.updateInfo =
|
|
117
|
-
await NativeUpdate.
|
|
117
|
+
await NativeUpdate.getAppUpdateInfo();
|
|
118
118
|
|
|
119
119
|
if (!this.updateInfo.updateAvailable) {
|
|
120
120
|
console.log('App is up to date');
|
|
@@ -166,7 +166,7 @@ class AppUpdateManager {
|
|
|
166
166
|
this.showImmediateUpdateUI();
|
|
167
167
|
|
|
168
168
|
// Start immediate update
|
|
169
|
-
await NativeUpdate.
|
|
169
|
+
await NativeUpdate.performImmediateUpdate();
|
|
170
170
|
|
|
171
171
|
// App will restart automatically after update
|
|
172
172
|
} catch (error) {
|
|
@@ -183,7 +183,7 @@ class AppUpdateManager {
|
|
|
183
183
|
async startFlexibleUpdate() {
|
|
184
184
|
try {
|
|
185
185
|
// Start background download
|
|
186
|
-
await NativeUpdate.
|
|
186
|
+
await NativeUpdate.startFlexibleUpdate();
|
|
187
187
|
|
|
188
188
|
// Show download progress UI
|
|
189
189
|
this.showFlexibleUpdateUI();
|
|
@@ -223,7 +223,7 @@ class AppUpdateManager {
|
|
|
223
223
|
|
|
224
224
|
async completeFlexibleUpdate() {
|
|
225
225
|
try {
|
|
226
|
-
await NativeUpdate.
|
|
226
|
+
await NativeUpdate.completeFlexibleUpdate();
|
|
227
227
|
// App will restart with new version
|
|
228
228
|
} catch (error) {
|
|
229
229
|
console.error('Failed to complete update:', error);
|
|
@@ -265,17 +265,17 @@ const androidUpdate = {
|
|
|
265
265
|
// Immediate update flow
|
|
266
266
|
immediate: async () => {
|
|
267
267
|
// Blocks UI until update is installed
|
|
268
|
-
await NativeUpdate.
|
|
268
|
+
await NativeUpdate.performImmediateUpdate();
|
|
269
269
|
// App restarts automatically
|
|
270
270
|
},
|
|
271
271
|
|
|
272
272
|
// Flexible update flow
|
|
273
273
|
flexible: async () => {
|
|
274
274
|
// Download in background
|
|
275
|
-
await NativeUpdate.
|
|
275
|
+
await NativeUpdate.startFlexibleUpdate();
|
|
276
276
|
|
|
277
277
|
// Monitor progress
|
|
278
|
-
const listener = await NativeUpdate.
|
|
278
|
+
const listener = await NativeUpdate.addListener(
|
|
279
279
|
'flexibleUpdateProgress',
|
|
280
280
|
(progress) => {
|
|
281
281
|
console.log(
|
|
@@ -285,7 +285,7 @@ const androidUpdate = {
|
|
|
285
285
|
);
|
|
286
286
|
|
|
287
287
|
// Complete when ready
|
|
288
|
-
await NativeUpdate.
|
|
288
|
+
await NativeUpdate.completeFlexibleUpdate();
|
|
289
289
|
},
|
|
290
290
|
};
|
|
291
291
|
```
|
|
@@ -299,7 +299,7 @@ iOS requires manual version checking and App Store redirection:
|
|
|
299
299
|
const iosUpdate = {
|
|
300
300
|
// Check version manually
|
|
301
301
|
check: async () => {
|
|
302
|
-
const info = await NativeUpdate.
|
|
302
|
+
const info = await NativeUpdate.getAppUpdateInfo();
|
|
303
303
|
|
|
304
304
|
if (info.updateAvailable) {
|
|
305
305
|
// Show custom update dialog
|
|
@@ -307,7 +307,7 @@ const iosUpdate = {
|
|
|
307
307
|
|
|
308
308
|
if (shouldUpdate) {
|
|
309
309
|
// Open App Store
|
|
310
|
-
await NativeUpdate.
|
|
310
|
+
await NativeUpdate.openAppStore();
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
313
|
},
|
|
@@ -322,7 +322,7 @@ Web platforms show update notifications:
|
|
|
322
322
|
// Web fallback
|
|
323
323
|
const webUpdate = {
|
|
324
324
|
notify: async () => {
|
|
325
|
-
const info = await NativeUpdate.
|
|
325
|
+
const info = await NativeUpdate.getAppUpdateInfo();
|
|
326
326
|
|
|
327
327
|
if (info.updateAvailable) {
|
|
328
328
|
// Show notification
|
|
@@ -455,13 +455,13 @@ async function enforceMinimumVersion() {
|
|
|
455
455
|
},
|
|
456
456
|
};
|
|
457
457
|
|
|
458
|
-
const info = await NativeUpdate.
|
|
458
|
+
const info = await NativeUpdate.getAppUpdateInfo();
|
|
459
459
|
|
|
460
460
|
// Check if current version is below minimum
|
|
461
461
|
if (isVersionBelow(info.currentVersion, config.appUpdate.minimumVersion)) {
|
|
462
462
|
// Force immediate update
|
|
463
463
|
try {
|
|
464
|
-
await NativeUpdate.
|
|
464
|
+
await NativeUpdate.performImmediateUpdate();
|
|
465
465
|
} catch (error) {
|
|
466
466
|
// If update fails or is cancelled, restrict app usage
|
|
467
467
|
showMinimumVersionRequired();
|
|
@@ -550,7 +550,7 @@ class UpdateProgressUI {
|
|
|
550
550
|
showProgress() {
|
|
551
551
|
this.createProgressUI();
|
|
552
552
|
|
|
553
|
-
NativeUpdate.
|
|
553
|
+
NativeUpdate.addListener(
|
|
554
554
|
'flexibleUpdateProgress',
|
|
555
555
|
(progress) => {
|
|
556
556
|
this.updateProgress(progress);
|
|
@@ -587,7 +587,7 @@ class UpdateProgressUI {
|
|
|
587
587
|
```typescript
|
|
588
588
|
async function handleAppUpdateErrors() {
|
|
589
589
|
try {
|
|
590
|
-
await NativeUpdate.
|
|
590
|
+
await NativeUpdate.performImmediateUpdate();
|
|
591
591
|
} catch (error) {
|
|
592
592
|
switch (error.code) {
|
|
593
593
|
case 'UPDATE_NOT_AVAILABLE':
|
|
@@ -635,7 +635,7 @@ class UpdateRetryStrategy {
|
|
|
635
635
|
|
|
636
636
|
async retryUpdate() {
|
|
637
637
|
try {
|
|
638
|
-
await NativeUpdate.
|
|
638
|
+
await NativeUpdate.startFlexibleUpdate();
|
|
639
639
|
this.retryCount = 0;
|
|
640
640
|
} catch (error) {
|
|
641
641
|
if (this.shouldRetry(error)) {
|
|
@@ -66,7 +66,7 @@ await NativeUpdate.configure({
|
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
// 2. Sync updates (automatic with autoUpdate: true)
|
|
69
|
-
const result = await NativeUpdate.
|
|
69
|
+
const result = await NativeUpdate.sync();
|
|
70
70
|
|
|
71
71
|
// 3. Handle the result
|
|
72
72
|
switch (result.status) {
|
|
@@ -108,7 +108,7 @@ class LiveUpdateManager {
|
|
|
108
108
|
|
|
109
109
|
private setupUpdateListeners() {
|
|
110
110
|
// Download progress
|
|
111
|
-
NativeUpdate.
|
|
111
|
+
NativeUpdate.addListener(
|
|
112
112
|
'downloadProgress',
|
|
113
113
|
(progress) => {
|
|
114
114
|
this.updateDownloadProgress(progress.percent);
|
|
@@ -116,7 +116,7 @@ class LiveUpdateManager {
|
|
|
116
116
|
);
|
|
117
117
|
|
|
118
118
|
// State changes
|
|
119
|
-
NativeUpdate.
|
|
119
|
+
NativeUpdate.addListener(
|
|
120
120
|
'updateStateChanged',
|
|
121
121
|
(event) => {
|
|
122
122
|
this.handleStateChange(event);
|
|
@@ -126,8 +126,8 @@ class LiveUpdateManager {
|
|
|
126
126
|
|
|
127
127
|
async checkForUpdates() {
|
|
128
128
|
try {
|
|
129
|
-
const latest = await NativeUpdate.
|
|
130
|
-
const current = await NativeUpdate.
|
|
129
|
+
const latest = await NativeUpdate.getLatest();
|
|
130
|
+
const current = await NativeUpdate.current();
|
|
131
131
|
|
|
132
132
|
if (this.isNewerVersion(latest.version, current.version)) {
|
|
133
133
|
this.updateAvailable = true;
|
|
@@ -142,7 +142,7 @@ class LiveUpdateManager {
|
|
|
142
142
|
if (!this.updateAvailable) return;
|
|
143
143
|
|
|
144
144
|
try {
|
|
145
|
-
const bundle = await NativeUpdate.
|
|
145
|
+
const bundle = await NativeUpdate.download({
|
|
146
146
|
version: 'latest',
|
|
147
147
|
onProgress: (progress) => {
|
|
148
148
|
console.log(`Download: ${progress.percent}%`);
|
|
@@ -150,7 +150,7 @@ class LiveUpdateManager {
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
// Validate the bundle
|
|
153
|
-
const validation = await NativeUpdate.
|
|
153
|
+
const validation = await NativeUpdate.validateUpdate({
|
|
154
154
|
bundleId: bundle.bundleId,
|
|
155
155
|
});
|
|
156
156
|
|
|
@@ -166,10 +166,10 @@ class LiveUpdateManager {
|
|
|
166
166
|
|
|
167
167
|
async installUpdate(bundle: BundleInfo) {
|
|
168
168
|
// Set the bundle as active
|
|
169
|
-
await NativeUpdate.
|
|
169
|
+
await NativeUpdate.set(bundle);
|
|
170
170
|
|
|
171
171
|
// Notify app is ready (important for rollback mechanism)
|
|
172
|
-
await NativeUpdate.
|
|
172
|
+
await NativeUpdate.notifyAppReady();
|
|
173
173
|
|
|
174
174
|
// Schedule reload based on user preference
|
|
175
175
|
this.scheduleReload();
|
|
@@ -177,12 +177,12 @@ class LiveUpdateManager {
|
|
|
177
177
|
|
|
178
178
|
private scheduleReload() {
|
|
179
179
|
// Option 1: Immediate reload
|
|
180
|
-
// await NativeUpdate.
|
|
180
|
+
// await NativeUpdate.reload();
|
|
181
181
|
|
|
182
182
|
// Option 2: Reload on next app resume
|
|
183
183
|
App.addListener('appStateChange', ({ isActive }) => {
|
|
184
184
|
if (isActive) {
|
|
185
|
-
NativeUpdate.
|
|
185
|
+
NativeUpdate.reload();
|
|
186
186
|
}
|
|
187
187
|
});
|
|
188
188
|
|
|
@@ -254,7 +254,7 @@ The plugin uses semantic versioning (MAJOR.MINOR.PATCH):
|
|
|
254
254
|
|
|
255
255
|
```typescript
|
|
256
256
|
// Version comparison
|
|
257
|
-
const current = await NativeUpdate.
|
|
257
|
+
const current = await NativeUpdate.current();
|
|
258
258
|
console.log(current.version); // "1.2.3"
|
|
259
259
|
|
|
260
260
|
// Check if update is major/minor/patch
|
|
@@ -273,7 +273,7 @@ function getUpdateType(oldVersion: string, newVersion: string) {
|
|
|
273
273
|
|
|
274
274
|
```typescript
|
|
275
275
|
// List all downloaded bundles
|
|
276
|
-
const bundles = await NativeUpdate.
|
|
276
|
+
const bundles = await NativeUpdate.list();
|
|
277
277
|
|
|
278
278
|
bundles.forEach((bundle) => {
|
|
279
279
|
console.log(`Version: ${bundle.version}`);
|
|
@@ -283,7 +283,7 @@ bundles.forEach((bundle) => {
|
|
|
283
283
|
});
|
|
284
284
|
|
|
285
285
|
// Clean up old bundles
|
|
286
|
-
await NativeUpdate.
|
|
286
|
+
await NativeUpdate.delete({
|
|
287
287
|
keepNewest: 3, // Keep only 3 most recent bundles
|
|
288
288
|
});
|
|
289
289
|
```
|
|
@@ -302,7 +302,7 @@ async function onAppReady() {
|
|
|
302
302
|
await performHealthCheck();
|
|
303
303
|
|
|
304
304
|
// Notify that app started successfully
|
|
305
|
-
await NativeUpdate.
|
|
305
|
+
await NativeUpdate.notifyAppReady();
|
|
306
306
|
} catch (error) {
|
|
307
307
|
// Don't call notifyAppReady() - automatic rollback will occur
|
|
308
308
|
console.error('App startup failed:', error);
|
|
@@ -314,14 +314,14 @@ async function onAppReady() {
|
|
|
314
314
|
|
|
315
315
|
```typescript
|
|
316
316
|
// Reset to original bundle
|
|
317
|
-
await NativeUpdate.
|
|
317
|
+
await NativeUpdate.reset();
|
|
318
318
|
|
|
319
319
|
// Or rollback to previous version
|
|
320
|
-
const bundles = await NativeUpdate.
|
|
320
|
+
const bundles = await NativeUpdate.list();
|
|
321
321
|
const previousBundle = bundles[bundles.length - 2];
|
|
322
322
|
if (previousBundle) {
|
|
323
|
-
await NativeUpdate.
|
|
324
|
-
await NativeUpdate.
|
|
323
|
+
await NativeUpdate.set(previousBundle);
|
|
324
|
+
await NativeUpdate.reload();
|
|
325
325
|
}
|
|
326
326
|
```
|
|
327
327
|
|
|
@@ -334,7 +334,7 @@ Use channels to manage different release tracks.
|
|
|
334
334
|
```typescript
|
|
335
335
|
// Set channel based on user preference
|
|
336
336
|
const channel = getUserPreference('updateChannel') || 'production';
|
|
337
|
-
await NativeUpdate.
|
|
337
|
+
await NativeUpdate.setChannel(channel);
|
|
338
338
|
|
|
339
339
|
// Available channels examples:
|
|
340
340
|
// - 'production': Stable releases
|
|
@@ -349,7 +349,7 @@ await NativeUpdate.LiveUpdate.setChannel(channel);
|
|
|
349
349
|
```typescript
|
|
350
350
|
// Enable features based on channel
|
|
351
351
|
async function getFeatureFlags() {
|
|
352
|
-
const bundle = await NativeUpdate.
|
|
352
|
+
const bundle = await NativeUpdate.current();
|
|
353
353
|
|
|
354
354
|
switch (bundle.metadata?.channel) {
|
|
355
355
|
case 'alpha':
|
|
@@ -381,7 +381,7 @@ async function getFeatureFlags() {
|
|
|
381
381
|
// Future API
|
|
382
382
|
// Note: Delta updates are handled automatically by the sync() method
|
|
383
383
|
// when configured on the server. Direct delta download is not available
|
|
384
|
-
const bundle = await NativeUpdate.
|
|
384
|
+
const bundle = await NativeUpdate.download({
|
|
385
385
|
version: latest.version,
|
|
386
386
|
});
|
|
387
387
|
```
|
|
@@ -411,7 +411,7 @@ async function getFeatureFlags() {
|
|
|
411
411
|
|
|
412
412
|
```typescript
|
|
413
413
|
// Monitor bundle count and clean up old versions
|
|
414
|
-
const bundles = await NativeUpdate.
|
|
414
|
+
const bundles = await NativeUpdate.list();
|
|
415
415
|
console.log(`Total bundles: ${bundles.length}`);
|
|
416
416
|
|
|
417
417
|
// Clean up old bundles (keep only recent 5)
|
|
@@ -423,7 +423,7 @@ if (bundles.length > 5) {
|
|
|
423
423
|
|
|
424
424
|
const toDelete = sortedBundles.slice(5);
|
|
425
425
|
for (const bundle of toDelete) {
|
|
426
|
-
await NativeUpdate.
|
|
426
|
+
await NativeUpdate.delete({
|
|
427
427
|
bundleId: bundle.bundleId,
|
|
428
428
|
});
|
|
429
429
|
}
|
|
@@ -436,7 +436,7 @@ if (bundles.length > 5) {
|
|
|
436
436
|
|
|
437
437
|
```typescript
|
|
438
438
|
try {
|
|
439
|
-
await NativeUpdate.
|
|
439
|
+
await NativeUpdate.sync();
|
|
440
440
|
} catch (error) {
|
|
441
441
|
switch (error.code) {
|
|
442
442
|
case 'NETWORK_ERROR':
|
|
@@ -451,7 +451,7 @@ try {
|
|
|
451
451
|
|
|
452
452
|
case 'CHECKSUM_ERROR':
|
|
453
453
|
// Bundle corrupted
|
|
454
|
-
await NativeUpdate.
|
|
454
|
+
await NativeUpdate.delete({
|
|
455
455
|
bundleId: error.bundleId,
|
|
456
456
|
});
|
|
457
457
|
break;
|
|
@@ -483,7 +483,7 @@ class UpdateRetryManager {
|
|
|
483
483
|
|
|
484
484
|
async syncWithRetry() {
|
|
485
485
|
try {
|
|
486
|
-
await NativeUpdate.
|
|
486
|
+
await NativeUpdate.sync();
|
|
487
487
|
this.retryCount = 0; // Reset on success
|
|
488
488
|
} catch (error) {
|
|
489
489
|
if (this.shouldRetry(error)) {
|
|
@@ -535,7 +535,7 @@ const devConfig = {
|
|
|
535
535
|
};
|
|
536
536
|
|
|
537
537
|
// Force update check
|
|
538
|
-
await NativeUpdate.
|
|
538
|
+
await NativeUpdate.sync();
|
|
539
539
|
|
|
540
540
|
// Simulate different scenarios
|
|
541
541
|
await testUpdateScenarios();
|
|
@@ -574,7 +574,7 @@ function shouldReceiveUpdate(userId: string, percentage: number): boolean {
|
|
|
574
574
|
|
|
575
575
|
if (shouldReceiveUpdate(user.id, 10)) {
|
|
576
576
|
// 10% rollout
|
|
577
|
-
await NativeUpdate.
|
|
577
|
+
await NativeUpdate.setChannel('beta');
|
|
578
578
|
}
|
|
579
579
|
```
|
|
580
580
|
|
|
@@ -582,7 +582,7 @@ if (shouldReceiveUpdate(user.id, 10)) {
|
|
|
582
582
|
|
|
583
583
|
```typescript
|
|
584
584
|
// Notify users about updates
|
|
585
|
-
NativeUpdate.
|
|
585
|
+
NativeUpdate.addListener('updateStateChanged', (event) => {
|
|
586
586
|
if (event.status === 'READY') {
|
|
587
587
|
showNotification({
|
|
588
588
|
title: 'Update Ready',
|
|
@@ -332,13 +332,13 @@ await NativeUpdate.configure({
|
|
|
332
332
|
|
|
333
333
|
```typescript
|
|
334
334
|
// Change update channel
|
|
335
|
-
await NativeUpdate.
|
|
335
|
+
await NativeUpdate.setChannel('beta');
|
|
336
336
|
|
|
337
337
|
// Change server URL
|
|
338
|
-
await NativeUpdate.
|
|
338
|
+
await NativeUpdate.setUpdateUrl('https://new-server.com');
|
|
339
339
|
|
|
340
340
|
// Update security settings
|
|
341
|
-
await NativeUpdate.
|
|
341
|
+
await NativeUpdate.updateConfig({
|
|
342
342
|
enforceHttps: true,
|
|
343
343
|
requireSignature: true,
|
|
344
344
|
});
|
|
@@ -141,11 +141,11 @@ To verify the installation:
|
|
|
141
141
|
|
|
142
142
|
```typescript
|
|
143
143
|
// Get current bundle info
|
|
144
|
-
const currentBundle = await NativeUpdate.
|
|
144
|
+
const currentBundle = await NativeUpdate.current();
|
|
145
145
|
console.log('Current bundle:', currentBundle);
|
|
146
146
|
|
|
147
147
|
// Check for updates
|
|
148
|
-
const latest = await NativeUpdate.
|
|
148
|
+
const latest = await NativeUpdate.getLatest();
|
|
149
149
|
console.log('Latest version available:', latest);
|
|
150
150
|
```
|
|
151
151
|
|
|
@@ -72,8 +72,8 @@ async function syncUpdates() {
|
|
|
72
72
|
```typescript
|
|
73
73
|
// Check for updates without downloading
|
|
74
74
|
async function checkForUpdates() {
|
|
75
|
-
const latest = await NativeUpdate.
|
|
76
|
-
const current = await NativeUpdate.
|
|
75
|
+
const latest = await NativeUpdate.getLatest();
|
|
76
|
+
const current = await NativeUpdate.current();
|
|
77
77
|
|
|
78
78
|
if (latest.version !== current.version) {
|
|
79
79
|
console.log(`Update available: ${latest.version}`);
|
|
@@ -86,15 +86,15 @@ async function checkForUpdates() {
|
|
|
86
86
|
async function downloadAndInstallUpdate() {
|
|
87
87
|
try {
|
|
88
88
|
// Download the latest version
|
|
89
|
-
const bundle = await NativeUpdate.
|
|
89
|
+
const bundle = await NativeUpdate.download({
|
|
90
90
|
version: 'latest',
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
// Set it as active
|
|
94
|
-
await NativeUpdate.
|
|
94
|
+
await NativeUpdate.set(bundle);
|
|
95
95
|
|
|
96
96
|
// Reload the app to apply
|
|
97
|
-
await NativeUpdate.
|
|
97
|
+
await NativeUpdate.reload();
|
|
98
98
|
} catch (error) {
|
|
99
99
|
console.error('Update failed:', error);
|
|
100
100
|
}
|
|
@@ -105,7 +105,7 @@ async function downloadAndInstallUpdate() {
|
|
|
105
105
|
|
|
106
106
|
```typescript
|
|
107
107
|
// Add download progress listener
|
|
108
|
-
const progressListener = await NativeUpdate.
|
|
108
|
+
const progressListener = await NativeUpdate.addListener(
|
|
109
109
|
'downloadProgress',
|
|
110
110
|
(progress) => {
|
|
111
111
|
console.log(`Download: ${progress.percent}% complete`);
|
|
@@ -124,14 +124,14 @@ const progressListener = await NativeUpdate.LiveUpdate.addListener(
|
|
|
124
124
|
```typescript
|
|
125
125
|
async function checkAppStoreUpdate() {
|
|
126
126
|
try {
|
|
127
|
-
const updateInfo = await NativeUpdate.
|
|
127
|
+
const updateInfo = await NativeUpdate.getAppUpdateInfo();
|
|
128
128
|
|
|
129
129
|
if (updateInfo.updateAvailable) {
|
|
130
130
|
console.log(`New version available: ${updateInfo.availableVersion}`);
|
|
131
131
|
|
|
132
132
|
if (updateInfo.updatePriority >= 4) {
|
|
133
133
|
// High priority - immediate update
|
|
134
|
-
await NativeUpdate.
|
|
134
|
+
await NativeUpdate.performImmediateUpdate();
|
|
135
135
|
} else {
|
|
136
136
|
// Optional update
|
|
137
137
|
showUpdateDialog(updateInfo);
|
|
@@ -145,7 +145,7 @@ async function checkAppStoreUpdate() {
|
|
|
145
145
|
function showUpdateDialog(updateInfo) {
|
|
146
146
|
// Show your custom update UI
|
|
147
147
|
if (userAcceptsUpdate) {
|
|
148
|
-
NativeUpdate.
|
|
148
|
+
NativeUpdate.openAppStore();
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
```
|
|
@@ -155,10 +155,10 @@ function showUpdateDialog(updateInfo) {
|
|
|
155
155
|
```typescript
|
|
156
156
|
// Start downloading in background
|
|
157
157
|
async function startFlexibleUpdate() {
|
|
158
|
-
await NativeUpdate.
|
|
158
|
+
await NativeUpdate.startFlexibleUpdate();
|
|
159
159
|
|
|
160
160
|
// Listen for download completion
|
|
161
|
-
const listener = await NativeUpdate.
|
|
161
|
+
const listener = await NativeUpdate.addListener(
|
|
162
162
|
'flexibleUpdateStateChanged',
|
|
163
163
|
(state) => {
|
|
164
164
|
if (state.status === 'DOWNLOADED') {
|
|
@@ -171,7 +171,7 @@ async function startFlexibleUpdate() {
|
|
|
171
171
|
|
|
172
172
|
// Complete the update
|
|
173
173
|
async function completeUpdate() {
|
|
174
|
-
await NativeUpdate.
|
|
174
|
+
await NativeUpdate.completeFlexibleUpdate();
|
|
175
175
|
// App will restart with new version
|
|
176
176
|
}
|
|
177
177
|
```
|
|
@@ -184,11 +184,11 @@ async function completeUpdate() {
|
|
|
184
184
|
async function requestReviewIfAppropriate() {
|
|
185
185
|
try {
|
|
186
186
|
// Check if we can request a review
|
|
187
|
-
const canRequest = await NativeUpdate.
|
|
187
|
+
const canRequest = await NativeUpdate.canRequestReview();
|
|
188
188
|
|
|
189
189
|
if (canRequest.allowed) {
|
|
190
190
|
// Request the review
|
|
191
|
-
const result = await NativeUpdate.
|
|
191
|
+
const result = await NativeUpdate.requestReview();
|
|
192
192
|
|
|
193
193
|
if (result.shown) {
|
|
194
194
|
console.log('Review dialog was shown');
|
|
@@ -218,7 +218,7 @@ import { NativeUpdate } from 'native-update';
|
|
|
218
218
|
App.addListener('appStateChange', async ({ isActive }) => {
|
|
219
219
|
if (isActive) {
|
|
220
220
|
// Check for updates when app becomes active
|
|
221
|
-
await NativeUpdate.
|
|
221
|
+
await NativeUpdate.sync({
|
|
222
222
|
installMode: 'ON_NEXT_RESUME',
|
|
223
223
|
});
|
|
224
224
|
}
|
|
@@ -248,7 +248,7 @@ class UpdateManager {
|
|
|
248
248
|
|
|
249
249
|
setupListeners() {
|
|
250
250
|
// Listen for update state changes
|
|
251
|
-
NativeUpdate.
|
|
251
|
+
NativeUpdate.addListener(
|
|
252
252
|
'updateStateChanged',
|
|
253
253
|
(event) => {
|
|
254
254
|
console.log('Update state:', event.status);
|
|
@@ -293,7 +293,7 @@ import { NativeUpdateError } from 'native-update';
|
|
|
293
293
|
|
|
294
294
|
async function safeUpdateCheck() {
|
|
295
295
|
try {
|
|
296
|
-
await NativeUpdate.
|
|
296
|
+
await NativeUpdate.sync();
|
|
297
297
|
} catch (error) {
|
|
298
298
|
if (error instanceof NativeUpdateError) {
|
|
299
299
|
switch (error.code) {
|
|
@@ -324,7 +324,7 @@ async function safeUpdateCheck() {
|
|
|
324
324
|
1. **Use staging channel for testing**:
|
|
325
325
|
|
|
326
326
|
```typescript
|
|
327
|
-
await NativeUpdate.
|
|
327
|
+
await NativeUpdate.setChannel('staging');
|
|
328
328
|
```
|
|
329
329
|
|
|
330
330
|
2. **Enable debug mode for app reviews**:
|
|
@@ -340,7 +340,7 @@ async function safeUpdateCheck() {
|
|
|
340
340
|
3. **Force update check**:
|
|
341
341
|
```typescript
|
|
342
342
|
// Clear cache and check
|
|
343
|
-
await NativeUpdate.
|
|
343
|
+
await NativeUpdate.sync({
|
|
344
344
|
forceCheck: true,
|
|
345
345
|
});
|
|
346
346
|
```
|
|
@@ -361,10 +361,10 @@ Now that you have the basics working:
|
|
|
361
361
|
| Method | Purpose |
|
|
362
362
|
| ------------------------------ | ------------------------------- |
|
|
363
363
|
| `configure()` | Initialize plugin with settings |
|
|
364
|
-
| `
|
|
365
|
-
| `
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
364
|
+
| `sync()` | Check and apply updates |
|
|
365
|
+
| `current()` | Get current bundle info |
|
|
366
|
+
| `getAppUpdateInfo()` | Check app store updates |
|
|
367
|
+
| `requestReview()` | Request user review |
|
|
368
368
|
|
|
369
369
|
### Key Events
|
|
370
370
|
|
|
@@ -123,7 +123,7 @@ try {
|
|
|
123
123
|
node tools/bundle-signer.js sign test-bundle.zip private-key.pem
|
|
124
124
|
|
|
125
125
|
# Verify in app
|
|
126
|
-
const isValid = await NativeUpdate.
|
|
126
|
+
const isValid = await NativeUpdate.validateUpdate({
|
|
127
127
|
bundlePath: 'bundle-path',
|
|
128
128
|
checksum: 'bundle-checksum',
|
|
129
129
|
signature: signature
|
|
@@ -135,7 +135,7 @@ const isValid = await NativeUpdate.LiveUpdate.validateUpdate({
|
|
|
135
135
|
#### Download Performance
|
|
136
136
|
```typescript
|
|
137
137
|
// Monitor download speed
|
|
138
|
-
NativeUpdate.
|
|
138
|
+
NativeUpdate.addListener('downloadProgress', (progress) => {
|
|
139
139
|
console.log(`Speed: ${progress.speed} MB/s`);
|
|
140
140
|
console.log(`Progress: ${progress.percent}%`);
|
|
141
141
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "native-update",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Foundation package for building a comprehensive update system for Capacitor apps. Provides architecture and interfaces but requires backend implementation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/plugin.cjs.js",
|