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 CHANGED
@@ -1,32 +1,34 @@
1
- # Cordova Hot Updates Plugin v2.2.2
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
  [![npm version](https://badge.fury.io/js/cordova-plugin-hot-updates.svg)](https://badge.fury.io/js/cordova-plugin-hot-updates)
17
6
  [![License](https://img.shields.io/badge/License-Custom%20Non--Commercial-blue.svg)](#license)
7
+ [![Platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20Android-lightgrey.svg)](#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
- This plugin enables **manual, JavaScript-controlled** web content updates for your Cordova iOS applications without requiring App Store approval. Your frontend code decides when to check, download, and install updates.
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
- - **Frontend Control**: JavaScript decides when to update (no automatic background checking)
24
- - **Two-Step Updates**: Separate download (`getUpdate`) and install (`forceUpdate`) for better UX
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
- - **Instant Effect**: WebView Reload approach - no app restart needed
29
- - **Cache Management**: Clears WKWebView cache (disk, memory, Service Worker) before reload
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 >= 11.2
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 from Info.plist
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 Xcode console: `[HotUpdates] ...`
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.2.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.2.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
- Enables seamless web content updates without requiring App Store approval.
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 (placeholder for future implementation) -->
73
+ <!-- Android platform -->
73
74
  <platform name="android">
74
- <!-- Android implementation would go here -->
75
- <!-- For now, this plugin only supports iOS -->
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) -->