2013-09-24 96 views
7

在閱讀「Media Playback」和「MediaPlayer」android文檔後,我仍然感到困惑,需要關於setDataSource重載方法的有經驗的建議。MediaPlayer setDataSource需要最佳實踐建議

我正在使用MediaPlayer在我的項目中的Service組件中,播放音樂時將會是foregroundService。我的我的音樂文件(.mp3)在我的apk的res/raw文件夾中。 要開始播放,我知道我必須準備MediaPlayer對象。由於默認情況下android應用程序中的服務使用單個進程和主線程,因此我不希望我的用戶在MediaPlayer準備好自己的時候獲得ANR (假設原始文件夾中的媒體文件具有較大的大小)。 然後我用prepareAsync代替prepare(同步)。所以我不能使用:

mp = MediaPlayer.create(context, R.raw.myfile); 

因爲這已經呼籲prepare()內部而不是prepareAsync()。 所以基本上我有兩個選擇(二從四個):

mp.prepareAsync(); 

最後我的問題出現了:

Uri myUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.myfile); 
mp.setDataSource(context, myUri); 

AssetFileDescriptor afd = context.getResources().openRawResourceFd(R.raw.myfile); 
mp.setDataSource(fd.getFileDescriptor()); 
afd.close(); 

使用其中的一個,我可以簡單的使用後「包括這些不同的方法,哪一個是最好的選擇?是否有任何好處,我錯過了什麼?」

+0

個人而言,我喜歡最後一種方法,因爲它不在代碼中使用字符串。儘管如此,如果這不算「利益」的話。 – Geobits

+0

@Geobits,避免代碼中的常量字符串是一個很好的做法,但我知道,但'FileDescriptor'是android喜歡的本地文件。感謝您的評論。我建議你閱讀我對接受答案的評論。 –

回答

7

對調用createsetDataSource的各種方式沒有任何實際好處。靜態的create方法所做的並不多於呼叫setDataSourceprepare。各種setDataSource方法在內部互相調用。最終他們歸結爲兩個可能的本地調用,一個使用描述遠程URI的字符串,另一個使用本地文件描述符。自己創建文件描述符可能會有非常小的性能優勢,但在上下文中不會很明顯。

對於本地文件播放,正如您在代碼中演示的那樣,只需調用prepare(或靜態的create方法)根本不是一個壞習慣。底層的播放器在確定相關的元數據時應該沒有問題,無論文件的大小如何都可以快速返回。對於網絡流,prepareAsync方法更有用,任何數量的情況都可能導致一些意外的延遲。如果您正在設計一個通用玩家,那麼使用prepareAsync方法將是一條可行的路線,但如果您只是玩原始資產,那麼它應該沒有什麼區別。提供的各種方法只是一個方便的事情(請注意javadoc的create)。

+0

在閱讀你的答案之後,我查看了[android framework](https://github.com/android/platform_frameworks_base/blob/master/media/java/android/media/MediaPlayer.java),並理解你所說的。我看到'private native void _setDataSource'方法,並注意到'setDataSource(FileDescriptor fd,long offset,long length)'方法對於本地訪問更爲常見。爲了遠程(流)的目的,我粗略地推導了本地和'Uri'的'FileDescriptor'。 –