【问题标题】:MediaPlayer setDataSource failed with status=0x80000000 for Ringtone set by filepath on 2.3.4MediaPlayer setDataSource 失败,状态 = 0x80000000 为 2.3.4 上的文件路径设置的铃声
【发布时间】:2013-04-30 00:29:19
【问题描述】:

标题说明了大部分内容。

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

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

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

然而,它在 Android 2.3.4-2.3.6 的手机上开始出现问题(虽然不是我的 2.3.3):

  • 我收到的日志很少,但有以下例外:setDataSource failed.: status=0x80000000 文件的路径类似于/system/media/audio/ringtones/TwirlAway.ogg
  • 我还收到了关于 MediaPlayer.onErrorListener.onError(int what, int extra) 方法调用的日志,其中包含 what=1extra=-2147483648,据我所知,这表明该文件丢失或已损坏。但是我执行

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

在这种情况下检查并返回该文件确实存在 - 那么它是否已损坏?内存中的音乐文件不太可能。

总结一下:

  • setDataSource("content://media/internal/audio/media/52")一起工作
  • 抛出异常:setDataSource failed.: status=0x80000000 for setDataSource(mContext, "/system/media/audio/ringtones/TwirlAway.ogg")

有趣的是,setDataSource(Context context, Uri uri) 调用的 setDataSource(Context context, Uri uri, Headers headers) 方法的前几行是 (from GrepCode source for 2.3.4):

 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(String path) 函数的源代码会有很大帮助,但我找不到它。

【问题讨论】:

    标签: android android-mediaplayer ringtone


    【解决方案1】:

    以下 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;
    }
    

    【讨论】:

    • 我已经尝试解决这个问题将近一个月了。我们的应用程序甚至是一个闹钟应用程序,它应该在早上完美地播放音乐或铃声,但直到现在播放音乐时出现很多崩溃。
    • 因为这个问题我很沮丧,你救了我的
    • 如何使用 /storage/emulated/0/IDM/Music/xxx.mp3 等路径?即使这是失败的。
    • @jeevs 似乎有什么问题?以上解决方案仍然对我有用。也许您的文件已损坏或在此位置找不到?
    • 当您的文件路径中包含由 %20 表示的空格时,此代码将不起作用(例如 file:///storage/emulated/0/Music/Artist%20(feat.% 20ArtistPart1%20ArtistPart2).mp3),因为 uri 编码会将 %20 替换为空格,但之后 setDataSource 将不起作用。如果我只是删除 Uri.encode 它可以工作,但代价是什么?我还没有看到没有编码部分的代码不起作用但我的测试用例有限的情况。
    【解决方案2】:

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

    【讨论】:

    • 谢谢,没想到是这个错误!之前我调用了上面的重载方法,但这次我不假思索地调用了更简单的方法..
    【解决方案3】:

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

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

    // 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);
    }
    

    【讨论】:

      【解决方案4】:

      这可能是因为您尝试播放或压缩的文件格式。我正在压缩一个运行良好的 mp4 文件,但是当我压缩一个 mov 文件时,应用程序崩溃了,出现了 setDataSource 失败异常。

      【讨论】:

      • 确实如此。它主要与文件格式有关。处理视频文件时,我发现以下视频格式:AVI、MPG/MPEG、MOV、mov、mp4、m4v、flv、WMV,我注意到 AVI、MPG/MPEG 和 WMV 每次都对我抛出异常时间。最好在运行方法之前排除它们并用 try-catch 包装它。
      【解决方案5】:

      我在尝试播放 .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();
           }
          }
      

      我也遇到了 status=0x80000000 错误。在我的情况下,解决方案是重新编码音频文件(例如,将 .wav 文件编码为 16 位 PCM)并且一切都按预期工作。

      【讨论】:

        【解决方案6】:
        MediaPlayer mPlayer = MediaPlayer.create(activity, R.raw.your_wave_audio_file);
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        

        你不能这样做,因为在create函数中调用了prepare,因此你不能改变音频流类型。

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

        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);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-04
          • 1970-01-01
          • 2018-10-26
          相关资源
          最近更新 更多