API 28下自定义菜单分享媒体提示“未找到媒体”求助
问题解决:API 28下自定义分享出现“未找到媒体”错误
问题场景
在API 28环境中,点击自定义菜单的分享按钮,打开分享界面后尝试分享媒体时,出现“no media found(未找到媒体)”错误,无法将媒体发送至其他应用。系统原生分享功能可正常使用,相关代码如下:
if(item.getTitle().equals("SHARED")){ String url = Uri.parse(selectedFile.getAbsolutePath()).toString(); try { Intent share = new Intent(Intent.ACTION_SEND); share.putExtra(Intent.EXTRA_STREAM, url); if(url.contains(".jpg") || url.contains(".jpeg")) { // JPG file share.setType("image/jpg"); } else if(url.contains(".png")) { // PNG file share.setType("image/png"); } else if(url.contains(".mpg") || url.contains(".mpeg") || url.contains(".mpe") || url.contains(".mp4") || url.contains(".avi")) { // Video files share.setType("video/*"); } //share.setData(Uri.parse(selectedFile.getPath())); //share.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Intent chooserIntent = Intent.createChooser(share, "Open With"); chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(chooserIntent); } catch (Exception e) { // For example, android.content.ActivityNotFoundException Log.e(DebugUtils.TAG, e.toString()); } }
错误原因
- 参数类型错误:
Intent.EXTRA_STREAM要求传入Uri对象,而非字符串类型的路径,直接传字符串会导致接收方无法解析媒体资源。 - 权限限制问题:API 24及以上版本(含API28)禁止应用直接通过
file://格式的Uri共享文件,其他应用没有访问该文件的权限。系统原生分享正常是因为它使用了媒体库提供的content://格式Uri,自带临时访问权限。
解决方案
步骤1:注册FileProvider
在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> ... </application>
步骤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-path name="shared_external" path="."/> --> </paths>
步骤3:修改分享代码
替换原代码中Uri的生成方式,使用FileProvider获取可共享的content://格式Uri,并修正EXTRA_STREAM的参数类型:
if(item.getTitle().equals("SHARED")){ try { Intent share = new Intent(Intent.ACTION_SEND); // 使用FileProvider生成可共享的Uri Uri fileUri = FileProvider.getUriForFile( context, context.getPackageName() + ".fileprovider", selectedFile); // 授予临时读取权限 share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); share.putExtra(Intent.EXTRA_STREAM, fileUri); // 通过File对象判断文件类型,更可靠 String fileName = selectedFile.getName(); if(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) { share.setType("image/jpeg"); } else if(fileName.endsWith(".png")) { share.setType("image/png"); } else if(fileName.matches(".*\\.(mpg|mpeg|mpe|mp4|avi)$")) { share.setType("video/*"); } Intent chooserIntent = Intent.createChooser(share, "Open With"); chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 确保所有目标应用都能获取权限 chooserIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); context.startActivity(chooserIntent); } catch (Exception e) { Log.e(DebugUtils.TAG, e.toString()); } }
关键修改说明
- 用
FileProvider.getUriForFile()生成content://格式Uri,替代Uri.parse(selectedFile.getAbsolutePath()),解决跨应用文件访问权限问题。 - 添加
FLAG_GRANT_READ_URI_PERMISSION标记,授予接收方临时读取文件的权限。 - 直接通过
File对象判断文件类型,避免字符串解析的潜在错误。
内容的提问来源于stack exchange,提问作者בני סעדון
相关产品推荐
相关产品推荐

