【问题标题】:Android MediaPlayer full path to fileAndroid MediaPlayer 文件的完整路径
【发布时间】:2011-06-22 21:57:48
【问题描述】:

我需要获取手机某处(任何位置)上某个文件的完整路径,并使用 MediaPlayer 播放它。

我听说过使用 Android 的文件选择器(通过启动意图)。

在测试代码中,我只是将一个资源复制到另一个文件中,获取路径并将其传递给 AudioVideoEntry(我稍后会展示,一个非常简单且精简的 MediaPlayer 包装器)

这是我写的测试代码:

private String ave_path;
    private String ave_file_name = "my_media_content";
    private InputStream ave_fis;
    private OutputStream ave_fos;
    public void testAudioVideoEntry()
    {
        //get the Activity
        Module_JournalEntry journalentryactivity = getActivity();
        //open an InputStream to a resource file (in this case strokes.mp3)
        ave_fis = journalentryactivity.getResources().openRawResource(module.jakway.JournalEntry.R.raw.strokes);

        //open an OutputStream to a new file
        try {
            ave_fos = journalentryactivity.openFileOutput(ave_file_name, 
                                                Context.MODE_PRIVATE);
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
            assertTrue(false);
        }
        catch(Exception e)
        {
            assertTrue(false);
        }

        //copy the data from the resource into
        //the OutputStream
        int data;
        try {
        while((data = ave_fis.read()) != -1)
        {
            ave_fos.write(data);
        }
            assertTrue(true);
        }
        catch(Exception e)
        {
            assertTrue(false);
        }

        //get the full path of the file we wrote to
        ave_path = journalentryactivity.getFileStreamPath(ave_file_name).toString();

        //and construct a new object of AudioVideoEntry with that path
        AudioVideoEntry ave = new AudioVideoEntry(ave_path);

        //register an error listener via MediaPlayer's setOnErrorListener
        ave.setOnErrorListener(new OnErrorListener()
                                {
                                    @Override
                                    public boolean onError(MediaPlayer mp,
                                            int what, int extra) {
                                        Log.e("MEDIAPLAYER ERRORS",
                                        "what: " + what + "  extra: "   + extra);
                                        assertTrue(false);
                                        // TODO Auto-generated method stub
                                        return false;
                                    }
                                });
        ave.prepareMedia();
        ave.playMedia();
        try {
        ave_fis.close();
        ave_fos.close();
        }
        catch(Exception e)
        {
            assertTrue(false);
            e.printStackTrace();
        }

AudioVideoEntry 基本上是 MediaPlayer 的一个薄包装器,可以拥有自己的路径:

public class AudioVideoEntry
{
    private String path_to_audio_file;
    private MediaPlayer mediaplayer;

    /**
     * Initialize the internal MediaPlayer
     * from the String parameter
     * @param set_path_to_audio_file
     */
    public AudioVideoEntry(String set_path_to_audio_file)
    {
        path_to_audio_file = set_path_to_audio_file;
        mediaplayer = new MediaPlayer();
        try {
            mediaplayer.setDataSource(path_to_audio_file);
            mediaplayer.prepare();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public AudioVideoEntry(FileDescriptor fd)
    {

        mediaplayer = new MediaPlayer();
        try {
            mediaplayer.setDataSource(fd);
            mediaplayer.prepare();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }



    /**
     * Begin playing media
     */
    public void prepareMedia()
    {
        try {
            mediaplayer.prepare();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * play media
     * don't forget to prepare() if necessary
     */
    public void playMedia()
    {
        mediaplayer.start();
    }

    /**
     * pause the media
     * can be played later
     */
    public void pauseMedia()
    {
        mediaplayer.pause();
    }

    /**
     * stop media
     */
    public void stopMedia()
    {
        mediaplayer.stop();
    }

    public void setOnErrorListener(OnErrorListener listener)
    {
        mediaplayer.setOnErrorListener(listener);
    }
}

这是 JUnit 测试的 logcat 输出(测试成功,实际结果 - 如 logat 所示 - 不是)

02-07 09:40:23.129: ERROR/MediaPlayer(1209): error (1, -2147483648)
02-07 09:40:23.139: WARN/System.err(1209): java.io.IOException: Prepare failed.: status=0x1
02-07 09:40:23.149: WARN/System.err(1209):     at android.media.MediaPlayer.prepare(Native Method)
02-07 09:40:23.149: WARN/System.err(1209):     at module.jakway.JournalEntry.AudioVideoEntry.<init>(AudioVideoEntry.java:39)
02-07 09:40:23.149: WARN/System.err(1209):     at module.jakway.JournalEntry.test.Module_JournalEntryTest.testAudioVideoEntry(Module_JournalEntryTest.java:182)
02-07 09:40:23.149: WARN/System.err(1209):     at java.lang.reflect.Method.invokeNative(Native Method)
02-07 09:40:23.149: WARN/System.err(1209):     at java.lang.reflect.Method.invoke(Method.java:507)
02-07 09:40:23.159: WARN/System.err(1209):     at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:204)
02-07 09:40:23.159: WARN/System.err(1209):     at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:194)
02-07 09:40:23.159: WARN/System.err(1209):     at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:186)
02-07 09:40:23.159: WARN/System.err(1209):     at junit.framework.TestCase.runBare(TestCase.java:127)
02-07 09:40:23.169: WARN/System.err(1209):     at junit.framework.TestResult$1.protect(TestResult.java:106)
02-07 09:40:23.169: WARN/System.err(1209):     at junit.framework.TestResult.runProtected(TestResult.java:124)
02-07 09:40:23.169: WARN/System.err(1209):     at junit.framework.TestResult.run(TestResult.java:109)
02-07 09:40:23.179: WARN/System.err(1209):     at junit.framework.TestCase.run(TestCase.java:118)
02-07 09:40:23.179: WARN/System.err(1209):     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
02-07 09:40:23.179: WARN/System.err(1209):     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
02-07 09:40:23.179: WARN/System.err(1209):     at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)
02-07 09:40:23.189: WARN/System.err(1209):     at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
02-07 09:40:23.189: ERROR/MediaPlayer(1209): prepareAsync called in state 0
02-07 09:40:23.189: WARN/System.err(1209): java.lang.IllegalStateException
02-07 09:40:23.189: WARN/System.err(1209):     at android.media.MediaPlayer.prepare(Native Method)
02-07 09:40:23.189: WARN/System.err(1209):     at module.jakway.JournalEntry.AudioVideoEntry.prepareMedia(AudioVideoEntry.java:79)
02-07 09:40:23.199: WARN/System.err(1209):     at module.jakway.JournalEntry.test.Module_JournalEntryTest.testAudioVideoEntry(Module_JournalEntryTest.java:197)
02-07 09:40:23.199: WARN/System.err(1209):     at java.lang.reflect.Method.invokeNative(Native Method)
02-07 09:40:23.199: WARN/System.err(1209):     at java.lang.reflect.Method.invoke(Method.java:507)
02-07 09:40:23.199: WARN/System.err(1209):     at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:204)
02-07 09:40:23.199: WARN/System.err(1209):     at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:194)
02-07 09:40:23.199: WARN/System.err(1209):     at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:186)
02-07 09:40:23.199: WARN/System.err(1209):     at junit.framework.TestCase.runBare(TestCase.java:127)
02-07 09:40:23.199: WARN/System.err(1209):     at junit.framework.TestResult$1.protect(TestResult.java:106)
02-07 09:40:23.199: WARN/System.err(1209):     at junit.framework.TestResult.runProtected(TestResult.java:124)
02-07 09:40:23.199: WARN/System.err(1209):     at junit.framework.TestResult.run(TestResult.java:109)
02-07 09:40:23.199: WARN/System.err(1209):     at junit.framework.TestCase.run(TestCase.java:118)
02-07 09:40:23.199: WARN/System.err(1209):     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
02-07 09:40:23.199: WARN/System.err(1209):     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
02-07 09:40:23.199: WARN/System.err(1209):     at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)
02-07 09:40:23.199: WARN/System.err(1209):     at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
02-07 09:40:23.199: ERROR/MediaPlayer(1209): start called in state 0
02-07 09:40:23.199: ERROR/MediaPlayer(1209): error (-38, 0)

