栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

RN-原生混合开发之热更新

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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、热更新需要两个权限,高版本需做权限申请适配



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自动加一

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/918982.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号