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

架构