@capgo/capacitor-updater 4.0.0-alpha.9 → 4.0.0
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/LICENCE +160 -656
- package/README.md +141 -21
- package/android/src/main/java/ee/forgr/capacitor_updater/BundleInfo.java +21 -9
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdater.java +90 -51
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +199 -118
- package/dist/docs.json +390 -19
- package/dist/esm/definitions.d.ts +72 -14
- package/dist/esm/web.d.ts +4 -2
- package/dist/esm/web.js +6 -2
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +6 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +6 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/BundleInfo.swift +22 -11
- package/ios/Plugin/CapacitorUpdater.swift +125 -77
- package/ios/Plugin/CapacitorUpdaterPlugin.m +2 -1
- package/ios/Plugin/CapacitorUpdaterPlugin.swift +140 -122
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# Capacitor updater
|
|
2
|
+
<a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
|
|
3
3
|
Update Ionic Capacitor apps without App/Play Store review (Code-push / hot-code updates).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
5
|
+
You have 3 ways possible :
|
|
6
|
+
- Use [capgo.app](https://capgo.app) a full featured auto update system in 5 min Setup, to manage version, update, revert and see stats.
|
|
7
|
+
- Use your own server update with auto update system
|
|
8
|
+
- Use manual methods to zip, upload, download, from JS to do it when you want.
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
## Community
|
|
12
12
|
Join the [discord](https://discord.gg/VnYRvBfgA6) to get help.
|
|
13
13
|
|
|
14
14
|
## Documentation
|
|
15
|
-
I maintain a more user friendly and complete [documentation](https://
|
|
15
|
+
I maintain a more user friendly and complete [documentation here](https://docs.capgo.app/).
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -24,10 +24,10 @@ npx cap sync
|
|
|
24
24
|
## Auto-update setup
|
|
25
25
|
|
|
26
26
|
Create account in [capgo.app](https://capgo.app) and get your [API key](https://capgo.app/app/apikeys)
|
|
27
|
-
-
|
|
28
|
-
- Add app
|
|
29
|
-
- Upload app `capgo
|
|
30
|
-
-
|
|
27
|
+
- Login to CLI `npx @capgo/cli@latest login API_KEY`
|
|
28
|
+
- Add app with CLI `npx @capgo/cli@latest add`
|
|
29
|
+
- Upload app to channel production `npx @capgo/cli@latest upload -c production`
|
|
30
|
+
- Set channel production public `npx @capgo/cli@latest set -c production -s public`
|
|
31
31
|
- Edit your `capacitor.config.json` like below, set `autoUpdate` to true.
|
|
32
32
|
```json
|
|
33
33
|
// capacitor.config.json
|
|
@@ -52,7 +52,8 @@ This tells Capacitor Updator that the current update bundle has loaded succesful
|
|
|
52
52
|
- Run the app and see app auto update after each backgrounding.
|
|
53
53
|
- Failed updates will automatically roll back to the last successful version.
|
|
54
54
|
|
|
55
|
-
See more
|
|
55
|
+
See more there in the [Auto update](
|
|
56
|
+
https://github.com/Cap-go/capacitor-updater/wiki) documentation.
|
|
56
57
|
|
|
57
58
|
|
|
58
59
|
## Manual setup
|
|
@@ -127,11 +128,15 @@ Capacitor Updator works by unzipping a compiled app bundle to the native device
|
|
|
127
128
|
* [`current()`](#current)
|
|
128
129
|
* [`reload()`](#reload)
|
|
129
130
|
* [`setDelay(...)`](#setdelay)
|
|
131
|
+
* [`cancelDelay()`](#canceldelay)
|
|
130
132
|
* [`getLatest(...)`](#getlatest)
|
|
131
133
|
* [`addListener('download', ...)`](#addlistenerdownload)
|
|
134
|
+
* [`addListener('noNeedUpdate', ...)`](#addlistenernoneedupdate)
|
|
135
|
+
* [`addListener('updateAvailable', ...)`](#addlistenerupdateavailable)
|
|
132
136
|
* [`addListener('downloadComplete', ...)`](#addlistenerdownloadcomplete)
|
|
133
137
|
* [`addListener('majorAvailable', ...)`](#addlistenermajoravailable)
|
|
134
138
|
* [`addListener('updateFailed', ...)`](#addlistenerupdatefailed)
|
|
139
|
+
* [`addListener('downloadFailed', ...)`](#addlistenerdownloadfailed)
|
|
135
140
|
* [`getId()`](#getid)
|
|
136
141
|
* [`getPluginVersion()`](#getpluginversion)
|
|
137
142
|
* [`isAutoUpdateEnabled()`](#isautoupdateenabled)
|
|
@@ -161,14 +166,14 @@ Notify Capacitor Updater that the current bundle is working (a rollback will occ
|
|
|
161
166
|
### download(...)
|
|
162
167
|
|
|
163
168
|
```typescript
|
|
164
|
-
download(options: { url: string; version
|
|
169
|
+
download(options: { url: string; version: string; }) => Promise<BundleInfo>
|
|
165
170
|
```
|
|
166
171
|
|
|
167
172
|
Download a new version from the provided URL, it should be a zip file, with files inside or with a unique id inside with all your files
|
|
168
173
|
|
|
169
|
-
| Param | Type
|
|
170
|
-
| ------------- |
|
|
171
|
-
| **`options`** | <code>{ url: string; version
|
|
174
|
+
| Param | Type |
|
|
175
|
+
| ------------- | ---------------------------------------------- |
|
|
176
|
+
| **`options`** | <code>{ url: string; version: string; }</code> |
|
|
172
177
|
|
|
173
178
|
**Returns:** <code>Promise<<a href="#bundleinfo">BundleInfo</a>></code>
|
|
174
179
|
|
|
@@ -277,14 +282,27 @@ Reload the view
|
|
|
277
282
|
### setDelay(...)
|
|
278
283
|
|
|
279
284
|
```typescript
|
|
280
|
-
setDelay(options: {
|
|
285
|
+
setDelay(options: { kind: DelayUntilNext; value?: string; }) => Promise<void>
|
|
281
286
|
```
|
|
282
287
|
|
|
283
288
|
Set delay to skip updates in the next time the app goes into the background
|
|
284
289
|
|
|
285
|
-
| Param | Type
|
|
286
|
-
| ------------- |
|
|
287
|
-
| **`options`** | <code>{
|
|
290
|
+
| Param | Type |
|
|
291
|
+
| ------------- | ------------------------------------------------------------------------------------ |
|
|
292
|
+
| **`options`** | <code>{ kind: <a href="#delayuntilnext">DelayUntilNext</a>; value?: string; }</code> |
|
|
293
|
+
|
|
294
|
+
**Since:** 4.0.0
|
|
295
|
+
|
|
296
|
+
--------------------
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
### cancelDelay()
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
cancelDelay() => Promise<void>
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Cancel delay to updates as usual
|
|
288
306
|
|
|
289
307
|
**Since:** 4.0.0
|
|
290
308
|
|
|
@@ -330,6 +348,46 @@ Listen for download event in the App, let you know when the download is started,
|
|
|
330
348
|
--------------------
|
|
331
349
|
|
|
332
350
|
|
|
351
|
+
### addListener('noNeedUpdate', ...)
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
addListener(eventName: 'noNeedUpdate', listenerFunc: NoNeedListener) => Promise<PluginListenerHandle> & PluginListenerHandle
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Listen for no need to update event, usefull when you want force check every time the app is launched
|
|
358
|
+
|
|
359
|
+
| Param | Type |
|
|
360
|
+
| ------------------ | --------------------------------------------------------- |
|
|
361
|
+
| **`eventName`** | <code>'noNeedUpdate'</code> |
|
|
362
|
+
| **`listenerFunc`** | <code><a href="#noneedlistener">NoNeedListener</a></code> |
|
|
363
|
+
|
|
364
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>> & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
|
|
365
|
+
|
|
366
|
+
**Since:** 4.0.0
|
|
367
|
+
|
|
368
|
+
--------------------
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
### addListener('updateAvailable', ...)
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
addListener(eventName: 'updateAvailable', listenerFunc: UpdateAvailabledListener) => Promise<PluginListenerHandle> & PluginListenerHandle
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Listen for availbale update event, usefull when you want to force check every time the app is launched
|
|
378
|
+
|
|
379
|
+
| Param | Type |
|
|
380
|
+
| ------------------ | ----------------------------------------------------------------------------- |
|
|
381
|
+
| **`eventName`** | <code>'updateAvailable'</code> |
|
|
382
|
+
| **`listenerFunc`** | <code><a href="#updateavailabledlistener">UpdateAvailabledListener</a></code> |
|
|
383
|
+
|
|
384
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>> & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
|
|
385
|
+
|
|
386
|
+
**Since:** 4.0.0
|
|
387
|
+
|
|
388
|
+
--------------------
|
|
389
|
+
|
|
390
|
+
|
|
333
391
|
### addListener('downloadComplete', ...)
|
|
334
392
|
|
|
335
393
|
```typescript
|
|
@@ -376,7 +434,7 @@ Listen for Major update event in the App, let you know when major update is bloc
|
|
|
376
434
|
addListener(eventName: 'updateFailed', listenerFunc: UpdateFailedListener) => Promise<PluginListenerHandle> & PluginListenerHandle
|
|
377
435
|
```
|
|
378
436
|
|
|
379
|
-
Listen for update event in the App, let you know when update
|
|
437
|
+
Listen for update fail event in the App, let you know when update has fail to install at next app start
|
|
380
438
|
|
|
381
439
|
| Param | Type |
|
|
382
440
|
| ------------------ | --------------------------------------------------------------------- |
|
|
@@ -390,6 +448,26 @@ Listen for update event in the App, let you know when update is ready to install
|
|
|
390
448
|
--------------------
|
|
391
449
|
|
|
392
450
|
|
|
451
|
+
### addListener('downloadFailed', ...)
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
addListener(eventName: 'downloadFailed', listenerFunc: DownloadFailedListener) => Promise<PluginListenerHandle> & PluginListenerHandle
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Listen for download fail event in the App, let you know when download has fail finished
|
|
458
|
+
|
|
459
|
+
| Param | Type |
|
|
460
|
+
| ------------------ | ------------------------------------------------------------------------- |
|
|
461
|
+
| **`eventName`** | <code>'downloadFailed'</code> |
|
|
462
|
+
| **`listenerFunc`** | <code><a href="#downloadfailedlistener">DownloadFailedListener</a></code> |
|
|
463
|
+
|
|
464
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>> & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
|
|
465
|
+
|
|
466
|
+
**Since:** 4.0.0
|
|
467
|
+
|
|
468
|
+
--------------------
|
|
469
|
+
|
|
470
|
+
|
|
393
471
|
### getId()
|
|
394
472
|
|
|
395
473
|
```typescript
|
|
@@ -464,6 +542,7 @@ removeAllListeners() => Promise<void>
|
|
|
464
542
|
| **`id`** | <code>string</code> |
|
|
465
543
|
| **`version`** | <code>string</code> |
|
|
466
544
|
| **`downloaded`** | <code>string</code> |
|
|
545
|
+
| **`checksum`** | <code>string</code> |
|
|
467
546
|
| **`status`** | <code><a href="#bundlestatus">BundleStatus</a></code> |
|
|
468
547
|
|
|
469
548
|
|
|
@@ -493,6 +572,20 @@ removeAllListeners() => Promise<void>
|
|
|
493
572
|
| **`bundle`** | <code><a href="#bundleinfo">BundleInfo</a></code> | | |
|
|
494
573
|
|
|
495
574
|
|
|
575
|
+
#### noNeedEvent
|
|
576
|
+
|
|
577
|
+
| Prop | Type | Description | Since |
|
|
578
|
+
| ------------ | ------------------------------------------------- | ---------------------------------------------- | ----- |
|
|
579
|
+
| **`bundle`** | <code><a href="#bundleinfo">BundleInfo</a></code> | Current status of download, between 0 and 100. | 4.0.0 |
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
#### updateAvailableEvent
|
|
583
|
+
|
|
584
|
+
| Prop | Type | Description | Since |
|
|
585
|
+
| ------------ | ------------------------------------------------- | ---------------------------------------------- | ----- |
|
|
586
|
+
| **`bundle`** | <code><a href="#bundleinfo">BundleInfo</a></code> | Current status of download, between 0 and 100. | 4.0.0 |
|
|
587
|
+
|
|
588
|
+
|
|
496
589
|
#### DownloadCompleteEvent
|
|
497
590
|
|
|
498
591
|
| Prop | Type | Description | Since |
|
|
@@ -514,6 +607,13 @@ removeAllListeners() => Promise<void>
|
|
|
514
607
|
| **`bundle`** | <code><a href="#bundleinfo">BundleInfo</a></code> | Emit when a update failed to install. | 4.0.0 |
|
|
515
608
|
|
|
516
609
|
|
|
610
|
+
#### DownloadFailedEvent
|
|
611
|
+
|
|
612
|
+
| Prop | Type | Description | Since |
|
|
613
|
+
| ------------- | ------------------- | -------------------------- | ----- |
|
|
614
|
+
| **`version`** | <code>string</code> | Emit when a download fail. | 4.0.0 |
|
|
615
|
+
|
|
616
|
+
|
|
517
617
|
### Type Aliases
|
|
518
618
|
|
|
519
619
|
|
|
@@ -522,11 +622,26 @@ removeAllListeners() => Promise<void>
|
|
|
522
622
|
<code>'success' | 'error' | 'pending' | 'downloading'</code>
|
|
523
623
|
|
|
524
624
|
|
|
625
|
+
#### DelayUntilNext
|
|
626
|
+
|
|
627
|
+
<code>'background' | 'kill' | 'nativeVersion' | 'date'</code>
|
|
628
|
+
|
|
629
|
+
|
|
525
630
|
#### DownloadChangeListener
|
|
526
631
|
|
|
527
632
|
<code>(state: <a href="#downloadevent">DownloadEvent</a>): void</code>
|
|
528
633
|
|
|
529
634
|
|
|
635
|
+
#### NoNeedListener
|
|
636
|
+
|
|
637
|
+
<code>(state: <a href="#noneedevent">noNeedEvent</a>): void</code>
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
#### UpdateAvailabledListener
|
|
641
|
+
|
|
642
|
+
<code>(state: <a href="#updateavailableevent">updateAvailableEvent</a>): void</code>
|
|
643
|
+
|
|
644
|
+
|
|
530
645
|
#### DownloadCompleteListener
|
|
531
646
|
|
|
532
647
|
<code>(state: <a href="#downloadcompleteevent">DownloadCompleteEvent</a>): void</code>
|
|
@@ -541,6 +656,11 @@ removeAllListeners() => Promise<void>
|
|
|
541
656
|
|
|
542
657
|
<code>(state: <a href="#updatefailedevent">UpdateFailedEvent</a>): void</code>
|
|
543
658
|
|
|
659
|
+
|
|
660
|
+
#### DownloadFailedListener
|
|
661
|
+
|
|
662
|
+
<code>(state: <a href="#downloadfailedevent">DownloadFailedEvent</a>): void</code>
|
|
663
|
+
|
|
544
664
|
</docgen-api>
|
|
545
665
|
|
|
546
666
|
### Listen to download events
|
|
@@ -21,6 +21,7 @@ public class BundleInfo {
|
|
|
21
21
|
private final String downloaded;
|
|
22
22
|
private final String id;
|
|
23
23
|
private final String version;
|
|
24
|
+
private final String checksum;
|
|
24
25
|
private final BundleStatus status;
|
|
25
26
|
|
|
26
27
|
static {
|
|
@@ -28,17 +29,18 @@ public class BundleInfo {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
public BundleInfo(final BundleInfo source) {
|
|
31
|
-
this(source.id, source.version, source.status, source.downloaded);
|
|
32
|
+
this(source.id, source.version, source.status, source.downloaded, source.checksum);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
public BundleInfo(final String id, final String version, final BundleStatus status, final Date downloaded) {
|
|
35
|
-
this(id, version, status, sdf.format(downloaded));
|
|
35
|
+
public BundleInfo(final String id, final String version, final BundleStatus status, final Date downloaded, final String checksum) {
|
|
36
|
+
this(id, version, status, sdf.format(downloaded), checksum);
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
public BundleInfo(final String id, final String version, final BundleStatus status, final String downloaded) {
|
|
39
|
+
public BundleInfo(final String id, final String version, final BundleStatus status, final String downloaded, final String checksum) {
|
|
39
40
|
this.downloaded = downloaded.trim();
|
|
40
41
|
this.id = id;
|
|
41
42
|
this.version = version;
|
|
43
|
+
this.checksum = checksum;
|
|
42
44
|
this.status = status;
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -60,7 +62,15 @@ public class BundleInfo {
|
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
public BundleInfo setDownloaded(Date downloaded) {
|
|
63
|
-
return new BundleInfo(this.id, this.version, this.status, downloaded);
|
|
65
|
+
return new BundleInfo(this.id, this.version, this.status, downloaded, this.checksum);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public String getChecksum() {
|
|
69
|
+
return this.isBuiltin() ? "" : this.checksum;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public BundleInfo setChecksum(String checksum) {
|
|
73
|
+
return new BundleInfo(this.id, this.version, this.status, this.downloaded, checksum);
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
public String getId() {
|
|
@@ -68,7 +78,7 @@ public class BundleInfo {
|
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
public BundleInfo setId(String id) {
|
|
71
|
-
return new BundleInfo(id, this.version, this.status, this.downloaded);
|
|
81
|
+
return new BundleInfo(id, this.version, this.status, this.downloaded, this.checksum);
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
public String getVersionName() {
|
|
@@ -76,7 +86,7 @@ public class BundleInfo {
|
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
public BundleInfo setVersionName(String version) {
|
|
79
|
-
return new BundleInfo(this.id, version, this.status, this.downloaded);
|
|
89
|
+
return new BundleInfo(this.id, version, this.status, this.downloaded, this.checksum);
|
|
80
90
|
}
|
|
81
91
|
|
|
82
92
|
public BundleStatus getStatus() {
|
|
@@ -84,7 +94,7 @@ public class BundleInfo {
|
|
|
84
94
|
}
|
|
85
95
|
|
|
86
96
|
public BundleInfo setStatus(BundleStatus status) {
|
|
87
|
-
return new BundleInfo(this.id, this.version, status, this.downloaded);
|
|
97
|
+
return new BundleInfo(this.id, this.version, status, this.downloaded, this.checksum);
|
|
88
98
|
}
|
|
89
99
|
|
|
90
100
|
public static BundleInfo fromJSON(final JSObject json) throws JSONException {
|
|
@@ -97,7 +107,8 @@ public class BundleInfo {
|
|
|
97
107
|
json.has("id") ? json.getString("id") : "",
|
|
98
108
|
json.has("version") ? json.getString("version") : BundleInfo.VERSION_UNKNOWN,
|
|
99
109
|
json.has("status") ? BundleStatus.fromString(json.getString("status")) : BundleStatus.PENDING,
|
|
100
|
-
json.has("downloaded") ? json.getString("downloaded") : ""
|
|
110
|
+
json.has("downloaded") ? json.getString("downloaded") : "",
|
|
111
|
+
json.has("checksum") ? json.getString("checksum") : ""
|
|
101
112
|
);
|
|
102
113
|
}
|
|
103
114
|
|
|
@@ -106,6 +117,7 @@ public class BundleInfo {
|
|
|
106
117
|
result.put("id", this.getId());
|
|
107
118
|
result.put("version", this.getVersionName());
|
|
108
119
|
result.put("downloaded", this.getDownloaded());
|
|
120
|
+
result.put("checksum", this.getChecksum());
|
|
109
121
|
result.put("status", this.getStatus());
|
|
110
122
|
return result;
|
|
111
123
|
}
|
|
@@ -28,6 +28,7 @@ import java.security.SecureRandom;
|
|
|
28
28
|
import java.util.ArrayList;
|
|
29
29
|
import java.util.Date;
|
|
30
30
|
import java.util.List;
|
|
31
|
+
import java.util.zip.CRC32;
|
|
31
32
|
import java.util.zip.ZipEntry;
|
|
32
33
|
import java.util.zip.ZipInputStream;
|
|
33
34
|
|
|
@@ -46,7 +47,7 @@ public class CapacitorUpdater {
|
|
|
46
47
|
private static final String bundleDirectory = "versions";
|
|
47
48
|
|
|
48
49
|
public static final String TAG = "Capacitor-updater";
|
|
49
|
-
public static final String pluginVersion = "4.0.0
|
|
50
|
+
public static final String pluginVersion = "4.0.0";
|
|
50
51
|
|
|
51
52
|
public SharedPreferences.Editor editor;
|
|
52
53
|
public SharedPreferences prefs;
|
|
@@ -212,13 +213,25 @@ public class CapacitorUpdater {
|
|
|
212
213
|
this.editor.commit();
|
|
213
214
|
}
|
|
214
215
|
|
|
216
|
+
private String getChecksum(File file) throws IOException {
|
|
217
|
+
byte[] bytes = new byte[(int) file.length()];
|
|
218
|
+
try(FileInputStream fis = new FileInputStream(file)){
|
|
219
|
+
fis.read(bytes);
|
|
220
|
+
}
|
|
221
|
+
CRC32 crc = new CRC32();
|
|
222
|
+
crc.update(bytes);
|
|
223
|
+
String enc = String.format("%08X", crc.getValue());
|
|
224
|
+
return enc.toLowerCase();
|
|
225
|
+
}
|
|
226
|
+
|
|
215
227
|
public BundleInfo download(final String url, final String version) throws IOException {
|
|
216
228
|
final String id = this.randomString(10);
|
|
217
|
-
this.saveBundleInfo(id, new BundleInfo(id, version, BundleStatus.DOWNLOADING, new Date(System.currentTimeMillis())));
|
|
229
|
+
this.saveBundleInfo(id, new BundleInfo(id, version, BundleStatus.DOWNLOADING, new Date(System.currentTimeMillis()), ""));
|
|
218
230
|
this.notifyDownload(id, 0);
|
|
219
231
|
final String idName = bundleDirectory + "/" + id;
|
|
220
232
|
this.notifyDownload(id, 5);
|
|
221
233
|
final File downloaded = this.downloadFile(id, url, this.randomString(10));
|
|
234
|
+
final String checksum = this.getChecksum(downloaded);
|
|
222
235
|
this.notifyDownload(id, 71);
|
|
223
236
|
final File unzipped = this.unzip(id, downloaded, this.randomString(10));
|
|
224
237
|
downloaded.delete();
|
|
@@ -226,7 +239,7 @@ public class CapacitorUpdater {
|
|
|
226
239
|
this.flattenAssets(unzipped, idName);
|
|
227
240
|
this.notifyDownload(id, 100);
|
|
228
241
|
this.saveBundleInfo(id, null);
|
|
229
|
-
BundleInfo info = new BundleInfo(id, version, BundleStatus.PENDING, new Date(System.currentTimeMillis()));
|
|
242
|
+
BundleInfo info = new BundleInfo(id, version, BundleStatus.PENDING, new Date(System.currentTimeMillis()), checksum);
|
|
230
243
|
this.saveBundleInfo(id, info);
|
|
231
244
|
return info;
|
|
232
245
|
}
|
|
@@ -246,28 +259,38 @@ public class CapacitorUpdater {
|
|
|
246
259
|
return res;
|
|
247
260
|
}
|
|
248
261
|
|
|
249
|
-
public Boolean delete(final String id) throws IOException {
|
|
262
|
+
public Boolean delete(final String id, final Boolean removeInfo) throws IOException {
|
|
250
263
|
final BundleInfo deleted = this.getBundleInfo(id);
|
|
264
|
+
if (deleted.isBuiltin() || this.getCurrentBundleId() == id) {
|
|
265
|
+
Log.e(TAG, "Cannot delete " + id);
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
251
268
|
final File bundle = new File(this.documentsDir, bundleDirectory + "/" + id);
|
|
252
269
|
if (bundle.exists()) {
|
|
253
270
|
this.deleteDirectory(bundle);
|
|
254
|
-
|
|
271
|
+
if (removeInfo) {
|
|
272
|
+
this.removeBundleInfo(id);
|
|
273
|
+
}
|
|
255
274
|
return true;
|
|
256
275
|
}
|
|
257
276
|
Log.e(TAG, "Directory not removed: " + bundle.getPath());
|
|
258
|
-
this.sendStats("delete", deleted);
|
|
277
|
+
this.sendStats("delete", deleted.getVersionName());
|
|
259
278
|
return false;
|
|
260
279
|
}
|
|
261
280
|
|
|
281
|
+
public Boolean delete(final String id) throws IOException {
|
|
282
|
+
return this.delete(id, true);
|
|
283
|
+
}
|
|
284
|
+
|
|
262
285
|
private File getBundleDirectory(final String id) {
|
|
263
286
|
return new File(this.documentsDir, bundleDirectory + "/" + id);
|
|
264
287
|
}
|
|
265
288
|
|
|
266
|
-
private boolean bundleExists(final
|
|
289
|
+
private boolean bundleExists(final String id) {
|
|
290
|
+
final File bundle = this.getBundleDirectory(id);
|
|
267
291
|
if(bundle == null || !bundle.exists()) {
|
|
268
292
|
return false;
|
|
269
293
|
}
|
|
270
|
-
|
|
271
294
|
return new File(bundle.getPath(), "/index.html").exists();
|
|
272
295
|
}
|
|
273
296
|
|
|
@@ -276,40 +299,56 @@ public class CapacitorUpdater {
|
|
|
276
299
|
}
|
|
277
300
|
|
|
278
301
|
public Boolean set(final String id) {
|
|
279
|
-
|
|
280
|
-
|
|
302
|
+
final BundleInfo newBundle = this.getBundleInfo(id);
|
|
303
|
+
if(newBundle.isBuiltin()) {
|
|
304
|
+
this.reset();
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
281
307
|
final File bundle = this.getBundleDirectory(id);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (this.bundleExists(bundle)) {
|
|
308
|
+
Log.i(TAG, "Setting next active bundle: " + id);
|
|
309
|
+
if (this.bundleExists(id)) {
|
|
285
310
|
this.setCurrentBundle(bundle);
|
|
286
311
|
this.setBundleStatus(id, BundleStatus.PENDING);
|
|
287
|
-
this.sendStats("set",
|
|
312
|
+
this.sendStats("set", newBundle.getVersionName());
|
|
288
313
|
return true;
|
|
289
314
|
}
|
|
290
|
-
this.sendStats("set_fail",
|
|
315
|
+
this.sendStats("set_fail", newBundle.getVersionName());
|
|
291
316
|
return false;
|
|
292
317
|
}
|
|
293
318
|
|
|
294
|
-
public void commit(final BundleInfo bundle) {
|
|
295
|
-
this.setBundleStatus(bundle.getId(), BundleStatus.SUCCESS);
|
|
296
|
-
this.setFallbackVersion(bundle);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
319
|
public void reset() {
|
|
300
320
|
this.reset(false);
|
|
301
321
|
}
|
|
302
322
|
|
|
303
|
-
public void
|
|
323
|
+
public void setSuccess(final BundleInfo bundle, Boolean autoDeletePrevious) {
|
|
324
|
+
this.setBundleStatus(bundle.getId(), BundleStatus.SUCCESS);
|
|
325
|
+
final BundleInfo fallback = this.getFallbackBundle();
|
|
326
|
+
Log.d(CapacitorUpdater.TAG, "Fallback bundle is: " + fallback);
|
|
327
|
+
Log.i(CapacitorUpdater.TAG, "Version successfully loaded: " + bundle.getVersionName());
|
|
328
|
+
if(autoDeletePrevious && !fallback.isBuiltin()) {
|
|
329
|
+
try {
|
|
330
|
+
final Boolean res = this.delete(fallback.getId());
|
|
331
|
+
if (res) {
|
|
332
|
+
Log.i(CapacitorUpdater.TAG, "Deleted previous bundle: " + fallback.getVersionName());
|
|
333
|
+
}
|
|
334
|
+
} catch (final IOException e) {
|
|
335
|
+
Log.e(CapacitorUpdater.TAG, "Failed to delete previous bundle: " + fallback.getVersionName(), e);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
this.setFallbackBundle(bundle);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
public void setError(final BundleInfo bundle) {
|
|
304
342
|
this.setBundleStatus(bundle.getId(), BundleStatus.ERROR);
|
|
305
343
|
}
|
|
306
344
|
|
|
307
345
|
public void reset(final boolean internal) {
|
|
346
|
+
Log.d(CapacitorUpdater.TAG, "reset: " + internal);
|
|
308
347
|
this.setCurrentBundle(new File("public"));
|
|
309
|
-
this.
|
|
310
|
-
this.
|
|
348
|
+
this.setFallbackBundle(null);
|
|
349
|
+
this.setNextBundle(null);
|
|
311
350
|
if(!internal) {
|
|
312
|
-
this.sendStats("reset", this.getCurrentBundle());
|
|
351
|
+
this.sendStats("reset", this.getCurrentBundle().getVersionName());
|
|
313
352
|
}
|
|
314
353
|
}
|
|
315
354
|
|
|
@@ -332,6 +371,7 @@ public class CapacitorUpdater {
|
|
|
332
371
|
json.put("version_name", version);
|
|
333
372
|
json.put("plugin_version", pluginVersion);
|
|
334
373
|
|
|
374
|
+
Log.e(CapacitorUpdater.TAG, "Auto-update parameters: " + json.toString());
|
|
335
375
|
// Building a request
|
|
336
376
|
JsonObjectRequest request = new JsonObjectRequest(
|
|
337
377
|
Request.Method.POST,
|
|
@@ -356,7 +396,7 @@ public class CapacitorUpdater {
|
|
|
356
396
|
}
|
|
357
397
|
}
|
|
358
398
|
|
|
359
|
-
public void sendStats(final String action, final
|
|
399
|
+
public void sendStats(final String action, final String versionName) {
|
|
360
400
|
String statsUrl = this.statsUrl;
|
|
361
401
|
if (statsUrl == null || "".equals(statsUrl) || statsUrl.length() == 0) { return; }
|
|
362
402
|
try {
|
|
@@ -367,7 +407,7 @@ public class CapacitorUpdater {
|
|
|
367
407
|
json.put("version_build", this.versionBuild);
|
|
368
408
|
json.put("version_code", this.versionCode);
|
|
369
409
|
json.put("version_os", this.versionOs);
|
|
370
|
-
json.put("version_name",
|
|
410
|
+
json.put("version_name", versionName);
|
|
371
411
|
json.put("plugin_version", pluginVersion);
|
|
372
412
|
json.put("action", action);
|
|
373
413
|
|
|
@@ -379,13 +419,13 @@ public class CapacitorUpdater {
|
|
|
379
419
|
new Response.Listener<JSONObject>() {
|
|
380
420
|
@Override
|
|
381
421
|
public void onResponse(JSONObject response) {
|
|
382
|
-
Log.i(TAG, "Stats send for \"" + action + "\", version " +
|
|
422
|
+
Log.i(TAG, "Stats send for \"" + action + "\", version " + versionName);
|
|
383
423
|
}
|
|
384
424
|
},
|
|
385
425
|
new Response.ErrorListener(){
|
|
386
426
|
@Override
|
|
387
427
|
public void onErrorResponse(VolleyError error) {
|
|
388
|
-
Log.i(TAG, "Stats send for \"" + action + "\", version " +
|
|
428
|
+
Log.i(TAG, "Stats send for \"" + action + "\", version " + versionName);
|
|
389
429
|
}
|
|
390
430
|
});
|
|
391
431
|
this.requestQueue.add(request);
|
|
@@ -395,25 +435,28 @@ public class CapacitorUpdater {
|
|
|
395
435
|
}
|
|
396
436
|
}
|
|
397
437
|
|
|
398
|
-
public BundleInfo getBundleInfo(String id) {
|
|
399
|
-
|
|
400
|
-
|
|
438
|
+
public BundleInfo getBundleInfo(final String id) {
|
|
439
|
+
String trueId = BundleInfo.VERSION_UNKNOWN;
|
|
440
|
+
if(id != null) {
|
|
441
|
+
trueId = id;
|
|
401
442
|
}
|
|
402
|
-
Log.d(TAG, "Getting info for bundle [" +
|
|
443
|
+
Log.d(TAG, "Getting info for bundle [" + trueId + "]");
|
|
403
444
|
BundleInfo result;
|
|
404
|
-
if(BundleInfo.ID_BUILTIN.equals(
|
|
405
|
-
result = new BundleInfo(
|
|
445
|
+
if(BundleInfo.ID_BUILTIN.equals(trueId)) {
|
|
446
|
+
result = new BundleInfo(trueId, (String) null, BundleStatus.SUCCESS, "", "");
|
|
447
|
+
} else if(BundleInfo.VERSION_UNKNOWN.equals(trueId)) {
|
|
448
|
+
result = new BundleInfo(trueId, (String) null, BundleStatus.ERROR, "", "");
|
|
406
449
|
} else {
|
|
407
450
|
try {
|
|
408
|
-
String stored = this.prefs.getString(
|
|
451
|
+
String stored = this.prefs.getString(trueId + INFO_SUFFIX, "");
|
|
409
452
|
result = BundleInfo.fromJSON(stored);
|
|
410
453
|
} catch (JSONException e) {
|
|
411
|
-
Log.e(TAG, "Failed to parse info for bundle [" +
|
|
412
|
-
result = new BundleInfo(
|
|
454
|
+
Log.e(TAG, "Failed to parse info for bundle [" + trueId + "] ", e);
|
|
455
|
+
result = new BundleInfo(trueId, (String) null, BundleStatus.PENDING, "", "");
|
|
413
456
|
}
|
|
414
457
|
}
|
|
415
458
|
|
|
416
|
-
Log.d(TAG, "Returning info [" +
|
|
459
|
+
Log.d(TAG, "Returning info [" + trueId + "] " + result);
|
|
417
460
|
return result;
|
|
418
461
|
}
|
|
419
462
|
|
|
@@ -489,37 +532,33 @@ public class CapacitorUpdater {
|
|
|
489
532
|
return this.getCurrentBundlePath().equals("public");
|
|
490
533
|
}
|
|
491
534
|
|
|
492
|
-
public BundleInfo
|
|
535
|
+
public BundleInfo getFallbackBundle() {
|
|
493
536
|
final String id = this.prefs.getString(FALLBACK_VERSION, BundleInfo.ID_BUILTIN);
|
|
494
537
|
return this.getBundleInfo(id);
|
|
495
538
|
}
|
|
496
539
|
|
|
497
|
-
private void
|
|
540
|
+
private void setFallbackBundle(final BundleInfo fallback) {
|
|
498
541
|
this.editor.putString(FALLBACK_VERSION,
|
|
499
542
|
fallback == null
|
|
500
543
|
? BundleInfo.ID_BUILTIN
|
|
501
544
|
: fallback.getId()
|
|
502
545
|
);
|
|
546
|
+
this.editor.commit();
|
|
503
547
|
}
|
|
504
548
|
|
|
505
|
-
public BundleInfo
|
|
506
|
-
final String id = this.prefs.getString(NEXT_VERSION,
|
|
507
|
-
|
|
508
|
-
return this.getBundleInfo(id);
|
|
509
|
-
} else {
|
|
510
|
-
return null;
|
|
511
|
-
}
|
|
549
|
+
public BundleInfo getNextBundle() {
|
|
550
|
+
final String id = this.prefs.getString(NEXT_VERSION, null);
|
|
551
|
+
return this.getBundleInfo(id);
|
|
512
552
|
}
|
|
513
553
|
|
|
514
|
-
public boolean
|
|
554
|
+
public boolean setNextBundle(final String next) {
|
|
515
555
|
if (next == null) {
|
|
516
556
|
this.editor.remove(NEXT_VERSION);
|
|
517
557
|
} else {
|
|
518
|
-
final
|
|
519
|
-
if (!this.bundleExists(
|
|
558
|
+
final BundleInfo newBundle = this.getBundleInfo(next);
|
|
559
|
+
if (!newBundle.isBuiltin() && !this.bundleExists(next)) {
|
|
520
560
|
return false;
|
|
521
561
|
}
|
|
522
|
-
|
|
523
562
|
this.editor.putString(NEXT_VERSION, next);
|
|
524
563
|
this.setBundleStatus(next, BundleStatus.PENDING);
|
|
525
564
|
}
|