React Native 实现热更新并自动签名打包功能
项目背景:手动link的安卓App
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.在androidappsrcmainjavacomappMainApplication.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<ReactPackage getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage 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
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文件吧
...
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"])
....
}
....
5.修改android/app/build.gradle文件
STACK TRACE AND/OR SCREENSHOTS
:app:compileDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
C:Stock Apistock_appandroidappsrcmainjavacomstock_appMainApplication.java:6: error: package com.microsoft.codepush.react does not exist
import com.microsoft.codepush.react.CodePush;
^
C:Stock Apistock_appandroidappsrcmainjavacomstock_appMainApplication.java:23: error: cannot find symbol
return CodePush.getJSBundleFile();
^
symbol: variable CodePush
C:Stock Apistock_appandroidappsrcmainjavacomstock_appMainApplication.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.
采坑: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 Apistock_appandroidappsrcmainjavacomstock_appMainApplication.java:6: error: package com.microsoft.codepush.react does not exist import com.microsoft.codepush.react.CodePush; ^ C:Stock Apistock_appandroidappsrcmainjavacomstock_appMainApplication.java:23: error: cannot find symbol return CodePush.getJSBundleFile(); ^ symbol: variable CodePush C:Stock Apistock_appandroidappsrcmainjavacomstock_appMainApplication.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 (
<
<Root store={store} persistor={persistor} /
{this.state.visitDialog && <UpdateDialog
title={this.state.current === this.state.total ? '已完成' : '正在下载更新文件'}
describe={this.state.current === this.state.total ? '欢迎使用' : '请耐心等待'}
current={this.state.current} total={this.state.total} </UpdateDialog }
</
)
}
};
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 实现热更新并自动签名打包的文章就介绍到这了,更多相关React Native签名打包内容请搜索ZaLou.Cn以前的文章或继续浏览下面的相关文章希望大家以后多多支持ZaLou.Cn!
- 从小白变RSA大神,附常用工具使用方法及CTF中RSA典型例题
- select多路选择的模拟实现
- 初学者需要注意的问题-变量的作用域
- 在 Go 语言中,正确的使用并发
- Injectify:一款执行MiTM攻击的工具
- 看我如何发现Google云平台漏洞并获得$7500赏金
- Go语言写Web 应用程序
- 小萝莉说Crash(一):Unrecognized selector sent to instance xxxx
- 游戏服务器之多线程发送(上)
- 游戏服务器之多线程发送(中)
- 游戏服务器之多线程发送(下)
- 【团队分享】手机QQ:升级iOS8.3后,发图就崩,为哪般?
- golang 字符串操作实例
- 【团队分享】刀锋铁骑:常见Android Native崩溃及错误原因
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android TV 开发之 TV视频播放器
- Android MediaPlayer 音乐播放器扫描 本地音乐、上一曲、下一曲切歌、播放本地音乐
- 1小时真正掌握正则表达式
- Android Studio 安装配置教程 - Windows(详细版)
- Android 天气APP(八)城市切换 之 自定义弹窗与使用
- Android 接入udesk SDK实现IM
- Android 天气APP(十二)空气质量、UI优化调整
- Python+selenium 自动化-调用dom节点的click()监听事件,强力操作节点!穿透元素进行点击,节点被遮挡不可点击解决方法
- pkl是什么类型的文件?怎么来打开它?
- Python 技术篇-如何查看文本用什么类型的编码,文本编码查看方法
- Elasticsearch:设置 Elastic 账户安全
- Git存管代码,实例演示
- Git 技术篇-GitHub绑定本地Git,实例演示。实现代码云寄存
- Android 天气APP(十三)仿微信弹窗(右上角加号点击弹窗效果)、自定义背景图片、UI优化调整
- Python 微信机器人:识别消息来源于群聊还是个人