RN-原生混合开发之热更新
一、原理
RN的热更新需要更换本地js文件,根据MainAppliction中new ReactNativeHost下的getJSBundleFile方法,它默认返回index.android.bundle.js的文件路径,我们需要做的就是去替换它。所以它的步骤就是: 判断是否热更新 -> 下载zip包(zip包减少带宽) -> 解压 -> 更新覆盖
@Nullable@Overrideprotected String getJSBundleFile() {// 判断权限if (!new RuntimePermissions(context).check(Manifest.permission.WRITE_EXTERNAL_STORAGE))return super.getJSBundleFile();File file = new File (FilePath.BUNDLE_PATH);if(file != null && file.exists()) {return FilePath.BUNDLE_PATH;} else {return super.getJSBundleFile();}}
二、热更新条件
判断热更新的条件有两个:
- 本地原生版本大于或等于网络请求的原生版本
- 本地热更新版本小于网络请求的热更新版本
这两个条件同时成立则进行热更新下载,第一个条件是为了限制不让原生和热更新同时触发,事实上原生更新是包括热更新的。本地的原生版本可以通过AndroidManifest.xml的android:versionCode来判断。而本地的热更新版本是不能这样的,可以在bundle.zip中加入一个version.txt来控制热更新版本,每次热更新后version.txt都加一,在android中读取这个文件来获取本地热更新版本,然后再去和网络请求的比对就能判断是否需要热更新了。
三、下载bundle.zip
public static void downloadFile(final Context mContext, String url) throws Exception {AsyncHttpClient client = new AsyncHttpClient(getSchemeRegistry());client.get(mContext, url, new AsyncHttpResponseHandler() {@Overridepublic void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {BufferedOutputStream bos = null;FileOutputStream fos = null;File file = null;try {file = new File(FilePath.ZIP_LOCAL_PATH);fos = new FileOutputStream(file);bos = new BufferedOutputStream(fos);bos.write(responseBody);} catch (IOException e) {e.printStackTrace();}File zipFile = new File(FilePath.ZIP_LOCAL_PATH);File file_unzip_path = new File(FilePath.LOCAL_PATH);if (!file_unzip_path.exists()) {file_unzip_path.mkdir();}try {UnZipFolder(zipFile, FilePath.LOCAL_PATH);} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onFailure(int statusCode, Header[] headers, byte[] binaryData, Throwable error) {Toast.makeText(mContext, "下载失败", Toast.LENGTH_LONG).show();}});
}
四、解压zip包
public static void UnZipFolder(File f, String outPathString) throws Exception {ZipInputStream inZip = new ZipInputStream(new FileInputStream(f));ZipEntry zipEntry;String szName = "";while ((zipEntry = inZip.getNextEntry()) != null) {szName = zipEntry.getName();if (zipEntry.isDirectory()) {//获取部件的文件夹名szName = szName.substring(0, szName.length() - 1);File folder = new File(outPathString + File.separator + szName);folder.mkdirs();} else {Log.e(TAG,outPathString + File.separator + szName);File file = new File(outPathString + File.separator + szName);if (!file.exists()){Log.e(TAG, "Create the file:" + outPathString + File.separator + szName);file.getParentFile().mkdirs();file.createNewFile();}// 获取文件的输出流FileOutputStream out = new FileOutputStream(file);int len;byte[] buffer = new byte[1024];// 读取(字节)字节到缓冲区while ((len = inZip.read(buffer)) != -1) {// 从缓冲区(0)位置写入(字节)字节out.write(buffer, 0, len);out.flush();}out.close();}}inZip.close();
}
五、注意点
1、热更新需要两个权限,高版本需做权限申请适配
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、当安装完app后,此时没有给app授权,但已检测到需要热更新,下载完后解压就需要android.permission.WRITE_EXTERNAL_STORAGE这个权限,没有的话会报异常,所以需要判断的是没有这个权限就不下载
// 判断是否有权限
if (permission.check(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {new UpdateChecker().check(this);
}
3、app已经热更新过,现在把它卸载掉,再重新装的时候,虽然不会触发热更新,但是此时手机上已经有热更新过的文件夹,这时app会直接去访问热更新的文件夹,又会因为没有授权报异常,所以需要做是否有权限的判断
@Nullable@Overrideprotected String getJSBundleFile() {// 判断权限if (!new RuntimePermissions(context).check(Manifest.permission.WRITE_EXTERNAL_STORAGE))return super.getJSBundleFile();File file = new File (FilePath.BUNDLE_PATH);if(file != null && file.exists()) {return FilePath.BUNDLE_PATH;} else {return super.getJSBundleFile();}}
4、热更新的过程需要开子线程处理
5、增量更新,不需要每次都去下载一个完整的bundle.zip
6、每热更新完后,bundle.zip中的version.txt自动加一
RN-原生混合开发之热更新相关推荐
- uni-app结合原生混合开发
uni-app混合开发 uni-app混合开发主要为扩展接入一些第三方的SDK或其他uni-app无法实现的功能,项目结构有两种: 主体采用uni-app,部分功能的实现使用原生开发. 主体采用原生, ...
- 推荐用于学习RN原生模块开发的开源库—react-native-ble-manager
如题RN的原生模块/Native Modules的开发是一项很重要的技能,但RN官网的示例又比较简单,然后最近我接触与使用.还有阅读了react-native-ble-manager的部份源码,发现里 ...
- iOS开发-苹果热更新禁止-JSpatch禁止-热更新上线被拒绝
今天一大早看各个iOS开发群炸锅了,原来是苹果大佬禁止了热更新和JSpatch.导致很多人的项目上线和更新被拒,目前还没有解决方案,也要等着业界大佬们尽快出方案,哈哈. 那么来说说JSpatch有什么 ...
- android调用flutter aar_Flutter原生混合开发
混合开发简介 使用Flutter从零开始开发App是一件轻松惬意的事情,但对于一些成熟的产品来说,完全摒弃原有App的历史沉淀,全面转向Flutter是不现实的.因此使用Flutter去统一Andro ...
- flutter打包的app有多大_Flutter原生混合开发
使用 Flutter 从头开始写一个 App是一件轻松惬意的事情.但是对于成熟产品来说,完全摒弃原有 App 的历史沉淀,全面转向 Flutter 并不现实.用 Flutter 去统一 iOS/And ...
- iOS开发-苹果热更新方案简介
以下是iOS app热更新的几种方案. 一.动态库 可以做demo用,真实使用的时候会被苹果禁止. 因为 打包发到AppStore的ipa安装包 里的每个动态库 都有唯一的编码,iOS系统会进行验证, ...
- Parcel React 开发服务器热更新实战
parcel Parcel 是 Web 应用打包工具,适用于经验不同的开发者.它利用多核处理提供了极快的速度,并且不需要任何配置. 内容 官网教程没有实现devSever和动态更新相结合具体部署步骤. ...
- Unity游戏开发-游戏热更新以及登录流程
本篇主要分享基于热更新的游戏初始化方案. 整体初始化的流程大致为:检查是否需要解压资需要则解压,之后再检查是否存在需要热更新的资源文件需要则更新,更新完成后则初始化结束可进入登录界面. 关于登录这块的 ...
- 《江湖X》开发笔谈 - 热更新框架
前言 大家好,我们这期继续借着我们工作室正在运营的在线游戏<江湖X>来谈一下热更新机制以及我们的理解和解决方案.这里先简单的介绍一下热更新的概念,熟悉这部分的朋友可以跳过,直接看我们的方案 ...
最新文章
- 扩展LLVM:添加指令、内部函数、类型等
- Mysql高级调优篇——前言简介
- 【社工】NodeJS 应用仓库钓鱼
- goto VS longjmp setjmp
- 疯狂捕鱼之路径解决方案的思考
- Android 四大组件之——Acitivity(一)
- conda重命名环境env
- python与正则表达式(part5)--re模块使用
- python 包和模块的区别_3分钟带你搞懂Python模块、包的区别和使用
- 苏宁大数据怎么运营_数据驱动经营 苏宁大数据用户标签入选2019TOP100全球软件案例...
- tomcat不停机部署_Tomcat中的零停机部署(和回滚); 演练和清单
- 前端:CSS/10/伪类选择器,CSS列表属性,CSS边框属性,CSS内边距属性,CSS背景属性
- 【深度优先搜索】计蒜客:正方形
- Seven Kinds of Testers - 七种类型的测试
- 在希望的田野上--生物柴油(Biodiesel)光明的未来
- 手写一个识别旺旺/千牛,手机在线/电脑在线状态的小工具
- ML/DL学习笔记2——偏差和方差模型好坏
- w ndows7怎么设置打印机,Windows7系统如何添加打印机
- JSON和全局异常处理
- Python删除字符串中的空格和特殊字符
热门文章
- pageHelper与PageInfo联合进行分页查询原理
- [原创] 在MFC中大家都习惯用CStdioFile来处理文本文件,可是为什么CStdioFile不叫CTextFile?
- C++ 多个指针指向同一个对象
- mysql报错1357_mysql8 参考手册--错误代码1343-1367
- 多智能体中的图论——图论中的定义(一)
- 利用OPC技术实现双网冗余系统的通讯驱动
- Jupyter lab add kernel Python+Julia+R 【jupyter Notebook 切换Python环境】and【在jupyter Notebook中安装第三方库】
- 下载配置安装MySql---超详细教程
- Docker容器回顾之运维篇
- 3 万字 + 100 张图带你彻底搞懂 TCP 面试题(强烈建议收藏)