切换Activity后,共享Uri/FileDescriptor权限失效致媒体处理报错
跨Activity处理分享Uri时MediaMetadataRetriever报错的解决方案
问题原因分析
你遇到的setDataSource failed: status = 0x80000000错误,本质是两个核心问题:
- FileDescriptor生命周期失效:从ContentResolver获取的FileDescriptor与当前Activity的资源绑定,当第一个Activity进入后台或销毁时,系统会自动关闭这个描述符,静态变量里存的只是无效引用,第二个Activity调用时自然失败。
- Uri临时权限未传递:通过分享菜单获取的Uri仅在接收它的第一个Activity拥有临时访问权限,默认不会自动传递给后续启动的Activity,导致第二个Activity无法访问该Uri指向的资源。
正确解决方案
放弃存储FileDescriptor,改为传递Uri并手动传递访问权限,在第二个Activity中重新通过ContentResolver获取资源访问权。
步骤1:在第一个Activity中传递Uri与权限
跳转第二个Activity时,通过Intent携带Uri,并添加权限标记:
// 假设sharedUri是你从分享菜单接收的Uri Intent intent = new Intent(this, SecondActivity.class); intent.setData(sharedUri); // 传递Uri的读取权限给第二个Activity intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent);
步骤2:修改工具方法支持Uri直接调用
更新videoThumbMini方法,直接使用Uri和Context获取数据源,无需依赖FileDescriptor:
public static Bitmap videoThumbMini(Context context, Uri uri) { Bitmap bitmap = null; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { // 直接通过Context和Uri设置数据源,自动处理权限 retriever.setDataSource(context, uri); bitmap = retriever.getFrameAtTime(1000); if (bitmap == null) return null; float ratio = 1; if (bitmap.getHeight() > 300) ratio = bitmap.getHeight() / 300f; bitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() / ratio), 200, false); } catch (RuntimeException e) { Logger.log(e.getMessage() + " ERR3", false, e); } finally { try { retriever.release(); } catch (Exception e) { Logger.log(e.getMessage() + " ERR4", false, e); } } return bitmap; }
步骤3:在第二个Activity中调用方法
从Intent中取出Uri,传入工具方法即可:
Uri sharedUri = getIntent().getData(); if (sharedUri != null) { Bitmap thumb = videoThumbMini(this, sharedUri); // 处理缩略图 }
额外注意事项
- 避免用静态变量存储Uri或FileDescriptor:不仅会导致权限失效,还可能引发内存泄漏问题。
- 若需长期访问资源:可以将分享的文件复制到应用私有目录(如
getFilesDir()),但会占用额外存储空间,需根据业务场景权衡。
内容的提问来源于stack exchange,提问作者forootan
相关产品推荐
相关产品推荐

