cordova-plugin-hot-updates 2.2.2 → 2.3.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/README.md +191 -27
- package/package.json +12 -7
- package/plugin.xml +27 -6
- package/src/android/HotUpdates.java +843 -0
- package/src/android/HotUpdatesConstants.java +98 -0
- package/src/android/HotUpdatesHelpers.java +326 -0
- package/src/ios/HotUpdates.h +8 -6
- package/src/ios/HotUpdates.m +63 -2
- package/src/ios/HotUpdatesConstants.h +1 -0
- package/src/ios/HotUpdatesConstants.m +1 -0
package/README.md
CHANGED
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
# Cordova Hot Updates Plugin v2.
|
|
1
|
+
# Cordova Hot Updates Plugin v2.3.0
|
|
2
2
|
|
|
3
|
-
Frontend-controlled manual hot updates for Cordova iOS applications using WebView Reload approach.
|
|
4
|
-
|
|
5
|
-
## Changelog
|
|
6
|
-
|
|
7
|
-
### v2.2.2 (2024-11-28)
|
|
8
|
-
- **Fixed**: Failed download no longer corrupts previously downloaded update
|
|
9
|
-
- **Fixed**: Infinite loop when pending update installation fails (flags now cleared)
|
|
10
|
-
- **Fixed**: UserDefaults now saved only after successful download (not before)
|
|
11
|
-
- **Improved**: ZIP file validation with magic bytes check (PK\x03\x04) before extraction
|
|
12
|
-
- **Improved**: Cleaner logs without duplicates and full paths
|
|
13
|
-
- **Improved**: All errors now have consistent format with `ERROR:` prefix
|
|
14
|
-
- **Removed**: Redundant initialization code
|
|
3
|
+
Frontend-controlled manual hot updates for Cordova **iOS and Android** applications using WebView Reload approach.
|
|
15
4
|
|
|
16
5
|
[](https://badge.fury.io/js/cordova-plugin-hot-updates)
|
|
17
6
|
[](#license)
|
|
7
|
+
[](#platform-support)
|
|
8
|
+
|
|
9
|
+
This plugin enables **manual, JavaScript-controlled** web content updates for your Cordova applications without requiring App Store/Google Play approval. Your frontend code decides when to check, download, and install updates.
|
|
10
|
+
|
|
11
|
+
## Platform Support
|
|
12
|
+
|
|
13
|
+
| Platform | Version | Status | Notes |
|
|
14
|
+
|----------|---------|--------|-------|
|
|
15
|
+
| iOS | 2.1.2+ | Stable | Requires CocoaPods for SSZipArchive |
|
|
16
|
+
| Android | 2.3.0+ | Stable | Built-in ZIP support, no external dependencies |
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
Both platforms provide 100% API compatibility. The same JavaScript code works on both iOS and Android.
|
|
20
19
|
|
|
21
20
|
## Features
|
|
22
21
|
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
22
|
+
- **Cross-Platform** - Full support for iOS and Android with 100% API compatibility
|
|
23
|
+
- **Frontend Control** - JavaScript decides when to update (no automatic background checking)
|
|
24
|
+
- **Two-Step Updates** - Separate download and install methods for better UX control
|
|
25
|
+
- **Auto-Install on Launch** - If user ignores update prompt, it installs on next app launch
|
|
26
|
+
- **Canary System** - Automatic rollback if update fails to load (20-second timeout)
|
|
27
|
+
- **IgnoreList** - Tracks problematic versions (information only, does not block installation)
|
|
28
|
+
- **Version History** - Tracks successful versions for progressive data migrations
|
|
29
|
+
- **Instant Effect** - WebView Reload approach, no app restart required
|
|
30
|
+
- **Cache Management** - iOS clears WKWebView cache; Android uses LOAD_NO_CACHE mode
|
|
31
|
+
- **Security** - ZIP magic bytes validation on both platforms
|
|
30
32
|
|
|
31
33
|
## Installation
|
|
32
34
|
|
|
@@ -34,9 +36,12 @@ This plugin enables **manual, JavaScript-controlled** web content updates for yo
|
|
|
34
36
|
# Install from npm
|
|
35
37
|
cordova plugin add cordova-plugin-hot-updates
|
|
36
38
|
|
|
37
|
-
# Install CocoaPods dependencies (required)
|
|
39
|
+
# For iOS: Install CocoaPods dependencies (required)
|
|
38
40
|
cd platforms/ios
|
|
39
41
|
pod install
|
|
42
|
+
cd ../..
|
|
43
|
+
|
|
44
|
+
# For Android: No additional dependencies needed!
|
|
40
45
|
```
|
|
41
46
|
|
|
42
47
|
Or install from local directory:
|
|
@@ -52,11 +57,25 @@ cordova plugin add https://github.com/vladimirDarksy/Cordova_hot_update.git
|
|
|
52
57
|
```
|
|
53
58
|
|
|
54
59
|
**Requirements:**
|
|
60
|
+
|
|
61
|
+
**iOS:**
|
|
55
62
|
- Cordova >= 7.0.0
|
|
56
63
|
- cordova-ios >= 4.4.0
|
|
57
|
-
- iOS >=
|
|
64
|
+
- iOS >= 12.0
|
|
58
65
|
- CocoaPods (for SSZipArchive dependency)
|
|
59
66
|
|
|
67
|
+
**Android:**
|
|
68
|
+
- Cordova >= 7.0.0
|
|
69
|
+
- cordova-android >= 9.0.0
|
|
70
|
+
- Android >= 7.0 (API 24)
|
|
71
|
+
- No external dependencies (uses built-in `java.util.zip`)
|
|
72
|
+
|
|
73
|
+
**Automatic Configuration:**
|
|
74
|
+
|
|
75
|
+
The plugin automatically configures required settings during installation:
|
|
76
|
+
- iOS: NSAppTransportSecurity for HTTP connections
|
|
77
|
+
- Android: file scheme, AndroidInsecureFileModeEnabled, LoadUrlTimeoutValue
|
|
78
|
+
|
|
60
79
|
## Quick Start
|
|
61
80
|
|
|
62
81
|
### 1. Minimal Integration
|
|
@@ -279,6 +298,58 @@ window.hotUpdate.getIgnoreList(function(result) {
|
|
|
279
298
|
|
|
280
299
|
---
|
|
281
300
|
|
|
301
|
+
### window.hotUpdate.getVersionHistory(callback)
|
|
302
|
+
|
|
303
|
+
Returns list of all successfully installed versions (excluding rolled back ones).
|
|
304
|
+
|
|
305
|
+
**New in v2.2.3** - Enables progressive data migrations.
|
|
306
|
+
|
|
307
|
+
When internal data structure changes, you may need to run migrations. This method returns the version history so your app can determine which migrations to run.
|
|
308
|
+
|
|
309
|
+
**Key behaviors:**
|
|
310
|
+
- **Automatically initialized** with `appBundleVersion` on first launch
|
|
311
|
+
- **Added to history** when update is successfully installed
|
|
312
|
+
- **Removed from history** when version is rolled back (failed canary)
|
|
313
|
+
- **Excludes ignoreList** - only contains successful versions
|
|
314
|
+
|
|
315
|
+
**Parameters:**
|
|
316
|
+
- `callback` (Function) - `callback(result)`
|
|
317
|
+
- `result`: `{versions: string[]}` - Array of successful version strings
|
|
318
|
+
|
|
319
|
+
**Example:**
|
|
320
|
+
```javascript
|
|
321
|
+
window.hotUpdate.getVersionHistory(function(result) {
|
|
322
|
+
console.log('Version history:', result.versions);
|
|
323
|
+
// Example: ["2.7.7", "2.7.8", "2.7.9"]
|
|
324
|
+
|
|
325
|
+
// Run migrations based on version progression
|
|
326
|
+
result.versions.forEach((version, index) => {
|
|
327
|
+
if (index > 0) {
|
|
328
|
+
const from = result.versions[index - 1];
|
|
329
|
+
const to = version;
|
|
330
|
+
runMigration(from, to);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Use Case:**
|
|
337
|
+
```javascript
|
|
338
|
+
// Check for missed critical versions
|
|
339
|
+
window.hotUpdate.getVersionHistory(function(result) {
|
|
340
|
+
const criticalVersions = ['2.8.0', '3.0.0']; // Versions with important migrations
|
|
341
|
+
const missed = criticalVersions.filter(v => !result.versions.includes(v));
|
|
342
|
+
|
|
343
|
+
if (missed.length > 0) {
|
|
344
|
+
console.warn('User skipped critical versions:', missed);
|
|
345
|
+
// Run all missed critical migrations
|
|
346
|
+
missed.forEach(v => runCriticalMigration(v));
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
282
353
|
### window.hotUpdate.getVersionInfo(callback)
|
|
283
354
|
|
|
284
355
|
Returns version information (debug method).
|
|
@@ -384,8 +455,18 @@ document.addEventListener('deviceready', function() {
|
|
|
384
455
|
|
|
385
456
|
### Storage Structure
|
|
386
457
|
|
|
458
|
+
**iOS:**
|
|
387
459
|
```
|
|
388
|
-
Documents/
|
|
460
|
+
~/Library/Application Support/[Bundle ID]/Documents/
|
|
461
|
+
├── www/ // Active version
|
|
462
|
+
├── www_previous/ // Previous version (rollback)
|
|
463
|
+
├── pending_update/ // Next launch auto-install
|
|
464
|
+
└── temp_downloaded_update/ // Immediate install
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Android:**
|
|
468
|
+
```
|
|
469
|
+
/data/data/[package.name]/files/
|
|
389
470
|
├── www/ // Active version
|
|
390
471
|
├── www_previous/ // Previous version (rollback)
|
|
391
472
|
├── pending_update/ // Next launch auto-install
|
|
@@ -394,7 +475,7 @@ Documents/
|
|
|
394
475
|
|
|
395
476
|
### Version Management
|
|
396
477
|
|
|
397
|
-
- **appBundleVersion** - Native app version
|
|
478
|
+
- **appBundleVersion** - Native app version (Info.plist / build.gradle)
|
|
398
479
|
- **installedVersion** - Current hot update version
|
|
399
480
|
- **previousVersion** - Last working version (rollback)
|
|
400
481
|
|
|
@@ -405,12 +486,13 @@ Your server should provide:
|
|
|
405
486
|
**Check API:**
|
|
406
487
|
```
|
|
407
488
|
GET https://your-server.com/api/check-update?version=1.0.0&platform=ios
|
|
489
|
+
GET https://your-server.com/api/check-update?version=1.0.0&platform=android
|
|
408
490
|
|
|
409
491
|
Response:
|
|
410
492
|
{
|
|
411
493
|
"hasUpdate": true,
|
|
412
494
|
"version": "2.0.0",
|
|
413
|
-
"downloadUrl": "https://your-server.com/updates/2.0.0.zip",
|
|
495
|
+
"downloadUrl": "https://your-server.com/updates/ios/2.0.0.zip",
|
|
414
496
|
"minAppVersion": "2.7.0",
|
|
415
497
|
"releaseNotes": "Bug fixes"
|
|
416
498
|
}
|
|
@@ -475,7 +557,9 @@ window.hotUpdate.canary(version);
|
|
|
475
557
|
|
|
476
558
|
- Check ZIP structure (must have `www/` folder)
|
|
477
559
|
- Check URL accessibility
|
|
478
|
-
- Check
|
|
560
|
+
- Check logs:
|
|
561
|
+
- iOS: Xcode console `[HotUpdates] ...`
|
|
562
|
+
- Android: `adb logcat -s HotUpdates:*`
|
|
479
563
|
|
|
480
564
|
### Automatic rollback
|
|
481
565
|
|
|
@@ -499,6 +583,86 @@ document.addEventListener('deviceready', function() {
|
|
|
499
583
|
}, false);
|
|
500
584
|
```
|
|
501
585
|
|
|
586
|
+
## Platform-Specific Notes
|
|
587
|
+
|
|
588
|
+
### iOS
|
|
589
|
+
|
|
590
|
+
**Technologies:**
|
|
591
|
+
- `NSUserDefaults` for metadata storage
|
|
592
|
+
- `NSTimer` for canary timer (20 seconds)
|
|
593
|
+
- `SSZipArchive` (CocoaPods) for ZIP extraction
|
|
594
|
+
- `WKWebView` with `loadFileURL()`
|
|
595
|
+
|
|
596
|
+
**Specifics:**
|
|
597
|
+
- Always loads from `file://` scheme
|
|
598
|
+
- ZIP magic bytes validation
|
|
599
|
+
- Cache clearing: disk, memory, Service Worker
|
|
600
|
+
|
|
601
|
+
### Android
|
|
602
|
+
|
|
603
|
+
**Technologies:**
|
|
604
|
+
- `SharedPreferences` for metadata storage
|
|
605
|
+
- `Handler + Runnable` for canary timer (20 seconds)
|
|
606
|
+
- `java.util.zip` (built-in) for ZIP extraction
|
|
607
|
+
- `CordovaWebView` with `loadUrlIntoView()`
|
|
608
|
+
|
|
609
|
+
**Specifics:**
|
|
610
|
+
- Starts from `https://localhost/`, switches to `file://` after update
|
|
611
|
+
- ZIP magic bytes validation
|
|
612
|
+
- Cache management: `LOAD_NO_CACHE` mode
|
|
613
|
+
- WebView file access automatically configured
|
|
614
|
+
|
|
615
|
+
**Code Structure:**
|
|
616
|
+
- `HotUpdates.java` - Main plugin class (700 lines)
|
|
617
|
+
- `HotUpdatesHelpers.java` - Utility methods (350 lines)
|
|
618
|
+
- `HotUpdatesConstants.java` - Constants (100 lines)
|
|
619
|
+
|
|
620
|
+
## Testing
|
|
621
|
+
|
|
622
|
+
### iOS Testing (Safari Web Inspector)
|
|
623
|
+
|
|
624
|
+
```bash
|
|
625
|
+
# On device: Settings → Safari → Advanced → Web Inspector (ON)
|
|
626
|
+
# On Mac: Safari → Develop → [Device Name] → [App Name]
|
|
627
|
+
|
|
628
|
+
# In console:
|
|
629
|
+
hotUpdate.getVersionInfo(console.log)
|
|
630
|
+
hotUpdate.canary('1.0.0', console.log)
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
### Android Testing (Chrome DevTools)
|
|
634
|
+
|
|
635
|
+
```bash
|
|
636
|
+
# 1. Connect device/emulator
|
|
637
|
+
adb devices
|
|
638
|
+
|
|
639
|
+
# 2. Open Chrome: chrome://inspect
|
|
640
|
+
|
|
641
|
+
# 3. Find WebView and click "inspect"
|
|
642
|
+
|
|
643
|
+
# 4. In console:
|
|
644
|
+
hotUpdate.getVersionInfo(console.log)
|
|
645
|
+
hotUpdate.canary('1.0.0', console.log)
|
|
646
|
+
|
|
647
|
+
# 5. View logs:
|
|
648
|
+
adb logcat -s HotUpdates:* -v time
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
## What's New in 2.3.0
|
|
652
|
+
|
|
653
|
+
### Android Support
|
|
654
|
+
|
|
655
|
+
Version 2.3.0 adds full Android platform support with the following features:
|
|
656
|
+
|
|
657
|
+
- Complete Android implementation with 100% iOS API compatibility
|
|
658
|
+
- Same JavaScript interface works on both platforms
|
|
659
|
+
- No external dependencies (uses built-in java.util.zip)
|
|
660
|
+
- Automatic configuration of file scheme and preferences
|
|
661
|
+
- ZIP magic bytes validation for security
|
|
662
|
+
- WebView cache management (LOAD_NO_CACHE mode)
|
|
663
|
+
|
|
664
|
+
For complete version history, see [CHANGELOG.md](CHANGELOG.md).
|
|
665
|
+
|
|
502
666
|
## License
|
|
503
667
|
|
|
504
668
|
Custom Non-Commercial License - See [LICENSE](LICENSE) file
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cordova-plugin-hot-updates",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Frontend-controlled manual hot updates for Cordova iOS apps using WebView Reload approach. Manual updates only, JavaScript controls all decisions.",
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "Frontend-controlled manual hot updates for Cordova iOS and Android apps using WebView Reload approach. Manual updates only, JavaScript controls all decisions. 100% API compatibility between platforms.",
|
|
5
5
|
"main": "www/HotUpdates.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
8
|
"prepublishOnly": "npm run verify",
|
|
9
|
-
"verify": "node -e \"console.log('Verifying package structure...'); const fs = require('fs'); ['www/HotUpdates.js', 'src/ios/HotUpdates.h', 'src/ios/HotUpdates.m', 'src/ios/HotUpdatesConstants.h', 'src/ios/HotUpdatesConstants.m', 'src/ios/HotUpdates+Helpers.h', 'src/ios/HotUpdates+Helpers.m', 'plugin.xml', 'LICENSE', 'README.md'].forEach(f => { if (!fs.existsSync(f)) throw new Error('Missing required file: ' + f); }); console.log('✓ All required files present');\"",
|
|
9
|
+
"verify": "node -e \"console.log('Verifying package structure...'); const fs = require('fs'); ['www/HotUpdates.js', 'src/ios/HotUpdates.h', 'src/ios/HotUpdates.m', 'src/ios/HotUpdatesConstants.h', 'src/ios/HotUpdatesConstants.m', 'src/ios/HotUpdates+Helpers.h', 'src/ios/HotUpdates+Helpers.m', 'src/android/HotUpdates.java', 'src/android/HotUpdatesHelpers.java', 'src/android/HotUpdatesConstants.java', 'plugin.xml', 'LICENSE', 'README.md'].forEach(f => { if (!fs.existsSync(f)) throw new Error('Missing required file: ' + f); }); console.log('✓ All required files present');\"",
|
|
10
10
|
"pack-test": "npm pack && echo '\n✓ Package created. Test installation with: cordova plugin add ./cordova-plugin-hot-updates-*.tgz'",
|
|
11
11
|
"preversion": "npm run verify",
|
|
12
12
|
"postversion": "git push && git push --tags"
|
|
@@ -26,8 +26,10 @@
|
|
|
26
26
|
"manual",
|
|
27
27
|
"ecosystem:cordova",
|
|
28
28
|
"cordova-ios",
|
|
29
|
+
"cordova-android",
|
|
29
30
|
"mobile",
|
|
30
|
-
"app"
|
|
31
|
+
"app",
|
|
32
|
+
"cross-platform"
|
|
31
33
|
],
|
|
32
34
|
"author": {
|
|
33
35
|
"name": "Mustafin Vladimir",
|
|
@@ -45,15 +47,18 @@
|
|
|
45
47
|
"cordova": {
|
|
46
48
|
"id": "cordova-plugin-hot-updates",
|
|
47
49
|
"platforms": [
|
|
48
|
-
"ios"
|
|
50
|
+
"ios",
|
|
51
|
+
"android"
|
|
49
52
|
]
|
|
50
53
|
},
|
|
51
54
|
"peerDependencies": {
|
|
52
|
-
"cordova-ios": ">=4.4.0"
|
|
55
|
+
"cordova-ios": ">=4.4.0",
|
|
56
|
+
"cordova-android": ">=9.0.0"
|
|
53
57
|
},
|
|
54
58
|
"devDependencies": {
|
|
55
59
|
"cordova": "^12.0.0",
|
|
56
|
-
"cordova-ios": "^7.0.0"
|
|
60
|
+
"cordova-ios": "^7.0.0",
|
|
61
|
+
"cordova-android": "^12.0.0"
|
|
57
62
|
},
|
|
58
63
|
"files": [
|
|
59
64
|
"www/",
|
package/plugin.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version='1.0' encoding='utf-8'?>
|
|
2
2
|
<plugin id="cordova-plugin-hot-updates"
|
|
3
|
-
version="2.
|
|
3
|
+
version="2.3.0"
|
|
4
4
|
xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
|
5
5
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
6
6
|
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
<description>
|
|
9
9
|
Cordova plugin for frontend-controlled manual hot updates using WebView Reload approach.
|
|
10
10
|
Manual updates only, JavaScript controls all decisions.
|
|
11
|
-
|
|
11
|
+
Supports iOS and Android with 100% API compatibility.
|
|
12
12
|
</description>
|
|
13
13
|
<license>Custom Non-Commercial</license>
|
|
14
|
-
<keywords>cordova,hot,updates,ota,over-the-air,webview,reload,manual</keywords>
|
|
14
|
+
<keywords>cordova,hot,updates,ota,over-the-air,webview,reload,manual,ios,android</keywords>
|
|
15
15
|
<repo>https://github.com/vladimirDarksy/Cordova_hot_update.git</repo>
|
|
16
16
|
<issue>https://github.com/vladimirDarksy/Cordova_hot_update/issues</issue>
|
|
17
17
|
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
<engines>
|
|
21
21
|
<engine name="cordova" version=">=7.0.0" />
|
|
22
22
|
<engine name="cordova-ios" version=">=4.4.0" />
|
|
23
|
+
<engine name="cordova-android" version=">=9.0.0" />
|
|
23
24
|
</engines>
|
|
24
25
|
|
|
25
26
|
<!-- JavaScript interface -->
|
|
@@ -69,10 +70,30 @@
|
|
|
69
70
|
</edit-config>
|
|
70
71
|
</platform>
|
|
71
72
|
|
|
72
|
-
<!-- Android platform
|
|
73
|
+
<!-- Android platform -->
|
|
73
74
|
<platform name="android">
|
|
74
|
-
<!--
|
|
75
|
-
|
|
75
|
+
<!-- Plugin configuration -->
|
|
76
|
+
<config-file target="res/xml/config.xml" parent="/*">
|
|
77
|
+
<feature name="HotUpdates">
|
|
78
|
+
<param name="android-package" value="com.getmeback.hotupdates.HotUpdates" />
|
|
79
|
+
<param name="onload" value="true" />
|
|
80
|
+
</feature>
|
|
81
|
+
</config-file>
|
|
82
|
+
|
|
83
|
+
<!-- Native Android files -->
|
|
84
|
+
<source-file src="src/android/HotUpdates.java"
|
|
85
|
+
target-dir="src/com/getmeback/hotupdates" />
|
|
86
|
+
<source-file src="src/android/HotUpdatesHelpers.java"
|
|
87
|
+
target-dir="src/com/getmeback/hotupdates" />
|
|
88
|
+
<source-file src="src/android/HotUpdatesConstants.java"
|
|
89
|
+
target-dir="src/com/getmeback/hotupdates" />
|
|
90
|
+
|
|
91
|
+
<!-- Critical preferences for file:// scheme support -->
|
|
92
|
+
<config-file target="res/xml/config.xml" parent="/*">
|
|
93
|
+
<preference name="scheme" value="file" />
|
|
94
|
+
<preference name="AndroidInsecureFileModeEnabled" value="true" />
|
|
95
|
+
<preference name="LoadUrlTimeoutValue" value="120000" />
|
|
96
|
+
</config-file>
|
|
76
97
|
</platform>
|
|
77
98
|
|
|
78
99
|
<!-- Plugin hooks (optional) -->
|