React Native中android集成code-push框架实现热修复
1.本地电脑安装code-push
电脑cmd命令行中安装codepush本地启动器:npm install -g code-push-cli
安装完成之后运行code-push register会在浏览器打开网址进行注册 可以用github账号进行登录 登陆之后给一个key复制下来粘贴在cmd中,然后回车完成注册
然后终端输入code-push login进行登陆,登陆成功后,你的session文件将会写在 /Users/你的用户名/.code-push.config。
相关命令:
code-push login 登陆
code-push loout 注销
code-push access-key ls 列出登陆的token
code-push access-key rm 删除某个 access-key
2.在CodePush服务器注册app
为了让CodePush服务器知道你的app,我们需要向它注册app: 在终端输入code-push app add 即可完成注册。
例如:code-push app add JiuYue
注册完成之后会返回一套deployment key,该key在后面步骤中会用
注意:如果你的应用分为Android和iOS版,那么在向CodePush注册应用的时候需要注册两个App获取两套deployment key,app名称不能相同
相关命令:
code-push app add 在账号里面添加一个新的app
code-push app remove 或者 rm 在账号里移除一个app
code-push app rename 重命名一个存在app
code-push app list 或则 ls 列出账号下面的所有app
code-push app transfer 把app的所有权转移到另外一个账号
3.android端集成CodePush
第一步:在项目中安装 react-native-code-push插件,终端进入你的项目根目录然后运行
npm install --save react-native-code-push
第二步:进行link
react-native link react-native-code-push(这一块有些博客比较旧,是使用的rnpm,较新的版本没有必要)
在终端运行此命令之后,终端会提示让你输入deployment key,这个地方可以输入也可以直接回车跳过。
第一种情况:如果输入自己前一步返回的任意一个key之后会自动在values中给配置,在MainApplication中进行配置,输入的key也需要和后面在js中检测更新时给的key保持一致。一般建议输入production的key。
link之后查看/android/app/build.gradle中是否有apply from: “…/…/node_modules/react-native-code-push/android/codepush.gradle” ,没有就添加
然后在/android/settings.gradle中查看是否有如下代码,没有就添加:
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
第二种情况,在link时没有输入自己选择的key,可以自己在build.gradle中进行打包时的配置,具体步骤如下:
link完成之后在/android/app/build.gradle中添加代码:
buildTypes {
debug {
···
buildConfigField "String", "CODEPUSH_KEY", '"你自己的Staging Deployment Key "'
···
}
release {
···
buildConfigField "String", "CODEPUSH_KEY", '"你自己的Production Deployment Key "'
···
}
}
一般来说,release中是Production的Deployment Key,属于正式环境下的key。
如果要区分两种key的关系,查看博客:react-native-code-push进阶篇
在MainApplication中的配置:
新增这个重写的方法并且别忘记导包:
import android.support.annotation.NonNull;
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@NonNull
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
}
在MainApplication中配置的new CodePush最终形态
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
···
new CodePush(BuildConfig.CODEPUSH_KEY, getApplicationContext(), BuildConfig.DEBUG),
···
);
}
第三步:
在 android/app/build.gradle中有个 android.defaultConfig.versionName属性,我们需要把 应用版本改成 1.0.0(默认是1.0,但是code-push需要三位数)
4.在js中进行更新检测配置:
//尽量在主界面的入口处进行调用
componentDidMount() {
this.checkCodePushVersion()
}
//code push热修复接入口
checkCodePushVersion() {
codePush.sync({
updateDialog: {
appendReleaseDescription: true, //true表示显示更新信息,如果为false就不会提示用户直接下载
descriptionPrefix: '\n更新内容:\n',
title: '有新的更新包',
mandatoryUpdateMessage: '',
mandatoryContinueButtonLabel: '更新',
},
mandatoryInstallMode: codePush.InstallMode.ON_NEXT_RESTART, //更新模式
deploymentKey: DEPLOYMENTKEY, //你自己配置的key,打包时使用到的DEPLOYMENTKEY
},
this.codePushStatusDidChange.bind(this), //状态监听
this.codePushDownloadDidProgress.bind(this)); //下载进度监听
}
//code-push的状态监听
codePushStatusDidChange(status) {
switch (status) {
case codePush.SyncStatus.CHECKING_FOR_UPDATE:
console.log("Checking for updates.");
break;
case codePush.SyncStatus.DOWNLOADING_PACKAGE:
console.log("Downloading package.");
break;
case codePush.SyncStatus.INSTALLING_UPDATE:
ToastAndroid.showWithGravity("下载完成,下次进入将会自动更新", ToastAndroid.SHORT, ToastAndroid.CENTER)
break;
case codePush.SyncStatus.UP_TO_DATE:
console.log("Installing update.");
break;
case codePush.SyncStatus.UPDATE_INSTALLED:
console.log("Update installed.");
break;
}
}
//code-push的下载进度监听
codePushDownloadDidProgress(progress) {
console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
}
(1)sync方法,提供了如下属性以允许你定制sync方法的默认行为
deploymentKey (String): 部署key,指定你要查询更新的部署秘钥,你可以通过设置该属性来动态查询不同部署key下的更新。
installMode (codePush.InstallMode): 安装模式,用在向CodePush推送更新时没有设置强制更新(mandatory为true)的情况下,默认codePush.InstallMode.ON_NEXT_RESTART即下一次启动的时候安装。
mandatoryInstallMode (codePush.InstallMode):强制更新,默认codePush.InstallMode.IMMEDIATE。
minimumBackgroundDuration (Number):该属性用于指定app处于后台多少秒才进行重启已完成更新。默认为0。 该属性只在installMode为InstallMode.ON_NEXT_RESUME情况下有效。
updateDialog (UpdateDialogOptions) :可选的,更新的对话框,默认是null,包含以下属性
appendReleaseDescription (Boolean) - 是否显示更新description,默认false
descriptionPrefix (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”.
(2)需要注意的是,sync方法需要在每次启动是都调用,不然会出现版本的回退。
5.版本发布
准备工作:在项目根目录下创建一个文件夹bundles
然后在项目根目录下进行命令行输入
(1)打包
react-native bundle --entry-file index.js --bundle-output ./bundles/index.android.bundle --platform android --assets-dest ./bundles --dev false
(2)打包完成之后将打包的bundes更新到codepush服务器
code-push release 你的项目名 ./bundles 1.0.0 --deploymentName Production --description “修改电子书评价” --mandatory true
参数介绍:
code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName: 更新环境 --description: 更新描述 --mandatory: 是否强制更新
注意:(1)这里的版本号是你现在线上的apk版本号,而不是你打包时的版本号,很多人在这一步做错,就是因为在生成apk时版本号是1.0.0,但是打包bundles时人为把版本号升级到1.0.1,然后命令行输入的也是
code-push release 你的项目名 ./bundles 1.0.1 --deploymentName Production --description “修改电子书评价” --mandatory true
这个是错误的做法,如果这样做的话,codepush会去找1.0.1版本号的apk去提示更新,这样就会出现你生成的1.0.0的包接收不到升级提示或者会报有更新,但是不是针对你的apk版本。所以需要注入你生成的apk的版本是多少,这里对应的版本就是多少,不管你对这个版本进行了多少次的codepush,版本号是不变的。jsbundles只是打包js文件,不会去打包android文件夹下的内容。
(2)很多博客上的打包命令都是错误的,只能打包出js文件,忽略了图片数据,这样你在更新之后会出现本地的图标无法显示的问题,需要注意这个坑。
6.其他:
使用code-push app ls查看是否添加成功?
默认会创建两个部署(deployment)环境:Staging和Production,可以通过code-push deployment ls MyAppIOS -k来查看当前App所有的部署,-k是用来查看部署的key,这个key是要方法原生项目中去的
已经发布到Production的更新如果撤销?
如果发生了我上面提到的发布出去的更新有bug或者重大崩溃,不想让更多的用户检测到此更新怎么办?这时你可以马上登录code-push官网https://microsoft.github.io/code-push/ ,然后登录进入到App Center,选择你对应的App, 选择Distribute-> Code-Push, 选择Production,点击你想要撤销的版本,有个设置的按钮,将Enabled 关掉,这样用户就检测不到你此版本了。
热更新是更新的那些内容?
热更新只是更新的js代码,并不能更新原生中的更改,所以如果你在原生中改了什么东西或者是更新了一些RN的三方库都需要重新打原生包发布到AppStore或者是android应用市场中去,而不能通过热更新来实现
参考博客:
React Native应用部署/热更新-CodePush最新集成总结
react-native-code-push进阶及实践小结
react-native-code-push进阶篇