×

react native codepush热更新解决成功更新

96
liu_520
2016.11.14 16:04* 字数 2979

        搞了两天,开始用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,打开了一个网页选择授权的账号。如下所示


注册codepush账号

2、我选的是github,这样的话会出来一个界面,把那个key复制下,并在终端复制下这个key,注册成功。


接入codepush账号的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

查询你的内容如下:

Deployment Key

Staging 为测试的key,Production为生产打包时用的key。

然后按照下图配置ios的东西就行了


修改version为三位数


修改version和deploymentkey

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

我是把这两个平台的都打包了,然后在文件夹下面


打包bundle

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、我的操作如下,大家可以看下:


打包-发布


更新前


codepush有更新,检测到更新,直接更新就可以了


苹果一样的测试成功哦,这里就不贴图了,跟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%

react native
Web note ad 1