IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> RN-原生混合开发之热更新 -> 正文阅读

[移动开发]RN-原生混合开发之热更新

一、原理

RN的热更新需要更换本地js文件,根据MainAppliction中new ReactNativeHost下的getJSBundleFile方法,它默认返回index.android.bundle.js的文件路径,我们需要做的就是去替换它。所以它的步骤就是: 判断是否热更新 -> 下载zip包(zip包减少带宽) -> 解压 -> 更新覆盖

   @Nullable
   @Override
   protected 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() {
        @Override
        public 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();
            }
        }

        @Override
        public 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
   @Override
   protected 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自动加一

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-25 11:39:46  更:2022-05-25 11:39:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 0:48:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码