
Security News
vlt Launches "reproduce": A New Tool Challenging the Limits of Package Provenance
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
cordova-app-loader
Advanced tools
Remote update your Cordova App
A little later...
CordovaAppLoader
to
check()
for a new manifestdownload()
filesupdate()
your app!Check out Cordova App Loader in Chrome for a demo! (Chrome only!)
Or run on your own computer:
git clone git@github.com:markmarijnissen/cordova-app-loader.git
cd cordova-app-loader
cordova platform add ios@3.7.0
cordova plugin add org.apache.cordova.file
cordova plugin add org.apache.cordova.file-transfer
cordova run ios
Note: Want to run your own server? Modify serverRoot
in www/app.js
!
cordova platform add ios@3.7.0
cordova plugin add org.apache.cordova.file
cordova plugin add org.apache.cordova.file-transfer
IMPORTANT: For iOS, use Cordova 3.7.0 or higher (due to a bug that affects requestFileSystem).
You need:
CordovaAppLoader includes cordova-file-cache to download and cache the files.
bower install cordova-app-loader cordova-promise-fs bluebird
npm install cordova-app-loader cordova-promise-fs bluebird
check()
, download()
and apply()
updates: // When using NPM, require these first.
// When using the ready-made files, these are available as global variables.
var CordovaPromiseFS = require('cordova-promise-fs');
var CordovaAppLoader = require('cordova-app-loader');
var Promise = require('bluebird');
// Initialize a FileSystem
var fs = new CordovaPromiseFS({
Promise: Promise
});
// Initialize a CordovaAppLoader
var loader = new CordovaAppLoader({
fs: fs,
serverRoot: 'http://data.madebymark.nl/cordova-app-loader/'
});
// Write your own "check", "download" and "update" logic:
loader.check()
.then(function(){
return loader.download();
}).then(function(){
return loader.update();
})
See an example.
If you don't need full control, you can use a ready-made solution: autoupdate.js
autoupdate.js includes everything except the bootloader.js (a Promise library, CordovaPromiseFS.js and CordovaAppLoader.js).
Autoupdate initializes everything as described above, and automatically updates your app when you open or resume it.
Download index.html, bootstrap.js and autoupdate.js to your www
directory.
Write a manifest.json (see below). Include autoupdate.js
in it.
Make sure you set the correct options in index.html
:
<script
type="text/javascript"
server="http://data.madebymark.nl/cordova-app-loader/"
manifest="manifest.json"
src="bootstrap.js"></script>
Write window.BOOTSTRAP_OK = true
in your code when your app succesfully launches.
Launch your app.
Upload a new manifest.json (+ files) to your server.
Reopen your app to download and apply the update.
This implementation is not recommended because:
Note: You cannot update bootstrap.js
- therefore autoupdate.js
is a seperate file. (So you can update autoupdate
itself).
Describe which files to download and which files to load during bootstrap.
{
"files": { // these files are downloaded (only when "version" is different from current version!)
"jquery": {
"version": "afb90752e0a90c24b7f724faca86c5f3d15d1178",
"filename": "lib/jquery.min.js"
},
"bluebird": {
"version": "f37ff9832449594d1cefe98260cae9fdc13e0749",
"filename": "lib/bluebird.js"
},
"CordovaPromiseFS": {
"version": "635bd29385fe6664b1cf86dc16fb3d801aa9461a",
"filename": "lib/CordovaPromiseFS.js"
},
"CordovaAppLoader": {
"version": "76f1eecd3887e69d7b08c60be4f14f90069ca8b8",
"filename": "lib/CordovaAppLoader.js"
},
"template": {
"version": "3e70f2873de3d9c91e31271c1a59b32e8002ac23",
"filename": "template.html"
},
"app": {
"version": "8c99369a825644e68e21433d78ed8b396351cc7d",
"filename": "app.js"
},
"style": {
"version": "6e76f36f27bf29402a70c8adfee0f84b8a595973",
"filename": "style.css"
}
},
"load": [ // these files are loaded in your index.html
"lib/jquery.min.js",
"lib/bluebird.js",
"lib/CordovaPromiseFS.js",
"lib/CordovaAppLoader.js",
"app.js",
"style.css"
],
"root":"./", // root location of files to be loaded. Defaults to current location: `./`
}
You can update your existing manifest like this:
node node_modules/cordova-app-loader/bin/update-manifest www www/manifest.json
node node_modules/cordova-app-loader/bin/update-manifest [root-directory] [manifest.json]
It will update the version of only changed files (with a hash of the content).
Or check out this gruntfile.
new CordovaAppLoader()
check()
for updatesdownload()
new filesupdate()
to apply updateRetrieves manifest.json and dynamically inserts JS/CSS to the current page.
<script type="text/javascript" timeout="5000" manifest="manifest.json" src="bootstrap.js"></script>
On the second run, the manifest.json is retrieved from localStorage.
Set window.BOOTSTRAP_OK
to true
when your app has succesfully launched.
If your app is updated and window.BOOTSTRAP_OK
is not true after timeout
milliseconds, the corrupt manifest in localStorage is destroyed, and the page will reload. This will revert the app back to the original manifest.
You should always bundle a manifest.json (+ files) in your app to make sure your app has a "factory default" to revert back to. (And to make sure your app works offline).
// When using NPM, require these first.
// When using bower or when you downloaded the files these are already available as global variables.
var CordovaPromiseFS = require('cordova-promise-fs');
var CordovaAppLoader = require('cordova-app-loader');
var Promise = require('bluebird');
// Initialize a FileSystem
var fs = new CordovaPromiseFS({
Promise: Promise
});
// Initialize a CordovaAppLoader
var loader = new CordovaAppLoader({
fs: fs,
serverRoot: 'http://data.madebymark.nl/cordova-app-loader/',
localRoot: 'app',
cacheBuster: true // make sure we're not downloading cached files.
checkTimeout: 10000 // timeout for the "check" function - when you loose internet connection
});
// download manifest from: serverRoot+'manifest.json'
loader.check().then(function(updateAvailable) { ... })
// download from custom url
loader.check('http://yourserver.com/manifest.json').then( ... )
// or just check an actual Manifest object.
loader.check({ files: { ... } }).then( ... )
Implementation Note: Only file versions are compared! If you, for example, update manifest.load
then the promise will return false
!
loader.download(onprogress)
.then(function(manifest){ ... },function(failedDownloadUrlArray){ ... });
Note: When downloading, invalid files are deleted first. This invalidates the current manifest. Therefore, the current manifest is removed from localStorage. The app is reverted to "factory settings" (the manifest.json that comes bundled with the app).
This writes the new manifest to localStorage and reloads the page to bootstrap the updated app.
// write manifest to localStorage and reload page:
loader.update() // returns `true` when update can be applied
// write manifest to localStorage, but DO NOT reload page:
loader.update(false)
Implementation Note: CordovaAppLoader changes the manifest.root
to point to your file cache - otherwise the bootstrap script can't find the downloaded files!
I want CordovaAppLoader to be fast, responsive, flexible, reliable and safe. In order to do this, I've made the following decisions:
First, I wanted to download 'index.html' to storage, then redirect the app to this new index.html.
This has a few problems:
cordova.js
and plugin javascript cannot be found.cordova.js
in the manifest because it is platform specific.Dynamically inserting CSS and JS allows you for almost the same freedom in updates, without all these problems.
loader.download()
for the second time, old downloads are aborted.check
and download
return a promise. These promises should always resolve - i.e. don't wait forever for a "deviceready" or for a "manifest.json" AJAX call to return.
I am assuming the following promises resolve or reject sometime:
requestFileSystem
CordovaPromiseFS methods:
fs.root.getFile
)fs.root.getDirectory
)getDirectory
)dirReader.readEntries
)fileEntry.remove
)filetransfer.download()
to resolve the promise)XHR-request to fetch manifest.json (Rejected after timeout)
As you see, most methods rely on the succes/error callbacks of native/Cordova methods.
Only for deviceready
and the XHR-request I've added timeouts to ensure a timely response.
When using check
: The XHR will timeout.
When using download
: I am assuming Cordova will invoke the error callback. The download has a few retry-attempts. If the connetion isn't restored before the last retry-attemt, the download will fail.
The only critical moment is during a download. Old files are removed while new files aren't fully downloaded yet. This makes the current manifest point to missing or corrupt files. Therefore, before downloading, the current manifest is destroyed.
If the app crashes during a download, it will restart using the original manifest.
BOOTSTRAP_OK
is not set to true
after a timeout, the app will destroy the current manifest and revert back to the original manifest.Yes, you need to include four files - but this is to create flexibility.
CordovaPromiseFS
instance for the entire app.download()
can slow down performance and update()
can interrupt the user - you need to decide yourself you want to handle this.If you don't care about this, you can use autoupdate.js as describe in QuickStart above.
TODO: Include CordovaPromiseFS.js
in the CordovaAppLoader.js
build, just like the CordovaFileCache. I need to make sure CordovaPromiseFS and CordovaFileCache are globally available then.
Let me know if you find bugs. Report an issue!
serverUrl
and Manifest.root
work together as expected?)dist
folder to for all build filesConvert CommonJS to a browser-version:
npm install webpack -g
npm run-script prepublish
Feel free to contribute to this project in any way. The easiest way to support this project is by giving it a star.
© 2014 - Mark Marijnissen
FAQs
Cordova App Loader - remote update your cordova app
The npm package cordova-app-loader receives a total of 4 weekly downloads. As such, cordova-app-loader popularity was classified as not popular.
We found that cordova-app-loader demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.