Android应用重启后无法直接通过URI播放本地MP4的解决方法咨询
解决方案:持久化文件Uri权限
核心问题原因
通过ACTION_OPEN_DOCUMENT获取的Uri仅拥有临时访问权限,应用重启后权限会被系统回收,导致无法直接访问。你尝试的grantUriPermission是用于给其他应用授权访问Uri,并非给自己的应用获取持久权限,因此无效。
正确实现步骤
1. 获取持久化权限
在选中视频的回调中,调用getContentResolver().takePersistableUriPermission()将临时权限转为持久权限:
private final ActivityResultLauncher<String[]> videoFilePickerLauncher = registerForActivityResult( new ActivityResultContracts.OpenDocument(), new ActivityResultCallback<Uri>() { @Override public void onActivityResult(Uri result) { if (result != null) { videoUri = result; // 转换为持久权限 int takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION; getContentResolver().takePersistableUriPermission(videoUri, takeFlags); // 保存Uri到本地存储(示例用SharedPreferences) SharedPreferences prefs = getSharedPreferences("VideoPlayerPrefs", MODE_PRIVATE); prefs.edit().putString("saved_video_uri", videoUri.toString()).apply(); } } } );
2. 应用重启后读取保存的Uri
在onCreate等初始化环节,从本地存储读取之前保存的Uri字符串并转为Uri对象:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ...其他初始化逻辑 SharedPreferences prefs = getSharedPreferences("VideoPlayerPrefs", MODE_PRIVATE); String savedUriStr = prefs.getString("saved_video_uri", null); if (savedUriStr != null) { videoUri = Uri.parse(savedUriStr); } }
3. 播放时处理权限失效情况
虽然持久权限一般不会主动失效,但用户可能在系统设置中撤销权限,因此建议添加异常捕获:
try { MediaItem mediaItem = MediaItem.fromUri(videoUri); exoPlayer.setMediaItem(mediaItem); exoPlayer.prepare(); exoPlayer.play(); } catch (SecurityException e) { Toast.makeText(this, "视频访问权限已失效,请重新选择", Toast.LENGTH_SHORT).show(); // 自动启动选择器重新获取 videoFilePickerLauncher.launch(new String[]{"video/*"}); }
其他可选方案(不推荐)
如果你的应用目标版本低于Android 10(API 29),可以考虑直接获取文件路径,但这种方式不符合Scoped Storage规范,在高版本系统中会被限制。官方强烈推荐使用持久化Uri的方案,适配性更强。
内容的提问来源于stack exchange,提问作者Shou Pu
相关产品推荐
相关产品推荐

