MediaPlayer setDataSource失败,状态= 0x80000000,在2.3.4上由filepath设置的铃声

标题说大部分。

我的应用程序一直在播放像uri指向的content://media/internal/audio/media/387content://media/external/audio/media/1655 (对于SDcard上的自定义铃声,我相信)使用setDataSource(fileInfo)setDataSource(mContext, Uri.parse(fileInfo))

在每种情况下,我都收到有关setDataSource failed.: status=0x80000000信息的日志setDataSource failed.: status=0x80000000使用Android 4.x(不同版本)的手机上的setDataSource failed.: status=0x80000000exception。

看到这个错误只发生在内容uri指向的铃声,而不是path指向的单个文件,我决定使用铃声的path以及上述手机上的固定问题(同时仍然使用setDataSource(mContext, Uri.parse(fileInfo))

但是,在Android 2.3.4-2.3.6手机上(但不是2.3.3版本),手机开始出现问题:

  • 我收到了一些例外情况的日志: setDataSource failed.: status=0x80000000 ,其path类似于/system/media/audio/ringtones/TwirlAway.ogg
  • 我也收到了有关MediaPlayer.onErrorListener.onError(int what, int extra)方法调用的logging,其中what=1extra=-2147483648 ,据我所知,这个logging表明该文件丢失或损坏。 但是我执行

     File file = new File(fileInfo); if (!file.exists()) 

检查这种情况,并返回该文件确实存在 – 是否损坏呢? 内部存储器中音乐文件的可能性极小。

总结一下:

  • 使用setDataSource("content://media/internal/audio/media/52")
  • 抛出exception: setDataSource failed.: status=0x80000000setDataSource failed.: status=0x80000000 setDataSource(mContext, "/system/media/audio/ringtones/TwirlAway.ogg")

有趣的是,由setDataSource(Context context, Uri uri)调用的setDataSource(Context context, Uri uri, Headers headers)方法的前几行( 从2.3.4的GrepCode源代码 ):

  String scheme = uri.getScheme(); if(scheme == null || scheme.equals("file")) { setDataSource(uri.getPath()); return; } 

所以,毕竟,它只是setDataSource("/system/media/audio/ringtones/TwirlAway.ogg") 。 我已经采取从uris来的铃声通过使用:

 private static String getRingtonePathFromContentUri(Context context, Uri contentUri) { String[] proj = { MediaStore.Audio.Media.DATA }; Cursor ringtoneCursor = context.getContentResolver().query(contentUri, proj, null, null, null); ringtoneCursor.moveToFirst(); return ringtoneCursor.getString(ringtoneCursor .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)); } 

任何想法可能导致错误抛出? 也许这些是由于阅读权限不足造成的一些问题? 我猜原始setDataSource(stringpath)函数的源代码将帮助很多,但我无法find它。

Solutions Collecting From Web of "MediaPlayer setDataSource失败,状态= 0x80000000,在2.3.4上由filepath设置的铃声"

在处理这个问题时,下面的Lorne回答最有帮助。

对于任何与之斗争的人来说,以下是我已经使用了6个多月的代码,几乎不会再报告错误。

fileinfo可以是两个(例子):

/system/media/audio/alarms/Walk_in_the_forest.ogg

