Android 11设备下应用向WhatsApp发送PDF文件出现发送失败错误的问题排查
解决Android 11下向WhatsApp发送PDF失败的问题
问题根源
Android 11(API 30)引入了**Scoped Storage(分区存储)**机制,哪怕你已经拿到存储权限,直接用file://格式的Uri给第三方应用(比如WhatsApp)分享文件也会失败——因为WhatsApp没有权限访问你的应用私有目录下的文件,而且file:// Uri在Android 7.0+就已经被官方不推荐使用,Android 11对这种跨应用文件访问的限制更严格。另外你代码里还有两个小问题:用setFlags()会覆盖原有flags,应该用addFlags();以及setType("*/*")不如指定具体MIME类型更可靠。
解决方案:使用FileProvider生成可共享的Uri
FileProvider是Android官方提供的组件,能把你的应用私有文件转换成其他应用有权限访问的Content Uri,具体步骤如下:
1. 在AndroidManifest.xml中配置FileProvider
在<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>
authorities:建议用你的应用包名加上.fileprovider,保证唯一性exported必须设为false,因为FileProvider不需要对外暴露grantUriPermissions设为true,允许临时授权其他应用访问文件
2. 创建文件路径配置文件
在res/xml目录下新建file_paths.xml文件(没有xml目录就新建一个),内容根据你的文件存储位置选择:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 如果文件存在应用私有files目录下 --> <files-path name="shared_files" path="." /> <!-- 如果文件存在外部存储的应用私有目录下 --> <!-- <external-files-path name="shared_external_files" path="." /> --> </paths>
不同标签对应不同存储位置:
files-path:对应Context.getFilesDir()目录external-files-path:对应Context.getExternalFilesDir(null)目录
3. 修改分享代码
替换原有的Uri生成和Intent配置部分,修改后的代码如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){ if (isPermissonGranted()){ Log.i("storageproblem","app runtime permission granted"); File pdfFile = new File(file); // 这里的file是你的文件路径字符串 // 先判断文件是否存在 if (!pdfFile.exists()) { Log.i("storageproblem","PDF file does not exist"); return; } // 使用FileProvider生成可共享的Content Uri Uri fileUri = FileProvider.getUriForFile( getApplicationContext(), getPackageName() + ".fileprovider", // 和Manifest里的authorities保持一致 pdfFile ); Intent share = new Intent(Intent.ACTION_SEND); share.putExtra(Intent.EXTRA_STREAM, fileUri); // 用addFlags添加权限,避免覆盖原有flags share.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); share.setPackage("com.whatsapp"); share.setType("application/pdf"); // 指定准确的PDF MIME类型 // 先判断WhatsApp是否安装再启动 if (share.resolveActivity(getPackageManager()) != null) { startActivity(share); } else { Log.i("storageproblem","WhatsApp is not installed"); } }else{ Log.i("storageproblem","app runtime permission not granted"); takePermisson(); } }
额外注意点
- 如果是分享给WhatsApp Business,需要把
setPackage("com.whatsapp")改成com.whatsapp.w4b - Android 11下不需要申请
MANAGE_EXTERNAL_STORAGE权限(除非你要访问其他应用的文件),常规存储权限加FileProvider就足够
内容的提问来源于stack exchange,提问作者Pavan Patil
相关产品推荐
相关产品推荐

