如何让Android MediaPlayer正确识别audio/aacp类型音频?
问题描述
向Android的MediaPlayer传入Content Type为audio/aacp的URI时,MediaPlayer无法正确识别该内容类型并抛出异常,其他Content Type的URI可正常识别,需在保留原有功能的前提下解决此问题。
相关代码
readonly MediaPlayer player; internal StreamingAudioPlayer(System.Uri uri) { player = new MediaPlayer(); player.Completion += OnPlaybackEnded; player.SetDataSource(Android.App.Application.Context, Uri.Parse(uri.AbsoluteUri)); player.Prepare(); }
异常详情
- 直接使用该URI启动应用时,抛出
Java.IO.IOException: 'Prepare failed.: status=0x1',日志输出:
[MediaPlayer] Couldn't open (URI路径): java.io.FileNotFoundException: No content provider: (URI路径)
[System] ClassLoader referenced unknown path: /system/framework/tcmclient.jar
[NetworkSecurityConfig] No Network Security Config specified, using platform default
[MediaPlayer] error (1, -2147483648)
- 先使用其他URI启动应用再切换至该特定URI时,抛出
System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.',日志输出:
[MediaPlayer] Couldn't open (URI路径): java.io.FileNotFoundException: No content provider: (URI路径)
[MediaPlayer] error (1, -2147483648)
System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'
解决方案
1. 显式指定媒体请求头
MediaPlayer可能无法自动识别audio/aacp类型,通过SetDataSource的重载方法添加请求头,强制服务器返回兼容的AAC格式,或告知MediaPlayer优先解析AAC类型:
var headers = new Dictionary<string, string> { { "Accept", "audio/aac, audio/aacp" } }; player.SetDataSource(Android.App.Application.Context, Uri.Parse(uri.AbsoluteUri), headers);
2. 修正URI格式与权限
日志核心错误是No content provider,需针对性排查:
- 如果是网络URI:确认URI以
http://或https://开头,且AndroidManifest中已添加<uses-permission android:name="android.permission.INTERNET"/>权限; - 如果是本地文件URI:确保路径正确,且应用已获取对应文件读取权限(Android 10及以下需
android.permission.READ_EXTERNAL_STORAGE); - 如果是自定义URI:确认系统存在对应处理该URI的ContentProvider,或自行实现适配逻辑。
3. 改用异步准备逻辑
同步Prepare()在网络流场景下易因阻塞或类型识别超时抛出异常,替换为PrepareAsync()并通过事件处理流程优化:
player.PrepareAsync(); // 准备完成后启动播放 player.Prepared += (sender, args) => player.Start(); // 错误回调中尝试重试逻辑 player.Error += (sender, args) => { if (args.What == MediaPlayer.ErrorUnknown) { player.Reset(); // 重试时强制指定AAC格式请求头 var headers = new Dictionary<string, string> { { "Accept", "audio/aac" } }; player.SetDataSource(Android.App.Application.Context, Uri.Parse(uri.AbsoluteUri), headers); player.PrepareAsync(); } };
4. 检查系统解码器支持
部分设备原生不支持audio/aacp解码,可通过MediaCodecList验证:
var codecList = new MediaCodecList(MediaCodecList.AllCodecs); var supportsAacp = codecList.FindCodecByType("audio/aacp") != null; if (!supportsAacp) { // 集成第三方解码库(如FFmpeg)处理该格式 }
内容的提问来源于stack exchange,提问作者Marika Lübbers