content://media/internal/audio/media/20

 public static void setMediaPlayerDataSource(Context context, MediaPlayer mp, String fileInfo) throws Exception { if (fileInfo.startsWith("content://")) { try { Uri uri = Uri.parse(fileInfo); fileInfo = getRingtonePathFromContentUri(context, uri); } catch (Exception e) { } } try { if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) try { setMediaPlayerDataSourcePreHoneyComb(context, mp, fileInfo); } catch (Exception e) { setMediaPlayerDataSourcePostHoneyComb(context, mp, fileInfo); } else setMediaPlayerDataSourcePostHoneyComb(context, mp, fileInfo); } catch (Exception e) { try { setMediaPlayerDataSourceUsingFileDescriptor(context, mp, fileInfo); } catch (Exception ee) { String uri = getRingtoneUriFromPath(context, fileInfo); mp.reset(); mp.setDataSource(uri); } } } private static void setMediaPlayerDataSourcePreHoneyComb(Context context, MediaPlayer mp, String fileInfo) throws Exception { mp.reset(); mp.setDataSource(fileInfo); } private static void setMediaPlayerDataSourcePostHoneyComb(Context context, MediaPlayer mp, String fileInfo) throws Exception { mp.reset(); mp.setDataSource(context, Uri.parse(Uri.encode(fileInfo))); } private static void setMediaPlayerDataSourceUsingFileDescriptor( Context context, MediaPlayer mp, String fileInfo) throws Exception { File file = new File(fileInfo); FileInputStream inputStream = new FileInputStream(file); mp.reset(); mp.setDataSource(inputStream.getFD()); inputStream.close(); } private static String getRingtoneUriFromPath(Context context, String path) { Uri ringtonesUri = MediaStore.Audio.Media.getContentUriForPath(path); Cursor ringtoneCursor = context.getContentResolver().query( ringtonesUri, null, MediaStore.Audio.Media.DATA + "='" + path + "'", null, null); ringtoneCursor.moveToFirst(); long id = ringtoneCursor.getLong(ringtoneCursor .getColumnIndex(MediaStore.Audio.Media._ID)); ringtoneCursor.close(); if (!ringtonesUri.toString().endsWith(String.valueOf(id))) { return ringtonesUri + "/" + id; } return ringtonesUri.toString(); } public static String getRingtonePathFromContentUri(Context context, Uri contentUri) { String[] proj = { MediaStore.Audio.Media.DATA }; Cursor ringtoneCursor = context.getContentResolver().query(contentUri, proj, null, null, null); ringtoneCursor.moveToFirst(); String path = ringtoneCursor.getString(ringtoneCursor .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)); ringtoneCursor.close(); return path; } 

由于Android 4.1.1中的错误修正, setDataSource(String path)的行为发生了变化。 在4.1.1或更高版本中,您需要使用本地path(不使用协议)。 但是,在4.0.4和更早的版本中,你需要使用一个URI(例如file:// protocol)。

这是一个不完整的代码片断,应该说明解决方法:

 // as of 4.1.1 (JELLY_BEAN) we need to use a local path (without protocol) // on 4.0.4 and earlier we needed a URI (with file:// protocol) final String cachedFile = android.os.Build.VERSION.SDK_INT >= 16 // android.os.Build.VERSION_CODES.JELLY_BEAN ? getCacheFilePath(file) : getCacheFileUri(file); // for the purpose of this example // assume cacheFolder is a String and getCacheFile returns a String public String getCacheFilePath(String file) { return cacheFolder + getCacheFile(file); } public String getCacheFileUri(String file) { return "file://" + cacheFolder + getCacheFile(file); } 

你必须明确地设置你的文件的长度。 使用重载的方法:
AssetFileDescriptor afd = ctx.getAssets().openFd([your asset name]); mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());

当我尝试播放.wav文件时,我遇到了同样的错误。 我们举个例子:

  private void start_player(){ // create raw folder inside the res folder if not present MediaPlayer mPlayer = MediaPlayer.create(activity, R.raw.your_wave_audio_file); mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mp.release(); // Your Stuff } }); mPlayer.start(); } } 

我也得到了状态= 0x80000000错误。 在我的情况下,解决scheme是重新编码audio文件(例如对于一个.wav文件的16位PCM),一切按预期工作。

 MediaPlayer mPlayer = MediaPlayer.create(activity, R.raw.your_wave_audio_file); mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 

你不能这样做,因为prepare是在create函数中调用的,所以你不能改变Audio Stream Type。

下面的代码对我来说工作的很好:

 sMediaPlayer = new MediaPlayer(); sMediaPlayer.setAudioStreamType(AudioManager.STREAM_RING); AssetFileDescriptor assetFileDescriptor = context.getResources(). openRawResourceFd(R.raw.cool_song); if(assetFileDescriptor == null) return; try { sMediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength()); assetFileDescriptor.close(); sMediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { if(sMediaPlayer != null){ sMediaPlayer.release(); sMediaPlayer = null; } } }); sMediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { sMediaPlayer.start(); } }); sMediaPlayer.prepare(); } catch (IllegalArgumentException e) { HelpFunctions.showLog("ERROR = " + e); } catch (IllegalStateException e) { HelpFunctions.showLog("ERROR = " + e); } catch (IOException e) { HelpFunctions.showLog("ERROR = " + e); }