编辑:为什么 MediaPlayer 失败了?

谢谢! 龙纹

【问题讨论】:

  • 如果某处有问题,我看不到它......
  • 为什么会出错?

标签: android path media-player


【解决方案1】:

您似乎调用了两次prepare(),第一次在AudioVideoEntry 的构造函数中,第二次在prepareMedia() 方法中,这就是它给出IllegalStateException 的原因。

如果您仔细阅读documentation,您可以理解状态图以及为什么会出现此类异常。

【讨论】:

  • 这解释了 prepareAsync 错误。 AVE 构造函数中仍然存在第一个准备错误。
【解决方案2】:

几点:

  1. 不要调用prepare() 两次(一次在构造函数中,另一次显式调用)。这可能是抛出 IllegalStateException 的原因之一。
  2. 另外,您尝试在应用程序中播放的文件是什么?如果是这样,您为什么要尝试创建流?如果文件已经在应用程序中(并且在/res/raw 中,您可以尝试通过创建媒体播放器对象来省去使用prepare() 的麻烦:

    mediaplayer = new MediaPlayer.create(this, R.raw.resource-name here);

create 函数在内部调用prepare()
3.如果MediaPlayer中的任何一个阶段失败导致MediaPlayer对象进入错误状态,也可以尝试使用reset()函数。使用 reset() 会使其回到空闲状态。
4. 上次我收到错误status=0x1 消息时,发现我没有为文件(Manifest 中的外部存储等)设置正确的权限,并且某些文件放置在不正确的文件夹中。您可能还想看看那个。

如果不起作用,请告诉我,
我们可以试试别的。
斯里拉姆。

【讨论】:

    【解决方案3】:

    AudioVideoEntry.prepareMedia() 方法中对 MediaPlayer.prepare() 的第二次调用(已经在 AudioVideoEntry ctor 中调用过一次)很容易被发现,因为其他人已经注意到了。

    最难发现的错误是第一个错误。

    我使用 Ogg 文件进行测试。

    第一条线索来自android-platform - Ogg on G1davidsparks 的回复(最后一条)

    只要文件具有 .ogg 扩展名,它们就应该使用 内置音乐播放器。我们依赖文件扩展名,因为有 媒体扫描仪没有集中式文件识别器。

    第二条线索来自[android-developers] Re: File permission about MediaPlayer

    由于 Android 安全模型,MediaPlayer 没有 root 访问权。可以访问sdcard,但是不能访问private 应用程序目录。

    您的应用可以明确授予 MediaPlayer 临时访问安全 通过打开文件并将文件描述符传递给 MediaPlayer 使用 setDataSource(FileDescriptor fd) 方法。

    如果您查看输出流的绝对路径,您会发现它位于应用程序包名称目录下的/data/data 目录中。

    请原谅时间戳 - 我向后工作以获取要在 OS2.1update1 (API7) 模拟器上显示的数据。

    您的代码有:

    String ave_file_name = "my_media_content";
    
    ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_PRIVATE);
    

    DDMS 显示:

    02-10 05:10:28.253: WARN/MediaPlayer(1992): info/warning (1, 26)
    02-10 05:10:28.253: ERROR/PlayerDriver(31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
    02-10 05:10:28.253: ERROR/MediaPlayer(1992): error (1, -4)
    02-10 05:10:28.274: WARN/PlayerDriver(31): PVMFInfoErrorHandlingComplete
    

    如果我们将文件更改为 MODE_WORLD_READABLE:

    String ave_file_name = "my_media_content";
    
    ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_WORLD_READABLE);
    

    DDMS 没有改善:

    02-10 05:08:28.543: WARN/MediaPlayer(1900): info/warning (1, 26)
    02-10 05:08:28.553: ERROR/PlayerDriver(31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
    02-10 05:08:28.553: ERROR/MediaPlayer(1900): error (1, -4)
    02-10 05:08:28.563: WARN/PlayerDriver(31): PVMFInfoErrorHandlingComplete
    

    如果我们将JUST文件扩展名更改为ogg

    String ave_file_name = "my_media_content.ogg";
    
    ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_PRIVATE);
    

    我们得到了 DDMS 输出的变化:

    02-10 04:59:30.153: ERROR/MediaPlayerService(31):   error: -2
    02-10 04:59:30.163: ERROR/MediaPlayer(1603): Unable to to create media player
    

    但是当我们将两者结合

    String ave_file_name = "my_media_content.ogg";
    
    ave_fos = activity.openFileOutput(ave_file_name, Context.MODE_WORLD_READABLE);
    

    DDMS 没有显示错误。

    【讨论】:

      猜你喜欢
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-21
      • 2014-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多