RN 0.71 (Android 33) 安卓更新方案

针对 React Native 0.71 且目标 Android API 33 (Android 13) 的原生下载并安装 APK 功能,主要挑战在于 Android 13 的权限收紧(特别是存储权限的变化)以及 FileProvider 的安全共享。

以下是详细的技术调研与实施方案:

技术调研方案:原生下载与增量更新安装

1. 核心技术选型

环节 推荐方案 理由
文件下载 rn-fetch-blob 或 react-native-fsrn-fetch-blob 支持 Android DownloadManager,集成度高。
权限管理 react-native-permissions API 33 需要特定的权限声明和运行时请求。
静默/唤起安装 android.intent.action.VIEW + FileProvider Android 7.0+ 强制要求,API 33 必须配置。

2. 权限与配置 (AndroidManifest.xml)

在 API 33 中,传统的 READ_EXTERNAL_STORAGE 已失效。对于下载 APK 这种操作,我们主要关注 安装未知应用权限 和 文件共享路径。

2.1 声明权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

2.2 配置 FileProvider (核心)

为了让系统安装器能读取你下载的 APK,必须配置 FileProvider

android/app/src/main/AndroidManifest.xml<application> 标签内:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

创建 android/app/src/main/res/xml/file_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="." />
<external-cache-path name="my_cache_download" path="." />
</paths>

3. 实现逻辑流程图

流程

4. 具体代码实现 (JavaScript/TypeScript)

第一步:下载 APK推荐使用 rn-fetch-blob,因为它对 Android DownloadManager 封装得最好,可以自动处理通知栏进度。

import RNFetchBlob from 'rn-fetch-blob';
const downloadApk = (url) => {
 const { config, fs } = RNFetchBlob;
 const apkPath = `${fs.dirs.DownloadDir}/app-release.apk`;

 return config({
     fileCache: true,
     addAndroidDownloads: {
         useDownloadManager: true, // 使用原生下载管理器
         notification: true, // 显示下载进度
         path: apkPath, // 下载路径
         mime: 'application/vnd.android.package-archive',
         description: '正在下载新版本...',
     },
 })
     .fetch('GET', url)
     .then((res) => {
         // 下载完成后唤起安装
         installApk(res.path());
     });
 };

第二步:唤起原生安装界面
由于 RN 0.71 依然可以通过原生模块或三方库调用 Intent,如果不想写 Java,可以使用 rn-fetch-blob 的原生 Intent 方法:

const installApk = (path) => {
if (Platform.OS === 'android') {
    RNFetchBlob.android.actionViewIntent(
        path,
        'application/   vnd.android.package-archive'
        );
    }
};

5. API 33 关键适配点

  1. 通知权限:在下载前,需要申请 PERMISSIONS.ANDROID.POST_NOTIFICATIONS,否则下载进度条不会在顶部通知栏显示。
  2. 安装权限检查:在执行安装前,建议检查 canRequestPackageInstalls()。如果未授权,需跳转设置页:
 import { Linking } from 'react-native';
 // 引导跳转
 Linking.sendIntent("android.settings.MANAGE_UNKNOWN_APP_SOURCES", [
  { key: "package", value: "你的包名" }
 ]);
  1. FileProvider 匹配:确保 actionViewIntent 内部处理了 content:// 协议,而非旧的 file:// 协议。rn-fetch-blob 的最新版通常已处理,若报错 FileUriExposedException,则需自定义 Native Module 使用 FileProvider.getUriForFile。

6. 方案总结

架构
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容