用web做app的都知道codepush,它可以跳过频繁的app发布审查过程,可以方便快捷的更新程序,如cordova, react-native等,本文介绍微软的cordova-plugin-code-push插件(也是用的最多的)。
CodePush
微软开发的,可以实时更新 React Native 和 Cordova 应用,给 React Native 和 Cordova 开发者直接部署移动应用更新给用户设备的云服务。
作为一个云仓库,作为开发者可以直接推送更新到 JS, HTML, CSS and images,应用可以从客户端 SDKs 里面查询更新。
可以让我们在修复一些小问题和添加新特性的时候,不需要经过二进制打包,可以直接推送代码进行实时更新。
CodePush 推送代码更新:
- 直接对用户部署代码更新 管理 Alpha,Beta 和生产环境应用
- 支持 Cordova 和 React Native
- CodePush提供两个客户端 SDKs(Cordova 和React Native)
- 相关插件cordova-plugin-code-push
- 另一个热更新的插件,但是已经在2018.09.30宣布不再维护了,可以了解下(cordova-hot-code-push)
- 苹果App允许使用热更新Apple's developer agreement, 为了不影响用户体验,规定必须使用静默更新。 Google Play不能使用静默更新,必须弹框告知用户App有更新。中国的android市场必须采用静默更新(如果弹框提示,App会被“请上传最新版本的二进制应用包”原因驳回)。
准备环境
全局安装typescript、typings、tslint、code-push-cli、cordova
npm install -g typescript
npm install -g typings
npm install -g tslint
npm install -g cordova
npm install -g code-push-cli
注:code-push-cli是连接热更新服务端的工具,我们把要更新的代码上传至服务端,客户端安装cordova-plugin-code-push插件来从服务端下载代码.
注册登录CodePush服务器
CodePush终端安装完成后就可以使用code-push命令了。
在终端输入code-push register
或code-push login
(有账号),会跳转授权网页。在这个网页可以选择Github。或者微软作为授权提供者,不过我觉得90%的开发者都会选择Github。
授权完成后,CodePush会显示你的 Access Key,复制输入到终端即可完成注册并登陆。
若选择CodePush Server 私有化部署,则只需登录自己的code push Server的url,code-push login url
,然后输入运维给你的Access Key即可。
在CodePush服务器中创建App
在终端输入code-push app add
Usage: code-push app add
$:code-push app add MyApp android cordova
添加完成后,可以登录 https://appcenter.ms/apps查看创建的MyApp.
创建Cordova项目并整合CodePush
创建项目
cordova create MyApp
添加平台
cd MyApp
cordova platform add android
or
cordova platform add android@^6.0.0
cordova platform add ios
添加插件
cordova plugin add cordova-plugin-code-push@latest
cordova plugin add cordova-plugin-whitelist
在config.xml中配置deployment keys:
若不知道上面的key,可以用命令查看:
code-push deployment ls APP_NAME -k
config.xml中配置访问权限:
或
index.html配置白名单安全协议:
更新config.xml后重新 build 项目
cordova build
在app启动的时候调用code-push同步方法
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
/* Invoke sync with the custom options, which enables user interaction.
For customizing the sync behavior, see SyncOptions in the CodePush documentation. */
window.codePush.sync(
function (syncStatus) {
switch (syncStatus) {
// Result (final) statuses
case SyncStatus.UPDATE_INSTALLED:
app.displayMessage("The update was installed successfully. For InstallMode.ON_NEXT_RESTART, the changes will be visible after application restart. ");
break;
case SyncStatus.UP_TO_DATE:
app.displayMessage("The application is up to date.");
break;
case SyncStatus.UPDATE_IGNORED:
app.displayMessage("The user decided not to install the optional update.");
break;
case SyncStatus.ERROR:
app.displayMessage("An error occured while checking for updates");
break;
// Intermediate (non final) statuses
case SyncStatus.CHECKING_FOR_UPDATE:
console.log("Checking for update.");
break;
case SyncStatus.AWAITING_USER_ACTION:
console.log("Alerting user.");
break;
case SyncStatus.DOWNLOADING_PACKAGE:
console.log("Downloading package.");
break;
case SyncStatus.INSTALLING_UPDATE:
console.log("Installing update");
break;
}
},
{
installMode: InstallMode.ON_NEXT_RESTART, updateDialog: true
},
function (downloadProgress) {
console.log("Downloading " + downloadProgress.receivedBytes + " of " + downloadProgress.totalBytes + " bytes.");
});
app.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
},
// Displays an alert dialog containing a message.
displayMessage: function (message) {
navigator.notification.alert(
message,
null,
'CodePush',
'OK');
}
};
app.initialize();
更多用法,请参考codePush.sync
发布更新
使用命令code-push deployment list
如下图可以看到目前android应用"Production"和"Staging"两种部署状态
使用命令code-push release-cordova
默认发布"Staging"部署状态,也就是开发版.code-push release-cordova MyApp android --des "修改按钮颜色"
发布上传时间依网速快慢大概需要1分钟左右
再次查看发布状态,会看到"Staging"已经有一个版本"v1",但是还没有安装记录
发布完成后再看就有相关信息了,如下:
然后启动app就可以连接到服务器并检查更新,若有则自动更新。
调试技巧
使用android studio导入工程,然后使用真机联调,可以看到完整的日志输出,方便定位问题。
注意:修改cordova代码,需要同步到platform,执行cordova prepare [platform]
或cordova prepare
,否则打包的app代码不是最新的。
code-push常用命令
//给app在热更新服务器上创建应用
code-push app add
//删除应用
code-push app rm
//查看热更新服务器上有哪些应用
code-push app list
//发布应用
code-push release-cordova [options]
Options参数:
--deploymentName, -d ..指定部署的类型.默认"Staging",可以选择"Production"或其他 自定义类型
--description, --des ..添加描述
--mandatory, -m .......指定此版本是否为强制更新版本
例1:发布更新
code-push release-cordova ionic2_tabs_android android --des ""
例2:部署"Production"状态的更新,即生产环境的热更新部署使用这句命令
code-push release-cordova ionic2_tabs_android android -d "Production" --des ""
注意:一般生产环境的app是压缩过的,所以在发布正式环境热更新之前,先执行"ionic build --prod"压缩代码
例3:部署ios应用的更新
code-push release-cordova ionic2_tabs_ios ios --des ""
例4:添加-m参数强制更新,code-push插件从服务端下载完代码,会立即自动重启app
code-push release-cordova ionic2_tabs_android android -m --des ""
//查看部署状态
code-push deployment list
例1:
code-push deployment list ionic2_tabs_android
例2:查看部署状态及key值,忘记key就这样找
code-push deployment list ionic2_tabs_android -k
//清空部署记录
code-push deployment clear
如:清空Staging状态的部署记录
code-push deployment clear ionic2_tabs_android Staging
//添加部署状态,默认只有"Staging"和"Production"两中状态
code-push deployment add [deploymentName]
//删除自定义的部署状态
code-push deployment rm
其它
- 官方文档教程中,要给index.html添加如下,只是增加安全性
安全规则:若从图片库取图片,需要加content: 从远程取则加 http://ip:port
- 关于苹果 App Store禁止热更新的说明
目前还没有全面禁止热更新,收到警告邮件的开发者绝大部分是使用了 JS-Patch 或 Rollout 的热更新类库
参考文档:
- CodePush 官方文档
- code-push-server
- https://github.com/lisong/code-push-server
- https://github.com/lisong/code-push-web
- Cordova Client SDK