Android MediaPlayer文件的完整路径

时间:2011-02-07 17:46:18

标签: android path media-player

我需要在手机(任何位置)的某个地方获取文件的完整路径并使用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失败?

谢谢! dragonwrenn

3 个答案:

答案 0 :(得分:11)

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

找到更难的错误是第一个错误。

我使用了一个Ogg文件进行测试。

第一个线索来自android-platform - Ogg on G1

中的davidsparks回复(最后一个)
  

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

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

  

由于Android安全模型,MediaPlayer没有root   访问权限。它可以访问SD卡,但无法访问私有   app目录。

     

您的应用可以明确授予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

如果我们将 JUST 文件更改为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没有显示错误。

答案 1 :(得分:3)

有些观点:

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

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

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

    如果不起作用,请告诉我,
    我们可以尝试其他的东西 斯利拉姆。

答案 2 :(得分:0)

您似乎正在调用prepare()两次,首先是AudioVideoEntry的构造函数,第二个是方法prepareMedia(),这就是为什么它会给IllegalStateException

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