React Native应用部署/热更新/常见问题-CodePush最新集成总结

什么是CodePush

CodePush是一个微软开发的云服务器。通过它,开发者可以直接在用户的设备上部署手机应用更新。CodePush相当于一个中心仓库,开发者可以推送当前的更新(包括JS/HTML/CSS/IMAGE等)到CoduPush,然后应用将会查询是否有更新。

接入流程

  • 安装 CodePush CLI
  • 注册 CodePush账号
  • 在CodePush服务器注册App
  • RN代码中集成CodePush
  • 原生应用中配置CodePush
  • 发布更新的版本

1. 安装 CodePush CLI

安装CodePush指令,直接在终端上输入如下命令即可,注意:这个CodePush指令只需要全局安装一次即可,如果第一次安装成功了,那后面就不在需要安装

npm install -g code-push-cli
image.png

2、注册 CodePush账号

注册CodePush账号也很简单,同样是只需简单的执行下面的命令,同样这个注册操作也是全局只需要注册一次即可

code-push register

注意:当执行完上面的命令后,会自动打开一个授权网页,让你选择使用哪种方式进行授权登录,这里我们统一就选择使用GitHub即可

image.png

当注册成功后,CodePush会给我们一个key



我们直接复制这个key,然后在终端中将这个key填写进去即可,填写key登录成功显示效果如下


image.png

我们使用下面的命令来验证我的登录是否成功
code-push login
image.png

CodePush注册登录相关命令

  • code-push login 登陆
  • code-push loout 注销
  • code-push access-key ls 列出登陆的token
  • code-push access-key rm <accessKye> 删除某个 access-key

3、在CodePush服务器注册App

为了让CodePush服务器有我们的App,我们需要CodePush注册App,输入下面命令即可完成注册,这里需要注意如果我们的应用分为iOS和Android两个平台,这时我们需要分别注册两套key
应用添加成功后就会返回对应的productionStaging 两个key,production代表生产版的热更新部署,Staging代表开发版的热更新部署,在ios中将staging的部署key复制在info.plist的CodePushDeploymentKey值中,在android中复制在Application的getPackages的CodePush中

添加iOS平台应用

code-push app add iOSrn_app ios react-native

image.png

添加Android平台应用

code-push app add Androidrn_app Android react-native
image.png

我们可以输入如下命令来查看我们刚刚添加的App

code-push app list
image.png

CodePush管理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的所有权转移到另外一个账号
  • code-push release-react <appName> <platform> -t 版本 -d 环境 --des 描述 -m true (强制更新)// 发布
  • code-push deployment clear <appName> Production or Staging // 清除历史部署记录
  • code-push rollback <appName> Production --targetRelease v4(codepush服务部署的版本号) // 回滚

// 应用信息相关

  • code-push deployment add <appName> 部署
  • code-push deployment rm <appName> 删除部署
  • code-push deployment rename <appName> 重命名
  • code-push deployment ls <appName> 列出应用的部署情况
  • code-push deployment ls <appName> -k 查看部署的key
  • code-push deployment history <appName> <deploymentName> 查看历史版本

4、RN代码中集成CodePush

首先我们需要安装CodeoPush组件,然后通过link命令添加原生依赖,最后在RN根组件中添加热更新逻辑代码
安装组件

npm install react-native-code-push --save
image.png

添加原生依赖,这里添加依赖我们使用自动添加依赖的方式(RN0.60版本以上的 cli里集成了AutoLink,不用手动link资源了)

react-native link react-native-code-push
image.png

我们在RN项目的根组件(例如App.js)中添加热更新逻辑代码如下

~
import codePush from "react-native-code-push";
const codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };
export default class App extends Component<{}> {

