1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > RN-原生混合开发之热更新

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

时间:2019-01-10 00:55:44

相关推荐

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。