React Native发布——使用AppCenter

前言

本文基于React Native开发环境搭建,默认已搭建好XXProject的react native项目。本文appcenter cli版本为2.10.0,本文法布时,coderova已停用,codepush已被弃用,因此直接使用更加傻瓜式接入的appcenter cli。本文基于react版本17.0.2、react-native版本0.67.3,使用mac开发。

AppCenter配置

XXProject根目录下执行

npm install -g appcenter-cli

安装appcenter cli,然后再运行

appcenter login

即可调起App Center网页,新建账户(此处不再赘述)结束后,页面会生成新的API token
React Native发布——使用AppCenter_第1张图片将token复制后粘贴到刚才输入appcenter login的终端,按enter后即刻登陆App Center应用页面以及运行cli命令,如果不是centeros等无gui系统的话,建议使用网页新增应用以及配置管理,比使用命令方便很多。
本文只讨论使用AppCenter接入React Native,首先新建App:
在这里插入图片描述
React Native发布——使用AppCenter_第2张图片
需要注意,rn产出的android包与ios包一般都是有区别的,因此需要新建两个app,一般默认命名都是类似于XXProject-Android,XXProject-IOS,如果不使用网页新建,则对应新建项目命令为

appcenter apps create -p React-Native -o Android -d XXProject-Android -r Production -n xxproject-android-url-name --description 'Android示例项目' 

appcenter apps create --platform React-Native --os iOS --display-name XXProject-IOS --release-type Production --name xxproject-ios-url-name --description 'IOS示例项目' 

特别注意,-d只是显示的名称,后续命令中的项目是用的是-n指定的,一般使用-d即可,默认同名。所有的cli详细命令可参见1,如不熟悉命令,可在appcenter相应命令后使用 --help查看详细说明。
在appcenter分别建立Android与ios项目后,在XXProject根目录中使用以下命令中集成CodePush:

npm install --save react-native-code-push

使用Codepush

点击按钮创建默认的两个发布环境:预发布环境Staging,与生产环境Production:
React Native发布——使用AppCenter_第3张图片
请特别注意,一般正式项目流程是直接使用上一篇中的yarn acd命令进行开发与调试,不需要打出bundle包,以方便开发,在交付给测试时,使用预发布环境Staging并打出Staging的离线bundle集成到app,测试通过后使用生产环境Production。
以上创建发布环境如需要使用命令,则先查看现有app:

appcenter apps list  

拷贝对应项目,分别执行新建部署:

appcenter codepush deployment add -a name/xxproject-android-url-name Staging
appcenter codepush deployment add -a name/xxproject-android-url-name Production

IOS项目部署创建也是相同的操作。

Android接入

  1. 在XXProject/android/settings.gradle 文件末尾,添加:
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
  1. 在XXProject/android/app/build.gradle中添加:
// 上一篇集成rn时已经引入,无需重复引入
// apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
  1. 在上篇的Application类中的添加方法:
// 1. Import the plugin class.
import com.microsoft.codepush.react.CodePush
...
class MainApplication : Application(), ReactApplication {
	override fun onCreate() {
	      CodePush.setReactInstanceHolder(mReactNativeHost)
	      super.onCreate()
	      ...
	   }
	   
    override fun getReactNativeHost() = mReactNativeHost

    private val mReactNativeHost: CodePushReactNativeHost = CodePushReactNativeHost(this)
 
    inner class CodePushReactNativeHost(appContext: Application) : ReactNativeHost(this),
        ReactInstanceHolder {
        override fun getUseDeveloperSupport(): Boolean {
            return BuildConfig.DEBUG
        }

        // Override the getJSBundleFile method to let
        // the CodePush runtime determine where to get the JS
        // bundle location from on each app start
        override fun getJSBundleFile(): String? {
            return CodePush.getJSBundleFile()
        }

        override fun getPackages(): List<ReactPackage> {
            // Packages that cannot be autolinked yet can be added manually here, for example:
            // packages.add(new MyReactNativePackage());
            // 比如rn桥接
            return PackageList(this).packages
        }

        override fun getJSMainModuleName(): String {
            return "index"
        }
    }
}
  1. 使用命令
appcenter codepush deployment list -a ownername/XXProject-Android -k

获取部署key如下图:
在这里插入图片描述
将所需部署环境的key放到strings.xml:

 <resources>
     ...
     <string moduleConfig="true" name="CodePushDeploymentKey">DeploymentKeystring>
 resources>

注意,部署key的环境需要与以下部署命令的一致,XXProject中,默认debug版使用Staging,release版使用Production(一般还需要一个预发布环境,此处测试项目就省略了,正式项目务必需要三个环境)。
更推荐的做法,是不使用strings.xml定义,而将key使用gradle配置:

android {
    ...
    buildTypes {
        debug {
            ...
            // CodePush更新不应在开发时使用,因为codepush会覆盖rn开发包。但是CodePush sdk会在所有模式下都去检查更新,因此需要提供key。XXProject中,直接使用Staging环境的key
            resValue "string", "CodePushDeploymentKey", '""'
            ...
        }
        releaseStaging {
            ...
            // 预发布环境Staging的key,XXProject由于历史原因,直接使用了debug
            resValue "string", "CodePushDeploymentKey", '""'
            // matchingFallbacks表示找不到的依赖使用release类似配置,https://www.jianshu.com/p/7e2d0e59a2bb
            matchingFallbacks = ['release']
            ...
        }
        release {
            ... 
            // 正式环境Production的key
            resValue "string", "CodePushDeploymentKey", '""'
            ...
        }
    }
    ...
}
  1. 可选项,安装Appcenter Analytics与Appcenter Crashes,此处不赘述,需要的可自行参考。

