CodePush简介
CodePush 是微软开发的,可以实时更新 React Native 和 Cordova 应用。
CodePush 是提供给 React Native 和 Cordova 开发者直接部署移动应用更新给用户设备的云服务。CodePush 作为一个中央仓库,开发者可以推送更新到 (JS, HTML, CSS and images),应用可以从客户端 SDKs 里面查询更新。CodePush 可以让应用有更多的可确定性,也可以让你直接接触用户群。在修复一些小问题和添加新特性的时候,不需要经过二进制打包,可以直接推送代码进行实时更新。
CodePush 可以进行实时的推送代码更新:
- 直接对用户部署代码更新
- 管理 Alpha,Beta 和生产环境应用
- 支持 Cordova 和 React Native
CodePush的react-native版本是react-native-code-push
JavaScript API
- checkForUpdate
- getCurrentPackage
- notifyApplicationReady
- restartApp
- sync
codePush.checkForUpdate
询问code push
服务器是否app有新的版本
codePush.checkForUpdate(deploymentKey: String = null): Promise<RemotePackage>;
该方法返回Promise,有如下两种值:
- null 没有更新
- A RemotePackage instance
举例用法:1
2
3
4
5
6
7
8codePush.checkForUpdate()
.then((update) => {
if (!update) {
console.log("The app is up to date!");
} else {
console.log("An update is available! Should we download it?");
}
});
codePush.getCurrentPackage
获得当前已安装更新的元数据(比如描述,安装时间,大小)
举例:1
2
3
4
5
6
7
8
9codePush.getCurrentPackage()
.then((update) => {
// If the current app "session" represents the first time
// this update has run, and it had a description provided
// with it upon release, let's show it to the end user
if (update.isFirstRun && update.description) {
// Display a "what's new?" modal
}
});
codePush.notifyApplicationReady
通知CodePush进程,一个更新安装好了。当你检查并安装更新,(比如没有使用sync方法去handle的时候),这个方法必须被调用。否则CodePush会认为update失败,并rollback当前版本,在app重启时。
当使用sync
方法时,不需要调用本方法,因为sync
会自动调用,
codePush.restartApp
立即重启app.
当以下情况时,这个方式是很有用的。:
- app 当 调用
sync
orLocalPackage.install
方法时,指定的 install mode 是ON_NEXT_RESTART
orON_NEXT_RESUME
时 . 这两种情况都是当app重启或resume时,更新内容才能被看到。 - You have an app-specific user event (e.g. the end user navigated back to the app’s home route) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end user sooner then waiting until the next restart or resume.
因为强制重启,能马上显示更新内容嘛!
codePush.sync
1 | codePush.sync(options: Object, syncStatusChangeCallback: function(syncStatus: Number), downloadProgressCallback: function(progress: DownloadProgress)): Promise<Number>; |
允许检查更新,下载并安装,都在一个方法中。除非你需要自定义UI开表现。我们建议开发者在整合CodePush时,使用这个函数。
checkForUpdate方法只能检查更新,接下来怎么做要自己写。而该方法更新,下载,安装都能处理。该方法提供了两种模式
Silent mode
(默认的模式),
它会自动下载可用更新,并在下次重启应用时应用它们(比如操作系统或用户杀死进程,或者重新启动设备) 。这样一来,整个更新是“沉默”给最终用户,因为用户看不到任何更新提示。
Active mode
当有可用的更新,提示用户是否允许下载,然后立即应用此更新。一旦选择了强制通知用户来手动更新,以后每次更新都会强制通知。个人感觉这种方式最合理
sync
方法,有以下设置属性
deploymentKey
(String): 部署key,用来区分不同的app,在Info.plist
(Ios)和MianActivity.java
(Android)修改,当然你也可以在JavaScript里填写,这样我们能动态的修改keyinstallMode
(codePush.InstallMode): 非强制更新,默认codePush.InstallMode.ON_NEXT_RESTART
mandatoryInstallMode
(codePush.InstallMode):强制更新,默认codePush.InstallMode.IMMEDIATE
minimumBackgroundDuration
(Number):updateDialog
(UpdateDialogOptions) :可选的,更新的对话框,默认是null,包含以下属性appendReleaseDescription
(Boolean) - 是否显示更新description,默认falsedescriptionPrefix
(String) - 更新说明的前缀。 默认是” Description: “mandatoryContinueButtonLabel
(String) - 强制更新的按钮文字. 默认 to “Continue”.mandatoryUpdateMessage
(String) - 强制更新时,更新通知. Defaults to “An update is available that must be installed.”.optionalIgnoreButtonLabel
(String) - 非强制更新时,取消按钮文字. Defaults to “Ignore”.optionalInstallButtonLabel
(String) - 非强制更新时,确认文字. Defaults to “Install”.optionalUpdateMessage
(String) - 非强制更新时,更新通知. Defaults to “An update is available. Would you like to install it?”.title
(String) - 要显示的更新通知的标题. Defaults to “Update available”.
举例:
1 | // Prompt the user when an update is available |
实战应用
Service部署
安装CodePush CLI
npm install -g code-push-cli
可以输入code-push -v
查看版本号
创建CodePush 账号
在发布一个更新前,必须有账号。
- 终端输入
code-push register
,执行后弹出https://codepush-management.azurewebsites.net/auth/register?hostname=DESKTOP-3PVIHT6, - 选择输入微软账号或者github账号,选择Authorize application。然后注册成功,获得一个token。
- token输入到控制台,显示
- 登录
code-push login
- 注销
code-push loout
- 列出登录的token
code-push access-key ls
- 删除某个access-key
code-push access-key rm <accessKey>
注册一个app
常用命令,只有下面几个:
access-key
View and delete active user sessionsapp
View and manage your CodePush-enabled appscollaborator
View and manage collaborators for a given appdeployment
View and manage the deployments for your appslogin
Authenticate with the CodePush server in order to begin managing your appslogout
Log out of the current sessionpromote
Promote the package from one deployment of your app to anotherregister
Register a new account with the CodePush serverrelease
Release a new version of your app to a specific deploymentrelease-react
Release a new version of your React Native app to a specific deploymentrollback
Performs a rollback on the latest package of a specific deployment
选项:
- -v, –version 显示版本号 [boolean]
比如
- 查看当前部署的app:
code-push app ls
- 添加一个app:
code-push app add Zlot_react
部署已经注册的app
- 部署:
code-push deployment add app名字 部署名
- 重命名部署名:
code-push deployment rename app名字 旧部署名 新部署名
- 删除部署名字:
code-push deployment rm app名字 部署名字
- 列表部署名字:
code-push deployment ls app名字
- 查看部署的key:
code-push deployment ls app名 -k
- 查看release 的历史版本
code-push deployment history appName deploymentName
注意:默认的部署名是staging,所以staging的key值就是我们的deployment key
react-native-code-push插件安装
需要有git环境,并在app工程目录控制台输入
npm install react-native-code-push --save
安装成功在package.json会看到
"react-native-code-push": "^1.8.0-beta",
android配置
- 编辑android/setting.gradle文件,添加
1 | include ':app', ':react-native-code-push' |
- 编辑android/app/builde.gradle文件,添加依赖
1
compile project(':react-native-code-push')
android react-native v0.18.0+
此种配置方法仅仅适用react-native 0.18版本及其以上。而且是android studio环境
- 修改
MainActivity.java
文件,添加CodePush包
1 | // 1. Import the plugin class |
- 确定在
android/app/build.gradle
文件有android.defaultConfig.versionName
属性
1 | android { |
JavaScript代码
- 导入CodePush的JavaScript组件
import codePush from "react-native-code-push";
- 在在每个app启动时,在生命周期的
componentDidMount
阶段调用sync
,来开启一个后台的更新。
codePush.sync();
设计方案
isMandatory === true
强制更新,采用弹出model框提醒的方式
isMandatory === false
非强制更新,采用静默安装的方式
如:1
2
3
4
5
6
7componentDidMount() {
codePush.sync({
updateDialog: false,
installMode: codePush.InstallMode.ON_NEXT_RESUME,
deploymentKey: CODE_PUSH_PRODUCTION_KEY,
});
},
app如何更新(JavaScript+image)
注意:从react-native v0.19.0开始支持android更新assets资源,并且需要CodePush v1.7.0。所以你需要升级你的react-native跟CodePush。
确保在工程目录,新建release文件夹,如下
package命令
1 | react-native bundle |
Android版本
1
react-native bundle --platform android --entry-file index.android.js --bundle-output ./release/main.jsbundle --assets-dest ./release --dev false
ios版本
1
react-native bundle --platform ios --entry-file index.ios.js --bundle-output ./release/main.jsbundle --assets-dest ./release --dev false
release命令
1 | code-push release <appName> <updateContents> <targetBinaryVersion> |
mandatory :是否强制更新。
注意:targetBinaryVersion指的是当前的app版本,比如客户端是1.0.0,如果我们要更新客户端,targetBinaryVersion也要是1.0.0,表示是1.0.0版本的更新,跟native的更新不太一样。这是我们第一次经常犯的错误大家不要搞混了。
- Android版本
1
code-push release Zlot ./release 1.0.0 --description "这是一个1.0.0版本的更新" --mandatory true
常见问题
1 更新不成功,报but it is being ignored due to having been previously rolled back.
问题原因:客户端版本1.0.0,然后release的版本是1.0.1,所以检测的时候发现不了1.0.0版本的更新。
因此我们也建议,js的更新采用静默更新,native的更新,做出提示。
注意:targetBinaryVersion指的是当前的app版本,比如客户端是1.0.0,如果我们要更新客户端,targetBinaryVersion也要是1.0.0,表示是1.0.0版本的更新,跟native的更新不太一样。这是我们第一次经常犯的错误大家不要搞混了。
2 [CodePush] An update is available, but it is being ignored due to having been previously rolled back.
解决方案:一般这种情况是在,我们自定义model,展示更新过程,并监听了安装完成,比如这个demo,我这这里忘了在componentDidMount()
方法里添加CodePush.notifyApplicationReady();
,就一直报这个错误。添加上就ok了