React Native 0.60.4升级SDK至29后Android10文件下载路径失效求助
Hey there, I’ve run into similar headaches with rn-fetch-blob after upgrading to target SDK 29 on Android 10, so let’s break down how to fix this or switch to a more reliable alternative.
先尝试修复 rn-fetch-blob 的问题
Even with android:requestLegacyExternalStorage="true" added, there are a few key checks to make:
Double-check your AndroidManifest.xml setup
Ensure the permission and legacy flag are placed correctly (don’t miss wrapping the flag inside the<application>tag):<manifest ...> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application ... android:requestLegacyExternalStorage="true"> ... </application> </manifest>Note: This flag works only for SDK 29; it gets ignored for SDK 30+, but since you’re targeting 29, it should still help bypass scoped storage restrictions temporarily.
Avoid hardcoded paths
Instead of usingstorage/emulated/0/test, leveragern-fetch-blob’s built-in directory constants to ensure compatibility:import RNFetchBlob from 'rn-fetch-blob'; // Use public Download directory instead of arbitrary custom path const downloadPath = `${RNFetchBlob.fs.dirs.DownloadDir}/test`;Hardcoded paths often fail on Android 10+ even with legacy mode, as scoped storage restricts direct access to arbitrary locations.
Update
rn-fetch-blobto its latest compatible version
Older versions of the library don’t handle SDK 29 properly. Whilern-fetch-blobis no longer actively maintained, checking for the final updates might resolve the immediate issue.
推荐支持 DownloadManager 与通知功能的替代库
Since rn-fetch-blob is deprecated, switching to a maintained library is a better long-term fix. Here are my top picks:
1. react-native-fs
This is a widely adopted, well-maintained library that natively supports Android’s DownloadManager with progress notifications out of the box.
Basic download example with notification:
import RNFS from 'react-native-fs'; const downloadFile = async () => { const url = 'https://example.com/your-file.pdf'; const downloadDest = `${RNFS.DownloadDirectoryPath}/test/your-file.pdf`; const options = { fromUrl: url, toFile: downloadDest, background: true, // Enable background download progressDivider: 1, // Update progress every 1% notification: { title: 'Downloading File', description: 'Please wait...', autoClear: true, color: '#2196F3' } }; try { const jobId = await RNFS.downloadFile(options).promise; console.log('Download finished:', jobId); } catch (error) { console.error('Download failed:', error); } };
2. react-native-download-manager
A lightweight, focused library built directly around Android’s DownloadManager, with straightforward notification configuration and background download support.
Example usage:
import DownloadManager from 'react-native-download-manager'; import RNFS from 'react-native-fs'; DownloadManager.download({ url: 'https://example.com/your-file.pdf', title: 'My Download', description: 'In progress...', destination: `${RNFS.DownloadDirectoryPath}/test/your-file.pdf`, showNotification: true, notificationVisibility: DownloadManager.VISIBILITY_VISIBLE_NOTIFY_COMPLETED });
3. expo-file-system (works for bare React Native apps too)
If you’re open to using Expo libraries in your bare project, expo-file-system offers robust download capabilities. You can pair it with expo-notifications to add custom progress alerts.
Download example with progress tracking:
import * as FileSystem from 'expo-file-system'; const downloadFile = async () => { const url = 'https://example.com/your-file.pdf'; const downloadDest = `${FileSystem.documentDirectory}test/your-file.pdf`; const downloadResumable = FileSystem.createDownloadResumable( url, downloadDest, {}, (progress) => { const percent = (progress.totalBytesWritten / progress.totalBytesExpectedToWrite) * 100; console.log(`Progress: ${Math.round(percent)}%`); // Use expo-notifications to update a custom notification here } ); try { const { uri } = await downloadResumable.downloadAsync(); console.log('File saved to:', uri); } catch (error) { console.error('Download failed:', error); } };
Final Tips
For Android 10+, even with legacy storage enabled, stick to public directories like Download or app-specific storage instead of arbitrary custom paths. This will help your app comply with scoped storage rules and avoid issues when upgrading to SDK 30+.
内容的提问来源于stack exchange,提问作者Rigsby

