Android跨应用播放其他应用raw目录MP4失败,求解决方案
跨应用播放另一个App的Raw目录MP4解决方案
嘿,我来帮你搞定这个跨应用播放视频的问题~你之前的代码之所以报错「无法播放此视频」,核心原因是App的Raw目录资源默认是私有的,其他应用没有直接访问的权限,直接用android.resource://的Uri去访问会被系统拒绝。
下面给你两种靠谱的解决思路,优先推荐第一种规范的ContentProvider方案:
方案一:通过ContentProvider共享视频资源(推荐)
这是Android官方推荐的跨应用共享私有资源的方式,步骤如下:
1. 在应用b(com.example.app.b)中实现ContentProvider
创建一个自定义的ContentProvider,负责对外提供视频资源的访问入口:
public class VideoShareProvider extends ContentProvider { // 定义对外暴露的Uri,其他App将通过这个Uri访问视频 public static final Uri SHARE_URI = Uri.parse("content://com.example.app.b.videoshare/keyboard_anim"); @Override public boolean onCreate() { return true; } // 核心方法:返回视频资源的文件描述符 @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { // 根据Uri匹配要共享的视频(这里我们固定返回raw目录下的keyboard_anim_theme) AssetFileDescriptor rawFd = getContext().getResources().openRawResourceFd(R.raw.keyboard_anim_theme); if (rawFd == null) { throw new FileNotFoundException("Video resource not found"); } return rawFd.getParcelFileDescriptor(); } // 以下方法如果不需要实现,返回默认值即可 @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return null; } @Nullable @Override public String getType(@NonNull Uri uri) { // 返回视频的MIME类型,帮助VideoView识别 return "video/mp4"; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { return null; } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } }
2. 在应用b的AndroidManifest中注册ContentProvider
需要声明这个Provider的权限和暴露属性,确保应用a可以访问:
<provider android:name=".VideoShareProvider" android:authorities="com.example.app.b.videoshare" android:exported="true" />
android:exported="true":表示允许其他应用访问这个Provider- 如果需要更安全的访问控制,可以添加
android:permission属性,定义自定义权限,只有声明了该权限的App才能访问
3. 修改应用a的代码,通过ContentProvider Uri访问视频
把原来的Uri替换成我们定义的ContentProvider Uri即可:
VideoView videoView = (VideoView) findViewById(R.id.picker); Uri videoUri = Uri.parse("content://com.example.app.b.videoshare/keyboard_anim"); videoView.setVideoURI(videoUri); videoView.requestFocus(); videoView.start();
方案二:将视频复制到外部存储(不推荐,安全性低)
如果不想用ContentProvider,可以在应用b启动时把Raw目录的视频复制到外部公共存储,然后应用a直接访问外部存储的路径:
应用b中复制视频的代码示例:
private void copyRawToExternal() { InputStream inputStream = getResources().openRawResource(R.raw.keyboard_anim_theme); File externalFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "keyboard_anim.mp4"); try (OutputStream outputStream = new FileOutputStream(externalFile)) { byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } } catch (IOException e) { e.printStackTrace(); } }
然后应用a的代码可以直接访问这个文件路径:
File videoFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "keyboard_anim.mp4"); videoView.setVideoPath(videoFile.getAbsolutePath());
⚠️ 注意:这种方法需要申请WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE权限,而且视频会暴露在公共存储中,安全性较差,不建议用于敏感资源。
关键注意点
- 确保应用b已经安装在设备上,且包含我们定义的ContentProvider
- 如果应用b的ContentProvider设置了自定义权限,应用a需要在Manifest中声明该权限
- 测试时注意不同Android版本的权限差异(比如Android 10+的Scoped Storage会影响外部存储的访问)
内容的提问来源于stack exchange,提问作者Kingyal
相关产品推荐
相关产品推荐

