美文网首页ReactNativeiOS开发系列技术分享
react native codepush热更新解决成功更新

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

作者: liu_520 | 来源:发表于2016-11-14 16:04 被阅读9372次

            搞了两天,开始用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%

    相关文章

      网友评论

      • Arthur澪:你好,看了 你这篇文章。我 npm install -g code-push-cli安装失败,请问你成功了吗
        liu_520:@Arthur凌 http://codepush.tools/docs/getting-started.html,科学上网,获取用npm 淘宝镜像
        Arthur澪:@liu_520 这个命令执行不了
        liu_520:@Arthur凌 sudo npm install -g code-push-cli
      • 妄自:准备试试,是个好东西!!!!
      • 地平线上硝烟弥漫:你好!我想请问下打包的时候直接执行react-native bundle --platform ios --entry-file index.ios.js --bundle-output ./bundles/main.jsbundle --assets-dest ./bundles --dev false,安装更新之后报Missing request token for request:<NSMutableURLRequest:0x1234567>{URL:http://localhost:8081/assets/images/image.png?platform=ios&hash=2345sdfghjertgy}这样的错误,在bundles文件夹下的assets文件里是有这个图片文件的,图片资源在打包的时候需要做什么处理吗
        地平线上硝烟弥漫:@liu_520 好的,谢谢了。
        liu_520:重新run就会把更新过的东西覆盖了,获取的数据还是你本地的数据,不需要处理的,这个错误我也没有见过的,你查看下issues里面有没有这个问题:https://github.com/Microsoft/react-native-code-push/issues
        地平线上硝烟弥漫:只会在安装更新完会报这个错误,我重新run的话又没问题了
      • T_Y_H:楼主你好,我在执行npm install --save react-native-code-push@latest命令后 再次运行android版本 出现如下提示:
        /usr/local/bin/node /usr/local/lib/node_modules/react-native-cli run-android
        Command `run-android` unrecognized. Make sure that you have run `npm install` and that
        you are inside a react-native project.
        请问这个命令会对自身的react-native 模块产生影响嘛?
        liu_520:@T_Y_H 如果有其他的问题,你看下codepush 的issues 看看有没有解决办法
      • chensx1993::mask: 更新发布,那里有点困惑。
        iOS正常发布app,其实四种,第一种就是发布在app store,这很明显就是Production环境;
        第二种,Save for Ad Hoc Deployment ,Staging 环境?
        第三种,Save for Development Deployment,Staging 环境?
        第四种,企业包,这个忽略。
        还有我测试直接运行在真机,拔掉数据线,然后直接在电脑修改代码,手机同步更新,完成不需要控制。
        如何保证我需要时更新,不需要时更新。这让我好困惑。:cry:
        liu_520:@T_Y_H 不会的
        T_Y_H:楼主你好,我在执行npm install --save react-native-code-push@latest命令后 再次运行android版本 出现如下提示:
        /usr/local/bin/node /usr/local/lib/node_modules/react-native-cli run-android
        Command `run-android` unrecognized. Make sure that you have run `npm install` and that
        you are inside a react-native project.
        请问这个命令会对自身的react-native 模块产生影响嘛?
        liu_520:@chensx1993 你可以在检查更新时定义一个弹框的,不更新就选取消,有一个update dialog
      • 97f93e0c3c7b:楼主好~我这遇到一个问题,就是当更新后,app的性能会降低,就跟处于debug模式一样,但是导出的正式包,这个是什么情况?
        6b7363486981:@coutliu_p54 @liu_520 你好,请问你解决这个问题没,我也出现了热更新的时候有个scene会点击进不去的情况。得重启完成更新才恢复正常
        97f93e0c3c7b:已经正式环境的,ios不会,android会,也是醉
        liu_520:确定,你更新时传到code-push上的js代码是打的正式环境的包吗?
        如果是正式打包,最后面的命令要加上这个: --dev false
        react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试。
      • 丐帮头:你好,我这边按照你这个来弄的,不知道为什么更新不了?
        liu_520:@丐帮头 可以的,应该是哪个地方没配置好,加我qq:674668211
      • ebd7850242c1:更新之后如何修改版本号呢,比如我一开始是1.0.0,然后我把build.gradle中设置为1.0.1再打包,使用命令code-push release 应用名 ./bundles/ 1.0.0 --deploymentName Production --description "1.修改标题颜色。" --mandatory false更新查看应用消息还是1.0.0版本
        liu_520:@Liesbeth 就是个方法,把配置信息加到你的组件里
        ebd7850242c1:还有个问题App = CodePush(codePushOptions)(App);这一句是什么意思有什么作用,谢谢博主
        liu_520:@Liesbeth 现在假设你手机上安装的是1.0.1,要对1.0.1这个版本进行更新,那code-push 命令里面就1.0.1
      • liu_520:如果出现Sending CodePushDownloadProgress with no listeners registered.,
        需要增加以下代码:
        codePushDownloadDidProgress(progress) {
        console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
        }

        CodePush.sync({
        installMode: CodePush.InstallMode.IMMEDIATE,
        updateDialog: false,
        },null,this.codePushDownloadDidProgress.bind(this))
        }
      • liu_520:ios的打包命令原来为:react-native bundle --platform ios --entry-file index.ios.js --bundle-output ./bundles/index.ios.undle --assets-dest ./bundles --dev false。
        现在的打包命令改了,react-native bundle --platform ios --entry-file index.ios.js --bundle-output ./bundles/main.jsbundle --assets-dest ./bundles --dev false
      • 康牙123:[CodePush] Update is installed and will be run on the next app restart.这样也不行
        liu_520:@康牙123 跟网络也有关系,毕竟是从微软的服务器上取的数据,相当于翻墙吧:cry:网络可以就可以更新,网络不行就完蛋了,所以如果有条件还是自己进行拆包打包,把bundle文件上传到服务器,手机每次启动检查服务器bundle是否变化,如果有变化,后台下载bundle文件,然后在本地进行加载,就可以了,如果没条件只能用别人的了,中文网还有一个pushy 你可以看看能否成功,我最近忙的没时间研究他这个
        康牙123:@liu_520 这个设置是一样的, 查看历史版本,上面也显示有一个更新成功,那个3位的版本号也设置的是正确的,按理来说更新成功之后下次进入马上就可以看到新的界面变化啊,但是确实没有任何变动,脑仁疼
        liu_520:@康牙123 生产版本更新:code-push deployment history 应用名 Production,你看下是否更新成功,codepush到微软的时间版本要和你的软件版本一样,而且版本号必须为1.0.0或者1.2.3这样的三位数据,跟你设置的重启更新或者resume没关系
      • 康牙123:我的出现[CodePush] App is up to date.
        但是下次重启app并没有发现包变化
        5997854c43de:@Qgold12138 必须打包才能热更新吗?直接运行在手机上的不行?
        jancywen:@Qgold12138 这个签名文件以及签名配置信息指的是什么?
        8fd28ad15588:需要签名文件以及签名配置信息
      • 楚怀哲:可有 qq,详细探讨一下
        liu_520:@楚怀哲 嗯,也可以,截止目前这两个命令都可以正常使用,github上是release-react:smile:
        楚怀哲:code-push release-react zyxcp android

        代替
        ode-push release zyxcp ./bundles/ 1.0.0 --deploymentName Staging  --description "1.修改标题颜色。" --mandatory false android

        我认为是
        liu_520:@楚怀哲 674668211

      本文标题:react native codepush热更新解决成功更新

      本文链接:https://www.haomeiwen.com/subject/gafhpttx.html