美文网首页技术分享
RN热更新——codepush

RN热更新——codepush

作者: bonon | 来源:发表于2016-07-09 00:45 被阅读2368次

    一、安装注册code-push

    1.安装code-push
    $ npm install -g code-push-cli
    
    2.注册账号
    $ code-push register
    

    这时候会自动启动浏览器打开网页并提供一个codePush AccessKey,然后命令行里出现需要输入access key

    Enter your access key:
    

    输入access key�登录

    3.添加一个CodePush应用(myProject是应用名字)
    $ code-push app add �myProject
    

    出现

    ||     name    || Deployment Key ||
    || Production  || (一串37位的key) ||
    || Staging     || (一串37位的key) ||
    

    如上有两个发布键值。一个Production是对应生产环境的,二Staging是对应开发环境的。当然我们还可以添加其他的发布键值。
    这个值在后面我们集成工程里面要用到。

    二、react-native应用接入code-push

    1.安装react-native-code-push

    在项目根目录运行

    $ npm install react-native-code-push --save
    
    2.cocoapods导入code-push
    • ios

    修改Podfile文件,添加:

      pod 'CodePush', :path => './node_modules/react-native-code-push'
    

    运行

      $ pod install
    
    • android

    • RNPM
      安装 RNPM(依次运行)
      如果 React Native 版本 >= 0.27 (因为 rnpm link 已经被合并到React Native CLI)

       $ react-native link react-native-code-push
      

    否则
    $ npm i -g rnpm
    $ rnpm link react-native-code-push

    • 手动
      在android/settings.gradle文件里添加
      include ':app'
      include ':react-native-code-push'
      project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
      在android/app/build.gradle文件里添加
      dependencies {
      ...
      compile project(':react-native-code-push')
      }
      在android/app/build.gradle文件里添加
      ...
      apply from: "../../node_modules/react-native/react.gradle"
      apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
      ...
      修改MainApplication.java文件
      ...
      // 1. Import the plugin class.
      import com.microsoft.codepush.react.CodePush;

       // public class MainActivity extends ReactActivity {                                     // For React Native v0.19 - v0.28
       public class MainApplication extends Application implements ReactApplication {        // For React Native >= 0.29
      
           private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
               ...
               // 2. Override the getJSBundleFile method in order to let
               // the CodePush runtime determine where to get the JS
               // bundle location from on each app start
               @Override protected String getJSBundleFile() {
                   return CodePush.getJSBundleFile();
               }
      
               @Override protected List<ReactPackage> getPackages() {
                   // 3. Instantiate an instance of the CodePush runtime and add it to the list of
                   // existing packages, specifying the right deployment key. If you don't already
                   // have it, you can run "code-push deployment ls <appName> -k" to retrieve your key.
                   return Arrays.<ReactPackage>asList(
                       new MainReactPackage(),
                       new CodePush("deployment-key-here", MainApplication.this, BuildConfig.DEBUG)
                   );
               }
           };
       }
      

    在android/app/build.gradle文件中(应用版本codepush需要三位数)
    android{
    defaultConfig{
    versionName "1.0.0"
    }
    }
    Background React Instances
    This section is only necessary if you're explicitly launching a React Native instance without an Activity
    (for example, from within a native push notification receiver). For these situations, CodePush must be told how to find your React Native instance.*
    In order to update/restart your React Native instance, CodePush must be configured with a ReactInstanceHolder
    before attempting to restart an instance in the background. This is usually done in your Application
    implementation.
    修改MainApplication.java文件
    // For React Native >= v0.29
    ...
    // 1. Declare your ReactNativeHost to extend ReactInstanceHolder.
    // ReactInstanceHolder is a subset of ReactNativeHost, so no additional implementation is needed.
    import com.microsoft.codepush.react.ReactInstanceHolder;
    public class MyReactNativeHost extends ReactNativeHost implements ReactInstanceHolder {
    // ... usual overrides
    }
    // 2. Provide your ReactNativeHost to CodePush.
    public class MainApplication extends Application implements ReactApplication {

            private final MyReactNativeHost mReactNativeHost = new MyReactNativeHost(this);
    
            @Override public void onCreate() {
                CodePush.setReactInstanceHolder(mReactNativeHost);
                super.onCreate();
            }
        }
    
        // For React Native v0.19 - v0.28
        // 1. Provide your ReactNativeHost to CodePush.
        public class MainApplication extends Application {
            // ... initialize your instance holder
            @Override public void onCreate() {
                CodePush.setReactInstanceHolder(mReactNativeHost);
                super.onCreate();
            }
        }
    

    以上的操作,即可成功集成CodePush。

    3.配置相关文件
    • IOS
    1.修改js程序入口文件

    RN应用是appDelegate.m
    原生应用是ReactView.m

      #ifdef DEBUG
          jsCodeLocation = [NSURL URLWithString:@"http://192.168.1.103:8081/index.ios.bundle?platform=ios"];
      #else
          jsCodeLocation = [CodePush bundleURLForResource:@"index"];
      #endif
    
    2.修改info.plist文件
      <key>CodePushDeploymentKey</key>
      <string>前面添加应用得到的发布key(注意这里要选择是正式版的key还是测试版的key,不是发布到appstore可以用Staging的key)</string>
    

    命令行里面输入

    $ code-push
    

    可以看到code-push各个命令

    三、更新策略(js)

    1、导入react-native-code-push

    import codePush from "react-native-code-push";
    

    2、策略

    默认情况下,CodePush会在app每次启动的时候去检测是否有更新,如果有,app会自动下载并在下次打开app时安装

    class MyApp extends Component {}
    MyApp = codePush(MyApp);
    
    // For ES7
    import codePush from "react-native-code-push";
    
    @codePush
    class MyApp extends Component {}
    

    每次打开app时检测更新并下载,下次打开app时安装

    // Sync for updates everytime the app resumes.
    class MyApp extends Component {}
    MyApp = codePush({
        checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
        installMode: codePush.InstallMode.ON_NEXT_RESUME
    })(MyApp);
    

    实时检测更新并下载,下载完成后立即安装

    // Active update, which lets the end user know
    // about each update, and displays it to them
    // immediately after downloading it
    class MyApp extends Component {}
    MyApp = codePush({
        updateDialog: true,
        installMode: codePush.InstallMode.IMMEDIATE
    })(MyApp);
    

    记录app检测、下载、安装的状态(可以实现进度条当做友好提示)

    // Make use of the event hooks to keep track of
    // the different stages of the sync process.
    class MyApp extends Component {
        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:
                    console.log("Installing update.");
                    break;
                case codePush.SyncStatus.UP_TO_DATE:
                    console.log("Installing update.");
                    break;
                case codePush.SyncStatus.UPDATE_INSTALLED:
                    console.log("Update installed.");
                    break;
            }
        }
        codePushDownloadDidProgress(progress) {
            console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
        }
    }
    MyApp = codePush(MyApp);
    
    CodePushOptions
    • checkFrequency (codePush.CheckFrequency) - 检测更新的时机
    方法 描述
    ON_APP_START(0) app启动后
    ON_APP_RESUME(1) app从后台切换过来时
    ON_APP_MANUAL(2) 不能自动检测,只有在调用 codePush.sync()时触发
    • deploymentKey (String) - 部署key,可以在js里动态修改
    • installMode (codePush.InstallMode) - 安装时机
    方法 描述
    IMMEDIATE(0) 立即安装并重启app
    ON_NEXT_RESTART(1) 下次启动app时安装
    ON_NEXT_RESUME(2) app从后台切换过来时安装
    • mandatoryInstallMode (codePush.InstallMode) - 同codePush.InstallMode.IMMEDIATE
    • minimumBackgroundDuration (Number) - app在后台切换过来安装的最小秒数,配合installMode.ON_NEXT_RESUME使用
    • updateDialog (UpdateDialogOptions) - 对话框
    属性 描述
    appendReleaseDescription(Boolean) 是否发送通知消息显示给用户,默认为false
    descriptionPrefix(String) 描述的前缀,默认为“Description:”
    mandatoryContinueButtonLabel(String) 强制更新下的继续按钮的文本,默认为“Continue”
    mandatoryUpdateMessage(String) 强制更新的通知消息文本,默认为“An update is available that must be installed.”
    optionalIgnoreButtonLabel(String) 忽略按钮的文本,默认为“Ignore”
    optionalUpdateMessage(String) 通知消息文本,默认为“An update is available. Would you like to install it?”
    title(String) 对话框的标题,默认为“Update available”
    optionalUpdateMessage 通知消息文本

    codePushStatusDidChange

    用于监听检测、下载、安装的状态——SyncStatus

    方法 描述
    CHECKING_FOR_UPDATE (0) 查询更新
    AWAITING_USER_ACTION (1) 有更新并且有对话框显示给最终用户(这只是适用updateDialog时使用)
    DOWNLOADING_PACKAGE (2) 正在下载
    INSTALLING_UPDATE (3) 正在安装
    UP_TO_DATE (4) 更新完成
    UPDATE_IGNORED (5) 提示更新后,用户选择了忽视(这只是适用updateDialog时使用)
    UPDATE_INSTALLED (6) 已经安装,并将运行syncStatusChangedCallback函数返回后立即或下次启动更新,在InstallMode SyncOptions中指定。
    SYNC_IN_PROGRESS (7) 有一个正在进行的同步操作运行,防止当前的调用被执行。
    UNKNOWN_ERROR (-1) 同步操作遇到了一个未知错误。

    codePushDownloadDidProgress

    下载进度

    返回参数 描述
    totalBytes (number) 预计大小
    receivedBytes(number) 已下载大小

    disallowRestart/allowRestart

    class OnboardingProcess extends Component {
      ...
      componentWillMount() {
        // Ensure that any CodePush updates which are
        // synchronized in the background can't trigger
        // a restart while this component is mounted. codePush.disallowRestart();
      }
      componentWillUnmount() {
        // Reallow restarts, and optionally trigger
        // a restart if one was currently pending.
        codePush.allowRestart();
      }
      ...
    }
    

    四、发布版本

    1、打包
    $ code-push release myProject ./bundle/index.jsbundle 1.20.1 --mandatory true
    

    myProject代表我们要更新的项目名称,就是前面我们注册的index.jsbundle是我们要更新的内容,1.20.1是我们在appstore发布的版本号,注意这个地方是我们程序二进制文件的版本号,其实这句命令就是:更新myProject 1.20.1的版本二进制文件,只有1.20.1的版本才能收到更新。最后面的参数是是否强制更新。这段命令没有指定更新的环境是正式环境还是测试环境,默认的是测试环境,如果要发布到正式环境需要指定一下

     code-push release wanna ./bundle/index.jsbundle 1.20.1 -d "Production" --mandatory true。 
    

    后面还可以在后面添加参数比如1.20.1版本的多少用户可以更新–rollout 20,代表百分之20的myProject 1.20.1的用户可以收到这个更新

    2、修改发布后版本的参数

    比如上面,我们发布更新到了1.20.1的测试版本,更新百分之20的用户,可是我们发布完成之后,想更新百分之30的用户:

    $ code-push patch wanna 1.20.1 --rollout 20
    

    code-push for redux -- react-native-code-push-saga

    注意:

    • 苹果不允许应用内有弹框提示更新

    相关文章

      网友评论

        本文标题:RN热更新——codepush

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