通常ionic源码可包括(HTML,javaScript,CSS文件和其他资源),往常我们必须通过提交程序到应用市场,经过漫长的审核后才可让用户更新,每改动一个小地方都需要重新打新版本。
现在ionic通过使用cordova插件cordova-hot-code-push
实现实现iOS与Android端代码『热更新』功能,可不必发布应用市场经平台审核,便可动态更新App源码的目的。
cordova-hot-code-push-cli
使用命令安装
1 | npm install -g cordova-hot-code-push-cli |
主要是生成检测配置文件,通常是在 www
目录下动态生成 chcp.json
和 chcp.manifest
生成两个文件,插件源码地址:
https://github.com/nordnet/cordova-hot-code-push
2、创建项目
包含
www
目录的项目,已有项目无需重新创建3、安装热更新插件
使用命令安装
123 ionic plugin add cordova-hot-code-push-pluginionic plugin add cordova-hot-code-push-local-dev-addon4、打包封装
执行命令
cordova-hcp build
或者cordova build
5、启动 hcp server 服务
重新打开一个终端窗口,cd到项目目录(包含www目录的父级目录)执行命令
1 cordova-hcp server稍等会在
www
目录下动态生成chcp.json
和chcp.manifest
生成两个文件6、正常在运行完成前4步以后会在我们config.xml动态加入如图所示链接地址
图中链接地址
https://1980480f.ngrok.io/chcp.json
,修改为在第8步www目录里chcp.json
文件可访问的地址:例如:
http://kaibin.me/hotcode/chcp.json
7、运行代码或打包我们的App
8、修改我们想要更新的代码
然后修改
chcp.json
文件的content_url
,此地址为我们项目放置的地址
123456 { "autogenerated": true, "release": "2016.07.17-11.36.13", "content_url": "http://kaibin.me/hotcode", "update": "now"}9、将项目www目录代码上传到服务器可访问的目录里
例如在服务器根目录创建
hotcode
命名的目录将项目www里的文件上传上去10、 关闭我们的应用重新打开,看看代码是否更新成功
优化流程
1.创建cordova-hcp模板
线上测试可卸载掉
cordova-hot-code-push-local-dev-addon
防止每次自动更新新版本,可通过命令卸载:
1 cordova plugin remove cordova-hot-code-push-local-dev-addon可以在 cordova 项目根目录下放一个
cordova-hcp.json
,这是个模板文件这样每次执行
1 cordova-hcp build就会利用这个模板生成新的 chcp.json,而不用手动更改 www/chcp.json了。cordova-hcp.json内容如下:
1234567 { "autogenerated": true, "content_url": "http://kaibin.me/hotcode", "min_native_interface": 1, // app内核版本号 "ios_identifier": "https://itunes.apple.com/cn/app/***", // iOS上线后的地址,用于内核版本更新后的确认跳转 "update": "now"}2.Build options build设置,配置开发环境、测试环境与生产环境
在 /Cordova/TestPRoject/ 下创建chcpbuild.options
文件,文件内容如下:这样在build app的时候, 转为开发要用的服务器, 可执行:
1234567891011 { "dev": { "config-file": "https://dev.kaibin.me/hotcode/www/chcp.json" }, "production": { "config-file": "https://kaibin.me/hotcode/chcp.json" }, "QA": { "config-file": "https://test.kaibin.me/hotcode/chcp.json" }}
1 ionic build -- chcp-dev结果就是, 特定拍下的 config.xml 文件(比如, /Cordova/TestProject/platforms/android/res/xml/config.xml) 变成了这样:
当我们需要上架app的时候 (Google Play, App Store) - 我们正常build:
123 <chcp> <config-file url="https://dev.kaibin.me/hotcode/chcp.json"/></chcp>
1 ionic build --release这样 config.xml 不会改变
如果没有使用
chcpbuild.options
插件会使用config.xml
里面默认的值。文件必须位于 Cordova 项目根目录. 在这个文件里面,指定(JSON格式) 所有想改变 config.xml 文件的配置,源文件 config.xml (Cordova项目根目录) 不会发生变动, 改变的是 特定平台下的 config.xml (在cordova build过程的 after_prepare 阶段)。
通过min_native_interface监控app是否提示更新
所需最小的外壳app版本. 这是app的build版本号,是个整型数字, 不是应用商店中看到的形如”1.0.0”字符串。
在 config.xml中,这样指定build版本号:
1234 <chcp> <native-interface version="1"/> <config-file url="http://kaibin.me/hotcode/chcp.json"/></chcp>与www目录下的chcp.json里面的
min_native_interface
数值相对应例如:app外壳里的config.xml是这样的:
1234 <chcp> <native-interface version="1"/> <config-file url="http://kaibin.me/hotcode/chcp.json"/></chcp>若服务器里的
min_native_interface
也对应是1,不会出现提示用户升级的状态,正常修改www目录的内容通过更新release值,可实现热更新。
12345678 { "autogenerated": true, "content_url": "http://kaibin.me/hotcode", "min_native_interface": 1, // app内核版本号 "ios_identifier": "https://itunes.apple.com/cn/app/***", // iOS上线后的地址,用于内核版本更新后的确认跳转 "release": "2017.07.17-12.22.11", "update": "now"}假设你的外壳app加了个新的插件,应该会更新外壳app。为了防止用户通过热更新下载了不适合他现有外壳app的web内容,你应该设置 min_native_interface 这个值
123456789 { "autogenerated": true, "content_url": "http://kaibin.me/hotcode", "min_native_interface": 1, // app内核版本号 "ios_identifier": "https://itunes.apple.com/cn/app/***", // iOS上线后的地址,用于内核版本更新后的确认跳转 "release": "2017.07.17-12.28.21", "min_native_interface": 2, "update": "now"}插件加载到这段json的时候, 发现 min_native_interface 比当前外壳app的build号要大,便不会下载web内容。而是触发一个chcp_updateLoadFailed 错误通知, 告诉用户需要升级外壳app了。
chcp.json中update字段含义
指定了什么时候安装web内容更新,支持的值有:
start - app启动时安装更新,默认值resume - app从后台切换过来的时候安装更新now - web内容下载完毕即安装更新
引导用户去应用商店更新外壳app或下载新版本
通过给web更新设置最小支持的外壳app版本
min_native_interface
。 如果插件检查发现用户安装的外壳app版本比服务端新的web内容要求的版本要低,就会触发错误事件,错误码:
1 chcp.error.application_BUILD_VERSION_TOO_LOW通过这个错误码可通过弹窗提示用户去升级,跳转到AppStore或下载新安装包(国内因GFW,跳转到google应用商店就算了= =)
chcp.json 里增加
min_native_interface
的值js端监听相应事件,并在出现错误的时候调用 chcp.requestApplicationUpdate 方法
cordova-plugin-file,cordova-plugin-file-transfer,cordova-plugin-file-opener2先把这几个插件安装好
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 var appUpdate = { // Application Constructor initialize: function() { this.bindEvents(); }, // Bind any events that are required. // Usually you should subscribe on 'deviceready' event to know, when you can start calling cordova modules bindEvents: function() { document.addEventListener('deviceready', this.onDeviceReady, false); document.addEventListener('chcp_updateLoadFailed', this.onUpdateLoadError, false); }, // deviceready Event Handler onDeviceReady: function() { }, onUpdateLoadError: function(eventData) { var error = eventData.detail.error; // 当检测出内核版本过小 if (error && error.code == chcp.error.APPLICATION_BUILD_VERSION_TOO_LOW) { var dialogMessage = '有新的版本,请下载更新'; // iOS端 直接弹窗提示升级,点击ok后自动跳转 if(ionic.Platform.isIOS()){ chcp.requestApplicationUpdate(dialogMessage, this.userWentToStoreCallback, this.userDeclinedRedirectCallback); // Android端 提示升级下载最新APK文件 }else if(ionic.Platform.isAndroid()){ var confirmPopup = $ionicPopup.confirm({ template: '有新的版本,请下载更新', cssClass: 'popup', cancelText:'取消', okText:'升级' }); confirmPopup.then(function (res) { if (res) { $ionicLoading.show({ template: "已经下载:0%" }); window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, function(fileEntry) { fileEntry.getDirectory("***(app名称)", { create: true, exclusive: false }, function (fileEntry) { //下载代码 var fileTransfer = new FileTransfer(); fileTransfer.download("app下载地址", fileEntry.toInternalURL()+"***(app名称).apk", function(entry) { // 打开下载下来的APP cordova.plugins.fileOpener2.open( entry.toInternalURL(),//下载文件保存地址 'application/vnd.android.package-archive', {//以APK文件方式打开 error: function(err) { }, success: function() {} }); }, function(err) { },true); fileTransfer.onprogress = function(progressEvent) { $timeout(function () { var downloadProgress = (progressEvent.loaded / progressEvent.total) * 100; $ionicLoading.show({ template: "已经下载:" + Math.floor(downloadProgress) + "%" }); if (downloadProgress > 99) { $ionicLoading.hide(); } }); }; },function(err){alert("创建失败")}); }); } }); } } }, userWentToStoreCallback: function() { // user went to the store from the dialog }, userDeclinedRedirectCallback: function() { // User didn't want to leave the app. // Maybe he will update later. } }; appUpdate.initialize();iOS与Android的出现的问题
在build ios的app时
config.xml
的
1 <name>***</name>name不可使用中文,设置app名称为中文,可通过Xcode修改Resources目录下的
***-Info.plist
内的Bundle display name
字段即可。这篇文章写得很详细,特转载过来慢慢研究,十分感谢本文作者贡献出如此好得文章。转载地址:http://kaibin.me/2016/07/17/ionic-hotcode/
新闻热点
疑难解答