React Native 实现热更新并自动签名打包

项目背景:手动link的安卓App,react-native: 0.62.2 ;react-native-code-push: 6.2.0

1.下载 react-native-code-push

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

2.在android/settings.gradle文件下新增:

include ':app', ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')

3.在android\app\src\main\java\com\app\MainApplication.java 文件中修改

...
// 1. Import the plugin class.
import com.microsoft.codepush.react.CodePush;

public class MainApplication extends Application implements ReactApplication {

    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();
        }
    //手动link需要修改的地方,自动link应该不需要改
            @Override
    protected List getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for
      // example:
      // packages.add(new MyReactNativePackage());
      packages.add(new CodePush(getResources().getString(R.string.CodePushDeploymentKey),
          getApplicationContext(), BuildConfig.DEBUG,
          getResources().getString(R.string.reactNativeCodePush_androidServerURL)));
      return packages;
    }
    };
}

//CodePushDeploymentKey对应string.xml里面的 Deployment key的name
//reactNativeCodePush_androidServerURL对应string.xml里面热更新服务地址的name

4.string.xml的修改:首先要将你的app添加到推送中心,并获取你需要的环境分支的key

全局安装code-push:  npm i -g code-push-cli 

4.1.登录热更新服务器  

 4.2.推送中心创建项目:(针对第一次部署)

         code-push app add 项目名称 android react-native

4.3 添加环境分支dev:code-push deployment add 项目名称 dev (针对第一次部署)

 

 

将项目打包至对应的环境分支,需要将环境分支对应的key和热更新地址配置到项目文件中:(strings.xml)

4.4 准备工作已经做好了,现在我们来修改string.xml文件吧


    app
    你需要推送代码的环境分支的key
     http://热更新服务地址

 

 

5.修改android/app/build.gradle文件

...
apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
...

dependencies {
    implementation project(':react-native-code-push') //最好手动加上,否则可能会有坑
    implementation fileTree(dir: "libs", include: ["*.jar"])
    ....
}
....

采坑:react-native-code-push需要手动添加依赖,否则会报错:

  STACK TRACE AND/OR SCREENSHOTS

:app:compileDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:6: error: package com.microsoft.codepush.react does not exist
import com.microsoft.codepush.react.CodePush;
                                   ^
C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:23: error: cannot find symbol
        return CodePush.getJSBundleFile();
               ^
  symbol: variable CodePush
C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:35: error: cannot find symbol
            new CodePush(null, getApplicationContext(), BuildConfig.DEBUG),
                ^
  symbol: class CodePush
3 errors
:app:compileDebugJavaWithJavac FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.

 

6.采坑:手动link react-native-code-push的app,需要禁止autolink,否则会报错:

java.lang.IllegalStateException: Native module CodePush tried to override CodePushNativeModule. Check the getPackages() method in MainApplication.java, it might be that module is being created twice. If this was your intention, set canOverrideExistingModule=true

所以需要加上一个配置文件,禁止自动link

在项目根目录创建react-native.config.js文件

module.exports = {
    dependencies: {
        'react-native-code-push': {
            platforms: {
                android: null, // disable Android platform, other platforms will still autolink
            },
        },
    },
};

7.热更新配置完成,现在我们需要在项目启动的时候检测热更新,并提示

在项目入口文件App.js中:

import React,{ Component } from 'react';
import Root from './src/inner';
import configureStore from './src/inner/store';
import UpdateDialog from './src/common/components/updateDialog'
import CodePush from "react-native-code-push";

const { persistor, store } = configureStore();


class App extends Component {

  state = {

    visitDialog: false,
    current: 0,
    total: 100
  }



  componentDidMount() {
    CodePush.sync({
      //安装模式
      //ON_NEXT_RESUME 下次恢复到前台时
      //ON_NEXT_RESTART 下一次重启时
      //IMMEDIATE 马上更新
      installMode: CodePush.InstallMode.IMMEDIATE,
      //对话框
      updateDialog: {
        //是否显示更新描述
        appendReleaseDescription: true,
        //更新描述的前缀。 默认为"Description"
        descriptionPrefix: "更新内容:",
        //强制更新按钮文字,默认为continue
        mandatoryContinueButtonLabel: "立即更新",
        //强制更新时的信息. 默认为"An update is available that must be installed."
        mandatoryUpdateMessage: "必须更新后才能使用",
        //非强制更新时,按钮文字,默认为"ignore"
        optionalIgnoreButtonLabel: '稍后',
        //非强制更新时,确认按钮文字. 默认为"Install"
        optionalInstallButtonLabel: '后台更新',
        //非强制更新时,检查到更新的消息文本
        optionalUpdateMessage: '有新版本了,是否更新?',
        //Alert窗口的标题
        title: '更新提示'
      },
    },
      (status) => {
        console.log(status, 'status')
        if (status == 7) {
          this.setState({ visitDialog: true })
        }
      },
      (progress) => {
        let receivedBytes = progress.receivedBytes / 1024 / 1024;
        let totalBytes = progress.totalBytes / 1024 / 1024;
        this.setState({
          current: receivedBytes,
          total: totalBytes
        })
        if (receivedBytes === totalBytes) {
          setTimeout(() => {
            this.setState({ visitDialog: false })
          }, 1000)
        }
        console.log(progress, 'progress')
      }
    );
  }

  render() {
    console.log(this.state.visitDialog, 'visitDialog');
    return (
      <>
        
        {this.state.visitDialog && }
      
    )
  }
};

let codePushOptions = {
  //设置检查更新的频率
  //ON_APP_RESUME APP恢复到前台的时候
  //ON_APP_START APP开启的时候
  //MANUAL 手动检查
  checkFrequency: CodePush.CheckFrequency.ON_APP_START
};

export default CodePush(codePushOptions)(App);

UpdateDialog :是我自己封装的热更新下载进度条的组件,下载提示,可根据自己的心情随便写,这里我就不贴自己的代码了!(写的不好,不好意思)

现在我们热更新配置好了,打包正式的apk吧!

1. 生成签名文件:在项目根目录下运行命令:

keytool -genkey -v -keystore 我的签名-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias 我的签名

2.将生成的签名文件拷贝至目录:android/app目录下

3.配置gradle.properties

android.useAndroidX=true
android.enableJetifier=true
MYAPP_RELEASE_STORE_FILE=wms-app-key.jks  //生成的签名密钥
MYAPP_RELEASE_KEY_ALIAS=ydh //别名
MYAPP_RELEASE_STORE_PASSWORD=签名时设置的密码
MYAPP_RELEASE_KEY_PASSWORD=签名时设置的密码

4.修改android/app/build.gradle

    signingConfigs {
        debug {
           ...
        }

        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }

 5..打包(android目录下): .\gradlew.bat assembleRelease 

app打包成功,将apk拷贝到手机安装即可

6..推送代码:(需要更新时,推送代码到你想要更新的环境分支)

推送到dev环境:code-push release-react 项目名称 android -d dev

推送到production环境:-m true 代表强制更新,不加代表不强制更新

code-push release-react 项目名称 android -d Production -m true

然后重启app,就可以看到更新提示啦

 

 

 

你可能感兴趣的:(react,native,前端)