2011-02-07 247 views
2

我需要獲取手機某處文件的完整路徑(任意位置)並使用MediaPlayer播放。Android MediaPlayer文件的完整路徑

我聽說過使用Android的文件選擇器(通過啓動一個intent)。

在測試代碼中,我只是複製的資源到另一個文件,得到了路徑,將其傳遞給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); 
    } 
} 

這裏的logcat的輸出F ROM JUnit測試(測試是成功的,實際的結果 - 作爲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

+0

如果在那裏有一個問題,我沒有看到它... – androidworkz 2011-02-07 18:13:14

+0

爲什麼我得到錯誤? – Prime 2011-02-08 03:49:15

回答

11

在AudioVideoEntry.prepareMedia()方法中,第二次調用MediaPlayer.prepare()(已在AudioVideoEntry ctor中調用一次)很容易被其他人發現。

找到更難的錯誤是第一個錯誤。

我用一個Ogg文件進行測試。

第一條線索是從davidsparks在android-platform - Ogg on G1

回覆(最後一個)只要文件具有.OGG擴展,就應該有內置的音樂播放器的播放 。我們依靠文件擴展名,因爲 沒有用於媒體掃描器的集中式文件識別器。

第二線索是從[android-developers] Re: File permission about MediaPlayer

由於Android的安全模型,MediaPlayer的沒有根 訪問權限。它可以訪問SD卡,但它不能訪問私人應用目錄 。

您的應用程序可以明確授予的MediaPlayer臨時訪問使用的setDataSource(FD FileDescriptor的)方法打開文件並通過文件描述符 的MediaPlayer,以確保 文件。

如果你看看輸出流的絕對路徑,你會發現它在應用程序包名稱目錄下的/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顯示沒有錯誤。

0

看來你在呼喚prepare()兩次,第一次在AudioVideoEntry構造,和第二的方法prepareMedia(),這就是爲什麼它給一個IllegalStateException

如果您仔細閱讀documentation您可以瞭解狀態圖以及爲什麼會給出這種例外。

+0

解釋了prepareAsync錯誤。在AVE構造函數中仍然有第一個準備錯誤。 – 2011-02-10 08:45:01

3

幾點:

  1. 別叫prepare()兩次(一次是在構造函數和其他明確)。這可能是導致IllegalStateException的原因之一。
  2. 此外,您正在試圖在應用程序內播放的文件?如果是這樣,你爲什麼要創建一個流?如果該文件已經在應用程序中(以及內/res/raw,你可以嘗試通過創建MediaPlayer對象,像這樣保存自己使用prepare()的麻煩:

    媒體播放器=新MediaPlayer.create(這一點,R.raw.resource -name這裏);

的創建函數中調用prepare()
3.您還可以嘗試使用reset()功能,如果在MediaPlayer的階段中的任何一個發生故障導致MediaPlayer對象進入錯誤。狀態。使用reset()會使其回到空閒狀態。
4.最後一次發生錯誤status=0x1消息,事實證明我沒有爲文件(Manifest中的外部存儲等)設置正確的權限,某些文件放置在不正確的文件夾中。你可能也想看看這個。

讓我知道萬一不行,
我們可以試試別的。
Sriram。