You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:32:46