  componentDidMount(){
    codePush.sync({
      updateDialog: true,
      installMode: codePush.InstallMode.IMMEDIATE,
      mandatoryInstallMode:codePush.InstallMode.IMMEDIATE,
      //deploymentKey为刚才生成的,用Platform判断下平台(填写你自己的)
      deploymentKey: Platform.OS === 'ios'?'sYvpLUxuBU9FxICqJ5sccL2GDUPZcc988a73-c917-4dba-bd40-1837998442a6':'fqdFCqLyL4XclNZjWvNN3KNhImR5cc988a73-c917-4dba-bd40-1837998442a6',
      });
  }
~

5,模拟器上运行项目

react-native run-ios
react-native run-android

5.1 如图下所显打包过程中可能遇到的\color{red}{报错}

image.png

错误发生在java编译器执行过程中
image.png

image.png

看到出来是刚刚引入的Code-Push包,实例化的时候getString方法获取我们之前的DeploymentKey失败.
getString是android 开发中Context类上的一个获取字符串的方法,在RN中会从根目录下/android/app/src/main/res/values/strings.xml文件中获取值。

我们打开strings.xml文件后添加这样一行代码:

<string moduleConfig="true" name="CodePushDeploymentKey"><string moduleConfig="true" name="CodePushDeploymentKey">xxxxxxx你刚刚注册DeploymentKey</string></string>

例如

image.png

再次react-native run-android即可成功运行

6. deployment-key的设置与获取bundle路径 (关于Grande

  • 在上述代码中我们在创建CodePush实例的时候需要设置一个deployment-key,因为deployment-key分生产环境与测试环境两种,所以建议大家在build.gradle中进行设置。在build.gradle中的设置方法如下:
    打开android/app/build.gradle文件,找到android { buildTypes {} }然后添加如下代码即可:
buildTypes {
    release {
        minifyEnabled enableProguardInReleaseBuilds
        proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        signingConfig signingConfigs.config
       + buildConfigField "String", "CODE_PUSH_KEY", CODE_PUSH_KEY_PRODUCTION
       + buildConfigField "boolean", "IS_CODE_PUSH", "true"
    }
    debug {
       + buildConfigField "String", "CODE_PUSH_KEY", CODE_PUSH_KEY_STAGING
       + buildConfigField "boolean", "IS_CODE_PUSH", "true"
    }
}

心得:另外,我们也可以将deployment-key存放在gradle.properties中:

CODE_PUSH_KEY_PRODUCTION="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
CODE_PUSH_KEY_STAGING="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
image.png
在android/app/build.gradle设置好deployment-key之后呢,我们就可以这样使用了:

MainApplication.java下的ReactNativeHost方法中添加

@Override
protected String getJSBundleFile() {
    // gradlew assembleRelease会把所有用到的JavaScript代码都打包内置到APK中
    if (BuildConfig.IS_CODE_PUSH) {
        return CodePush.getJSBundleFile(); // code-push热更新
    }
    //return UpdateContext.getBundleUrl(MainApplication.this); // pushy热更新
} 

7.修改versionName和引入code-push设置。

在 android/app/build.gradle中有个 android.defaultConfig.versionName属性,我们需要把 应用版本改成 1.0.0(默认是1.0,但是codepush需要三位数)。

android{
    defaultConfig{
        versionName "1.0.0"
    }
}
//文件最下方
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"  

\android\app\src\main\java\com\ysty_app3\MainApplication.java添加包

import com.microsoft.codepush.react.CodePush;

至此Code Push for Android的SDK已经集成完成。

8、发布更新的版本

在使用之前需要考虑的是检查更新时机,更新是否强制,更新是否要求即时等

更新时机

一般常见的应用内更新时机分为两种,一种是打开App就检查更新,一种是放在设置界面让用户主动检查更新并安装

  • 打开APP就检查更新
    最为简单的使用方式在React Natvie的根组件的componentDidMount方法中通过
    codePush.sync()(需要先导入codePush包:import codePush from 'react-native-code-push')方法检查并安装更新,如果有更新包可供下载则会在重启后生效。不过这种下载和安装都是静默的,即用户不可见。如果需要用户可见则需要额外的配置。具体可以参考codePush官方API文档,部分代码,完整代码请参照文档上面
 codePush.sync({
      updateDialog: true,//code-push 接管更新
      installMode: codePush.InstallMode.IMMEDIATE,
      mandatoryInstallMode:codePush.InstallMode.IMMEDIATE,
      //deploymentKey为刚才生成的,用Platform判断下平台
      deploymentKey: Platform.OS === 'ios'?'IOSKey':'andoridKey',
      });

上面的配置在检查更新时会弹出提示对话框, mandatoryInstallMode表示强制更新,

  • 用户点击检查更新按钮
    在用户点击检查更新按钮后进行检查,如果有更新则弹出提示框让用户选择是否更新,如果用户点击立即更新按钮,则会进行安装包的下载(实际上这时候应该显示下载进度,这里省略了)下载完成后会立即重启并生效(也可配置稍后重启),部分代码如下
codePush.checkForUpdate(deploymentKey).then((update) => {
    if (!update) {
        Alert.alert("提示", "已是最新版本--", [
            {
                text: "Ok", onPress: () => {
                console.log("点了OK");
            }
            }
        ]);
    } else {
        codePush.sync({
                deploymentKey: deploymentKey,
                updateDialog: {
                    optionalIgnoreButtonLabel: '稍后',
                    optionalInstallButtonLabel: '立即更新',
                    optionalUpdateMessage: '有新版本了,是否更新?',
                    title: '更新提示'
                },
                installMode: codePush.InstallMode.IMMEDIATE,

            },
            (status) => {
                switch (status) {
                    case codePush.SyncStatus.DOWNLOADING_PACKAGE:
                        console.log("DOWNLOADING_PACKAGE");
                        break;
                    case codePush.SyncStatus.INSTALLING_UPDATE:
                        console.log(" INSTALLING_UPDATE");
                        break;
                }
            },
            (progress) => {
                console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
            }
        );
    }
 }

更新是否要求即时
在更新配置中通过指定installMode来决定安装完成的重启时机,亦即更新生效时机

  • codePush.InstallMode.IMMEDIATE :安装完成立即重启更新

  • codePush.InstallMode.ON_NEXT_RESTART :安装完成后会在下次重启后进行更新

  • codePush.InstallMode.ON_NEXT_RESUME :安装完成后会在应用进入后台后重启更新

    如何发布CodePush更新包

工程根目录新增 bundles文件夹:

mkdir bundles

1.自动生成bundles文件发布:

code-push release-react 《app名称》《平台》 -t 《版本号》 -d Production --des "描述" -m true
例如
code-push release-react weather android --t 1.0.0 -d Production --dev false --des "1.优化操作流程,2.我裂开" --m false

2.手动生成bundles文件发布, 首先在根目录创建bundles文件夹(每次重新生成文件时需删除上次的文件)

  • 单js文件
1. 创建bundles里的文件
打包命令
react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试 

打包整个项目的js文件,例如: 
react-native bundle --platform android --entry-file index.js --bundle-output ./bundles/index.android.bundle --dev false

2. 发布更新
发布命令: 
code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName 更新环境 --description 更新描述 --mandatory 是否强制更新

例如:
code-push release CodePushDemo-android ./bundles/index.android.bundle 1.0.0 --deploymentName Production --description "热更新" --mandatory true
  • js文件+图片资源,–assets-dest 后就是放图片的文件夹路径
打包命令:–assets-dest 后就是放图片的文件夹路径
react-native bundle --platform android --entry-file index.js --bundle-output ./bundles/index.android.bundle --assets-dest ./bundles --dev false

发布bundles文件:
code-push <release/debug> <projectName(与注册的app同名)><bundle文件名> <版本号> --deploymentName 更新环境 --description 更新描述 --mandatory 是否强制更新
例如:
code-push release CodePushDemo-android ./bundles 1.0.0  //省略默认是发布Staging
code-push release CodePushDemo-android ./bundles 1.0.0 -d Production --des "热更新" --mandatory true

需要注意的是:

  • 输出的bundle文件名不叫其他,而是 index.android.bundle,是因为 在debug模式下,
    工程读取的bundle就是叫做 index.android.bundle。
  • 平台可以选择 android 或者 ios。

查看发布信息

查看已add appName
code-push app list 
查看部署的历史版本信息
code-push deployment ls CodePushDemo-android -k

9,自定义更新窗口

我们再次打开 app是就可以看到,code-push弹出的 更新提示弹框

image.png

这是code-push提供的弹窗,如果需要自定义文字

修改更新弹出框内容
进入node_modules->react-native-code-push->Codepush.js修改以下内容

image.png

需要更多自定义设置参考https://blog.csdn.net/weixin_42613755/article/details/104964557

可能出现的问题(react-native run-android)
  1. What went wrong:
    Execution failed for task ':app:mergeDebugResources'.
    Could not read path 'E:\cli3\weather2\android\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values'.
    cd android 执行 gradlew clean解决
  2. [Error:Execution failed for task ':app:transformClassesWithDexForDebug]

在项目android/app/build.gradle下添加

 defaultConfig {
        ...
        multiDexEnabled true
}

本片内容借鉴至https://segmentfault.com/a/1190000016273902?utm_source=tag-newest
可访问 查阅关于ios端的热更新

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容