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

使用MediaMetadataRetriever setDataSource读取外部存储MP3触发IllegalArgumentException

解决MediaMetadataRetriever.setDataSource触发IllegalArgumentException的问题

我帮你分析下问题出在哪,以及对应的解决办法:

你遇到的IllegalArgumentException主要是因为直接用绝对路径字符串解析Uri的方式错误,再加上Android不同版本的存储权限、访问规则限制,导致系统无法正确定位并访问你的MP3文件。

具体解决步骤:


1. 修正Uri的获取方式

不能直接用Uri.parse("/sdcard/song.mp3")来构建Uri,这种方式不符合Android的文件Uri规范。正确的做法是先创建File对象,再根据系统版本生成对应的Uri:

File songFile = new File(Environment.getExternalStorageDirectory(), "song.mp3");
  • Android 7.0以下可以直接用Uri.fromFile(songFile)生成Uri
  • Android 7.0及以上需要用FileProvider生成安全Uri(避免FileUriExposedException)

2. 确保申请了存储权限

Android 6.0(API 23)及以上版本,读取外部存储需要动态申请READ_EXTERNAL_STORAGE权限,否则会被系统拒绝访问文件。

你可以把加载封面的逻辑封装成方法,先检查权限再执行:

private static final int REQUEST_STORAGE_PERMISSION = 100;
private MediaMetadataRetriever metaRetriver;
private ImageView album_art;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getInit();

    // 检查存储权限
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                REQUEST_STORAGE_PERMISSION);
    } else {
        loadAlbumArt();
    }
}

// 权限申请回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_STORAGE_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            loadAlbumArt();
        } else {
            Toast.makeText(this, "需要存储权限才能读取专辑封面", Toast.LENGTH_SHORT).show();
        }
    }
}

// 加载专辑封面的核心方法
private void loadAlbumArt() {
    metaRetriver = new MediaMetadataRetriever();
    try {
        File songFile = new File(Environment.getExternalStorageDirectory(), "song.mp3");
        // 先检查文件是否存在
        if (!songFile.exists()) {
            Log.i("lolol", "文件不存在,请检查路径");
            return;
        }

        Uri songUri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // Android 7.0+使用FileProvider获取安全Uri
            songUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", songFile);
        } else {
            songUri = Uri.fromFile(songFile);
        }

        metaRetriver.setDataSource(this, songUri);
        byte[] art = metaRetriver.getEmbeddedPicture();
        if (art != null) {
            Bitmap songImage = BitmapFactory.decodeByteArray(art, 0, art.length);
            album_art.setImageBitmap(songImage);
        } else {
            Log.i("lolol", "art is null");
        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.i("lolol", "加载失败: " + e.getMessage());
    } finally {
        // 使用后释放资源,避免内存泄漏
        if (metaRetriver != null) {
            metaRetriver.release();
        }
    }
}

public void getInit() {
    album_art = findViewById(R.id.album_art);
}

3. Android 7.0+配置FileProvider

如果你的APP目标版本是Android 7.0及以上,需要在AndroidManifest.xml中配置FileProvider:

<application>
    <!-- 其他配置 -->
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

然后在res/xml目录下创建file_paths.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 允许访问外部存储根目录 -->
    <external-path name="external_files" path="." />
</paths>

额外注意事项

  • 尽量避免硬编码/sdcard路径,用Environment.getExternalStorageDirectory()获取外部存储根目录更可靠
  • 每次使用MediaMetadataRetriever后一定要调用release()释放资源
  • 提前检查文件是否存在,避免因文件缺失导致的异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:26:43