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

MediaStore获取音频异常:指定内部存储却读SD卡,INTERNAL_CONTENT_URI无效

问题分析与解决方案

我来帮你捋捋这个问题,你遇到的情况大概率是MediaStore的URI逻辑、路径匹配规则,加上Android存储权限的问题导致的,咱们一步步拆解:

1. 先搞懂EXTERNAL vs INTERNAL_CONTENT_URI的真实区别

很多人会误解这两个URI的作用:

  • MediaStore.Audio.Media.EXTERNAL_CONTENT_URI 并不是只指向外置SD卡,它实际覆盖了所有可挂载的外部存储介质——包括设备内置的主存储(也就是你说的“手机内部存储”)和外置SD卡。你之前读到SD卡内容,大概率是因为外置SD卡上也存在同名的/nexcox/voicerecorder/audio/目录。
  • MediaStore.Audio.Media.INTERNAL_CONTENT_URI 指向的是系统内部存储的私有媒体目录(比如系统自带的音乐目录),并不包含你自定义的/nexcox/...目录,所以切换到这个URI后查不到数据是正常的。

2. 路径匹配的逻辑问题

你的代码里用了AudioFilePath = "%" +"/nexcox/voicerecorder/audio/" +"%"这种通配符匹配,会导致匹配到所有路径中包含该字符串的文件——不管是内置存储还是外置SD卡的。另外,在Android 10(API 29)及以上,MediaStore.Audio.Media.DATA列已经被废弃,官方推荐用RELATIVE_PATH来匹配相对路径,避免绝对路径的适配问题。

3. 权限必须到位

  • Android 9及以下:需要申请READ_EXTERNAL_STORAGE权限,并且要动态申请(不能只在Manifest里加)。
  • Android 10及以上:如果要访问非系统默认媒体目录(比如你自定义的nexcox目录),除了READ_EXTERNAL_STORAGE,还需要申请MANAGE_EXTERNAL_STORAGE权限(注意这个权限需要用户手动在设置里开启,代码里可以引导用户跳转设置页面)。

4. 修正后的完整代码示例

下面是适配不同Android版本的查询代码,确保只读取内置存储中目标目录的音频文件:

// 先确保已经申请并获取了相应的存储权限
String targetRelativeDir = "nexcox/voicerecorder/audio/";
Uri audioUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;

// 定义要查询的字段
String[] projection = {
    MediaStore.Audio.Media._ID,
    MediaStore.Audio.Media.TITLE,
    MediaStore.Audio.Media.DATA,
    MediaStore.Audio.Media.RELATIVE_PATH
};

String selection;
String[] selectionArgs;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    // Android Q+ 用RELATIVE_PATH匹配相对路径
    selection = MediaStore.Audio.Media.RELATIVE_PATH + " LIKE ?";
    selectionArgs = new String[]{targetRelativeDir + "%"};
} else {
    // Android 9及以下 用绝对路径匹配
    String internalRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
    String targetAbsolutePath = internalRoot + "/" + targetRelativeDir;
    selection = MediaStore.Audio.Media.DATA + " LIKE ?";
    selectionArgs = new String[]{targetAbsolutePath + "%"};
}

// 执行查询
Cursor cursor = getContentResolver().query(
    audioUri,
    projection,
    selection,
    selectionArgs,
    null
);

if (cursor != null) {
    while (cursor.moveToNext()) {
        // 读取音频信息
        String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
        String filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
        Log.d("AudioQuery", "找到音频:" + title + ",路径:" + filePath);
    }
    cursor.close();
} else {
    Log.w("AudioQuery", "未查询到任何音频文件,请检查权限和路径是否正确");
}

另外还有个小细节:如果你的目标目录是刚创建的,或者里面的音频文件是刚添加的,系统可能还没完成MediaStore的索引,这时候可以发送Intent.ACTION_MEDIA_SCANNER_SCAN_FILE广播来触发扫描,确保文件能被查询到。

内容的提问来源于stack exchange,提问作者Khurram Shahzad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:15:47