IOS接入

  1. XXProject根目录执行命令安装依赖:
cd ios && pod install && cd ..

未完待续

React Native配置

接入Android与IOS原生SDK后,需要配置react native以确定codepush更新检查与安装时机。

主模块接入codepush

const codePushOptions = {
  //设置检查更新的频率
  //ON_APP_RESUME APP恢复到前台的时候
  //ON_APP_START APP开启的时候
  //MANUAL 手动检查
  checkFrequency: CodePush.CheckFrequency.ON_APP_START
};
var that = null
class RNAPP extends Component {
	...
}

App = CodePush(codePushOptions)(RNAPP)
export default App

codePushOptions可以不传,默认行为为app启动时检查更新,有更新时静默下载,并在再次冷启动时安装更新。codePushOptions详细介绍此处不赘述,有两个是常用的:

  • checkFrequency:检查更新的时机,
  1. 默认为CodePush.CheckFrequency.ON_APP_START,app冷启动时;
  2. CodePush.CheckFrequency.ON_APP_RESUME,app回到前台时,如home键、跳到别的app再回来时;
  3. CodePush.CheckFrequency.MANUAL,不自动检查更新,需要使用codePush.sync()手动检查。特别注意,手动模式时,如果调用codePush检查更新(checkForUpdate)的时机不是在app start时,必须在加载前notifyAppReady以防止更新重启之后jsbundle回滚:
class RNAPP extends Component {
  ...
  componentWillMount() {
    // 更新重启之后,防止回滚
    CodePush.notifyAppReady()
  }
  • installMode:应用更新的时机,
  1. 默认为codePush.InstallMode.ON_NEXT_RESTART, 下次冷启动时应用更新;
  2. codePush.InstallMode.ON_NEXT_RESUME ,app回到前台时应用更新;
  3. codePush.InstallMode.ON_NEXT_SUSPEND ,页面退到后台minimumBackgroundDuration(默认0)秒后,再次回到前台时应用更新;
  4. codePush.InstallMode.IMMEDIATE ,检查到更新后,立即应用更新。

自定义更新时机

如果业务需求在有更新时,弹窗提示更新,就需要用到两个常用的函数CodePush.checkForUpdate和CodePush.sync:

class RNAPP extends Component {
  ...
  const codePushOptions = {
	// 设置检查更新的频率
    // ON_APP_RESUME APP恢复到前台的时候
    // ON_APP_START APP开启的时候
    // MANUAL 手动检查
    // 1、设定为手动更新
	checkFrequency: CodePush.CheckFrequency.MANUAL
  };

  syncCodePush() {
    // 3、应用更新
    CodePush.sync({
      // 安装模式
      // ON_NEXT_RESUME 下次恢复到前台时
      // ON_NEXT_RESTART 下一次重启时
      // IMMEDIATE 马上更新
      installMode: CodePush.InstallMode.IMMEDIATE,
      // 后台30秒以上才更新
      // minimumBackgroundDuration: 30
      // 不要使用原生对话框!!!!,需要的话自行配置,2022/3/9新版android codepush源码CodePushDialog直接在非主线程mqt_native_modules上show
      // updateDialog:true
    });
  }

  componentWillMount() {
    // 更新重启之后,防止回滚
    CodePush.notifyAppReady();
    // 在加载完了可以允许重启
    CodePush.disallowRestart();
  }

  componentDidMount() {
    that = this
    //在加载完了可以允许重启
    CodePush.allowRestart();
    // 2、检查是否有更新
    CodePush.checkForUpdate().then((update)=>{
      if(!update){
        console.log("The app is up to date!");
      } else {
        // 自定义弹窗提示新版本,或其他操作,此处省略 
        that.syncCodePush()
      }
    });
  }
  ...
}
  • CodePush.checkForUpdate(deploymentKey: String = null, handleBinaryVersionMismatchCallback: (update: RemotePackage) => void): Promise
  1. 参数deploymentKey可以指定检测不同的发布环境key,可用于实现灵活配置付费版等功能的更新;
  2. 参数handleBinaryVersionMismatchCallback,处理更新版本返回,比如现在app的jsb版本是1.0.0,但是查询到新的jsb更新是1.0.1版本的,此回调可做此类可选项处理
  3. 返回的Promise函数null时,无更新或更新对当前版本app不可用,否则返回RemotePackage对象:
    downloadUrl——包可供下载的 URL;
    download (downloadProgressCallback?: Function) : Promise——下载更新,downloadProgressCallback用于回调进度,返回LocalPackage的Promise用于安装。
  • CodePush.sync(options?: SyncOptions, syncStatusChangedCallback?: SyncStatusChangedCallback, downloadProgressCallback?: DownloadProgressCallback, handleBinaryVersionMismatchCallback?: HandleBinaryVersionMismatchCallback): Promise;
    非常建议细看codePush.sync文档,内容较多且比较重要,此处不再展开。

发布与更新包

以上步骤走完,rn就可以”热更“了。根据上一篇文章操作,离线包已被打进app里,此时随意修改App.js的显示,保存后,使用命令发布更新:

appcenter codepush release-react -a ownername/xxproject-android-url-name -d Staging -t 0.0.1

即可在0.0.1版本的Android app上更新rn页面。同样强烈建议通读发布更新命令参数详解。

参考资料


  1. appcenter-cli仓库
    React Native客户端 SDK
    React Native 客户端 SDK API 参考
    使用CLI发布codepush更新 ↩︎

你可能感兴趣的:(react,native,react.js,javascript)