搞了两天,开始用react-native-pushy来做热更新,但是编译都编译不过,我就头疼了,后来想想还是算了,我还是用微软的吧,国内的东西如果做得让我们都放心的话,我就会用了,也可能是我不懂吧。废话少说,下面就开始进行我的codepush挖坑之路。测试了两个软件都还成功,挺不错的。
而且很多文章上讲的内容已经过时了,codepush也随着RN的更新也一直在更新,所以文章还是用最新的,最好是看github的地址。
codepush是微软的一套用于热更新的服务,微软的github地址:https://github.com/Microsoft/react-native-code-push,里面讲述了详细的使用方法。这里我就自己的操作做了一下调整。
我的代码在github上,大家可以查看下:https://github.com/LiuC520/react-native-codepush01
一、安装codepush服务
1、在终端输入 npm install -g code-push-cli,然后等待安装完毕。
安装完毕后输入 code-push -v查看版本,如果有版本就成功了,下一步。
(RN必须要用npm的,这里没有的话自己去看下RN的官网,安装下nodejs)
二、创建codepush账号
1、在终端输入 code-push register,打开了一个网页选择授权的账号。如下所示
2、我选的是github,这样的话会出来一个界面,把那个key复制下,并在终端复制下这个key,注册成功。
3、在终端输入 code-push login登录,以后再登录就不用注册了,只需要输入code-push login就可以了,然后出来一个key的页面,输入key就可以登录了。
其他的代码如下:
code-push login登陆
code-push logout注销
code-push access-key ls列出登陆的token
code-push access-key rm 删除某个 access-key
4、在codepush上注册我的app,就相当于我们在用极光推送的时候,要在极光的官网上注册一个应用,会给你一个appkey一样的道理:
在终端输入:code-push app add 你的应用名字
其他的命令如下:
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的所有权转移到另外一个账号
三、下面单独操作android和ios的配置(我的RN版本是0.37)
1、首先在终端输入 :
npm install --save react-native-code-push@latest
安装code-push最新版本
2、然后关联code-push
如果你安装了rnpm直接用命令:rnpm link react-native-code-push,如果没有安装先安装npm i -g rnpm,然后再输入rnpm link react-native-code-push,进行关联
3、ios端的配置如下:https://microsoft.github.io/code-push/docs/react-native.html#link-4
先用xcode打开RN项目下的ios,找到.xcodeproj的文件双击打开,点击左上角的项目名字,找到AppDelegate.m,单击打开,然后添加如下代码:
#import "CodePush.h"
然后把下面这两行代码更改下:
jsCodeLocation = [[RCTBundleURLProvidersharedSettings]
jsBundleURLForBundleRoot:@"index.ios"fallbackResource:nil];
更改成:
#ifdef DEBUG
jsCodeLocation = [[RCTBundleURLProvidersharedSettings]jsBundleURLForBundleRoot:@"index.ios"fallbackResource:nil];
#else
jsCodeLocation = [CodePush bundleURL];
#endif
4、打开xcode左侧的项目名称,找到general和info两个选项卡:分别作如下的操作,把bundle version和codepushdeploymentKey修改下就行了:
先在终端输入:
code-push deployment ls 您的应用名 -k
查询你的内容如下:
Staging 为测试的key,Production为生产打包时用的key。
然后按照下图配置ios的东西就行了
5、android端的配置如下:
同样在rnpm link react-native-code-push 后,打开RN项目的android-app-src-main-java-...-MainApplication.java,打开后
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost=new ReactNativeHost(this) {
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage> asList(
new MainReactPackage(),
new CodePush("kLavEmLMaRSwemp98FiAQ7BRK7bd4yj8ga1-f",MainApplication.this,BuildConfig.DEBUG)
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
其中new codepush里面的第一个字符串就是上面通过 code-push deployment ls 应用名 -k 查询出来的deployment key,我这里是直接用的Production key。
6、然后修改version name,
在 android/app/build.gradle中有个 android.defaultConfig.versionName属性,我们需要把 应用版本改成 1.0.0(默认是1.0,但是codepush需要三位数)。
android{
defaultConfig{
versionName"1.0.0"
}
}
四、RN中的操作如下:
详细的操作在官网demo示例中:https://github.com/Microsoft/react-native-code-push/blob/master/Examples/CodePushDemoApp/demo.js
首先导入:
import CodePush from "react-native-code-push";
let codePushOptions = { checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME };
sync() {
CodePush.sync();
}
/** Update pops a confirmation dialog, and then immediately reboots the app */
syncImmediate() {
CodePush.sync(
{ installMode: CodePush.InstallMode.IMMEDIATE,//启动模式三种:ON_NEXT_RESUME、ON_NEXT_RESTART、IMMEDIATE
updateDialog: {
appendReleaseDescription:true,//是否显示更新description,默认为false
descriptionPrefix:"更新内容:",//更新说明的前缀。 默认是” Description:
mandatoryContinueButtonLabel:"立即更新",//强制更新的按钮文字,默认为continue
mandatoryUpdateMessage:"",//- 强制更新时,更新通知. Defaults to “An update is available that must be installed.”.
optionalIgnoreButtonLabel: '稍后',//非强制更新时,取消按钮文字,默认是ignore
optionalInstallButtonLabel: '后台更新',//非强制更新时,确认文字. Defaults to “Install”
optionalUpdateMessage: '有新版本了,是否更新?',//非强制更新时,更新通知. Defaults to “An update is available. Would you like to install it?”.
title: '更新提示'//要显示的更新通知的标题. Defaults to “Update available”.
},
},
);
}
componentWillMount(){
CodePush.disallowRestart();//页面加载的禁止重启,在加载完了可以允许重启
}
componentDidMount(){
CodePush.allowRestart();//在加载完了可以允许重启
}
最后在styles最后添加:
App = CodePush(codePushOptions)(App);
五、修改好后把软件打包安装到手机上,直接react-native run-android也行,但是打包发布后安装到手机上这样能看的更清楚些,具体打包流程请上rn官网:http://facebook.github.io/react-native/docs/signed-apk-android.html
1、打包生成bundle文件:
首先在RN项目下面新建一个文件夹bundles:mkdir bundles,
其次运行打包命令:
react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试。
例如:
android的打包命令:
react-native bundle --platform android --entry-file index.android.js --bundle-output ./bundles/index.android.bundle --assets-dest ./bundles --dev false
ios的打包命令:
react-native bundle --platform ios --entry-file index.ios.js --bundle-output ./bundles/main.jsbundle --assets-dest ./bundles --dev false
我是把这两个平台的都打包了,然后在文件夹下面
2、发布更新:
然后需要在codepush上发布我们的更新,在终端输入:
code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName: 更新环境 --description: 更新描述 --mandatory: 是否强制更新
如下:
code-push release codepush01 ./bundles/ 1.0.0 --deploymentName Production --description "1.修改标题颜色。" --mandatory false
CodePush默认是更新 staging 环境的,如果是staging,则不需要填写 deploymentName。
如果有 mandatory 则Code Push会根据mandatory 是true或false来控制应用是否强制更新。默认情况下mandatory为false即不强制更新。
对应的应用版本(targetBinaryVersion)是指当前app的版本(对应build.gradle中设置的versionName "1.0.0"),也就是说此次更新的js/images对应的是app的那个版本。不要将其理解为这次js更新的版本。
如客户端版本是 1.0.0,那么我们对1.0.0的客户端更新js/images,targetBinaryVersion填的就是1.0.0。
说的意思就是我们手机上上的安装的版本是1.0.0,我们要更新这个版本的代码,在codepush发布更新的时间,对应的应用版本就是手机上安装的那个版本。
这个地方有点儿绕,不知道大家能不能理解,不理解的话联系我: qq和微信都是 674668211 .
可以同时对一个应用版本进行多次更新,只要传的bundle或者image不一样就行,
在终端输入下面的命令就可以查看你的应用的版本更新情况:
测试版本更新:code-push deployment history 应用名 Staging
生产版本更新:code-push deployment history 应用名 Production
我的测试版本如下:
3、我的操作如下,大家可以看下:
苹果一样的测试成功哦,这里就不贴图了,跟android一样的,
如果有人不懂的话,联系我的微信或者QQ都是674668211.
六、其他的命令:
code-push deployment add 部署
code-push deployment rename 重命名
code-push deployment rm 删除部署
code-push deployment ls 列出应用的部署情况
code-push deployment ls -k 查看部署的key
code-push deployment history 查看历史版本(Production 或者 Staging)
七、其他的一些api,强烈建议大家去查看官网,慢慢研究,根据自己的需求调整响应的api
codePush.sync(options: Object, syncStatusChangeCallback: function(syncStatus: Number), downloadProgressCallback: function(progress: DownloadProgress)): Promise<Number>;
deploymentKey (String): 部署key,指定你要查询更新的部署秘钥,默认情况下该值来自于Info.plist(Ios)和MainApplication.java(Android)文件,你可以通过设置该属性来动态查询不同部署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”.
具体可以查看我上面的代码:
还有一个是:codePush.InstallMode,有三种模式,
一个是立即启动,nstallMode.IMMEDIATE
一个是下次启动安装:InstallMode.ON_NEXT_RESTART
一个是程序在前台,并没有从后台切换到前台的情况下用的InstallMode.ON_NEXT_RESUME
八、测试:还有一个经常用的是发布的时间进行部分用户升级测试:
应用创建时有两个环境,一个是Staging,一个是Production,开发阶段用Staging,开发完成可以用code-push promote 将应用迁移到Production中。
可以对一小部分用户进行升级测试:
code-push promote 应用名 Staging Production -r 20%
软件稳定后,可以全面发布:
code-push patch 应用名 Production -r 100%