react-native-share在Android 7及以上版本失效,求问题排查方案
嘿,我看到你在集成react-native-share时遇到了Android版本兼容的糟心事——Android 5能用,7及以上直接罢工,还折腾了一整天,太闹心了!这问题我之前帮不少开发者搞定过,大概率是Android 7(API 24)开始的文件访问权限和URI规则变更搞的鬼,给你一步步拆解解决方案:
一、先搞定FileProvider配置(这是核心!)
Android 7开始彻底禁止用file://格式的链接在应用之间分享文件,必须换成content://开头的URI,这就得靠FileProvider来实现:
- 打开
AndroidManifest.xml,在<application>标签里加这段配置:
<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> </application>
这里的${applicationId}会自动替换成你的应用包名,不用手动改。
- 去
res目录下新建个xml文件夹,然后创建file_paths.xml文件,内容填这个:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-cache-path name="external_cache" path="." /> <cache-path name="cache" path="." /> <!-- 如果你的图片存在外部存储其他位置,再加上下面这句 --> <external-path name="external_files" path="." /> </paths>
这个文件是告诉FileProvider哪些目录的文件可以被分享出去。
二、调整你的分享代码适配新规则
你用了RNFetchBlob缓存图片,得把本地文件路径转换成FileProvider的URI才行,不能直接用原来的file路径。给你改改你的_downloadImageAndShare方法:
_downloadImageAndShare(url ,title, message) { this.setState({loading: true}) RNFetchBlob.config({ fileCache: true }) .fetch('GET', url) .then(resp => { // 获取缓存好的图片绝对路径 const filePath = resp.path() let shareUrl = filePath // 针对Android 7+做URI转换 if (Platform.OS === 'android' && Platform.Version >= 24) { // 这里的authority要和AndroidManifest里的一致,直接用包名+".fileprovider"也可以 const authority = "com.your.app.fileprovider" // 替换成你的应用包名+fileprovider shareUrl = RNFetchBlob.android.getUriForFile(filePath, authority) } // 调用react-native-share分享 return Share.open({ title: title, message: message, url: shareUrl, // 图片分享的话指定type更稳妥 type: 'image/*' }) }) .then(() => { this.setState({loading: false}) // 分享完清理缓存文件 resp.flush() }) .catch(err => { this.setState({loading: false}) console.error('分享炸了:', err) resp.flush() }) }
注意把代码里的com.your.app.fileprovider换成你实际的应用包名后缀,要和Manifest里的authorities保持完全一致。
三、权限也得盯紧
Android 6及以上需要动态申请存储权限,虽然你用的是应用缓存目录(理论上不需要权限),但有些分享场景还是会卡权限,保险起见做一下:
- 先在
AndroidManifest.xml里加权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
Android 13+的话WRITE权限已经没用了,所以加个maxSdkVersion="32"就行。
- 用
react-native-permissions库动态申请权限(先装这个库哈):
import Permissions from 'react-native-permissions'; import { Alert } from 'react-native'; // 先写个检查权限的方法 async function checkStoragePermission() { const status = await Permissions.check('storage'); if (status !== 'granted') { const result = await Permissions.request('storage'); return result === 'granted'; } return true; } // 然后在分享前先检查权限 _downloadImageAndShare(url ,title, message) { checkStoragePermission().then(granted => { if (!granted) { Alert.alert('权限不够哦', '需要存储权限才能分享图片,请去设置里开启'); return; } // 下面放你原来的下载和分享逻辑 this.setState({loading: true}) RNFetchBlob.config({...}) ... }) }
四、版本适配别踩坑
你说试过换版本,建议用和你React Native版本兼容的最新稳定版react-native-share,比如RN 0.60+的话,直接上react-native-share@7.x及以上,这些版本已经适配了Android 7+的规则,少踩很多坑。
五、关于Android 6的测试
Android 6主要是动态权限的问题,你按上面的步骤配置好权限申请,再把URI转换加上(虽然Android 6还支持file://,但统一用content://更稳妥),应该就能正常工作了。
先按这些步骤来,应该能解决Android 7+的分享问题,有其他细节问题再随时说!
内容的提问来源于stack exchange,提问作者khalifathul

