2015-01-10 72 views
2

我目前正在嘗試製作音頻媒體播放器。我目前正在運行棒棒糖。我遇到了爲媒體播放器設置dataSource的問題。首先,這裏是我如何設置DataSource:Android - 將URI轉換爲棒棒糖上的文件路徑

public void playSong() { 
    player.reset(); 
    Song selSong = songs.get(songPos); 
    long currSong = selSong.getId(); 
    //Get Uri of song 
    Uri trackUri = ContentUris.withAppendedId(
      MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, currSong); 
    try { 
     //Tell the player the song to play 
     player.setDataSource(getApplicationContext(), trackUri); 
    } catch (Exception e) { 
     Log.e("MUSIC SERVICE", "Error setting data source", e); 
     Log.d("URI Path", trackUri.toString()); 
    } 

    //Will prepare the song and call onPrepare of player 
    player.prepareAsync(); 
} 

和URI出來這樣:

content://media/external/audio/media/22

我做了一些研究,並從我的理解,之後的Android 4.1,你可以不再使用數據源的URI。當我運行這個程序與上面的代碼,我會得到這個錯誤:

E/MediaPlayer﹕ Unable to create media player 
E/MUSIC SERVICE﹕ Error setting data source 
    java.io.IOException: setDataSource failed.: status=0x80000000 
      at android.media.MediaPlayer.nativeSetDataSource(Native Method) 

所以現在我需要將URI轉換爲文件路徑,並提供爲數據源。而且,經過更多研究,似乎kitkat改變了URI的提供方式,所以很難從URI獲取文件路徑。不過,我不確定此更改是否持續存在於Android Lollipop 5.0.2中。基本上,我有一首歌曲的URI,但我需要提供除URI之外的其他內容給dataSource。有什麼方法可以轉換棒棒糖上的URI,如果沒有,我怎麼才能提供數據源只知道歌曲的ID?謝謝。

+1

「我做了一些研究,並從我的理解,在Android 4.1之後,你不能再使用數據源的URI「 - 請引用。如果有的話,反過來也是如此 - 你不能假定文件路徑會起作用。 「當我用上面的代碼運行這個應用時,我會得到這個錯誤」 - 如果你正在測試Android 4.4+,添加'READ_EXTERNAL_STORAGE'權限。 「似乎kitkat改變了URI的提供方式,因此很難從URI獲取文件路徑」 - 並不要求Uri是文件,更不用說可以訪問的文件了。 – CommonsWare

+0

當然,我會看看我是否能找到我發現那個聲明的地方。我只是假定它是正確的,因爲我的URI不起作用。我具有READ_EXTERNAL_STORAGE權限以及INTERNET。 – user2082169

+0

這裏是我閱讀URI的地方。我可能誤解了。他說,在Android 4.1.1上,如果使用傳入字符串的構造函數,則需要使用本地路徑。 http://stackoverflow.com/questions/16395559/mediaplayer-setdatasource-failed-with-status-0x80000000-for-ringtone-set-by-file/22152628#22152628 – user2082169

回答

0

棒棒堂決定採取另一個課程從系統獲取文件。 (有人說它來自KitKat,但我還沒有在KitKat上遇到它)。下面的代碼是得到棒棒糖的文件路徑

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && isMediaDocument(uri)) 
    { 
     final String docId = DocumentsContract.getDocumentId(uri); 
     final String[] split = docId.split(":"); 
     final String type = split[0]; 

     Uri contentUri = null; 
     if ("audio".equals(type)) 
     { 
      contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
     } 

     final String selection = "_id=?"; 
     final String[] selectionArgs = new String[] { 
       split[1] 
     }; 

     String filePath = getDataColumn(context, contentUri, selection, selectionArgs); 
    } 

isMediaDocument:

public static boolean isMediaDocument(Uri uri) 
{ 
    return "com.android.providers.media.documents".equals(uri.getAuthority()); 
} 

getDataColumn:

private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) 
{ 
    Cursor cursor = null; 
    final String column = "_data"; 
    final String[] projection = { 
      column 
    }; 

    try { 
     cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); 
     if (cursor != null && cursor.moveToFirst()) 
     { 
      final int column_index = cursor.getColumnIndexOrThrow(column); 
      return cursor.getString(column_index); 
     } 
    } finally { 
     if (cursor != null) 
      cursor.close(); 
    } 
    return null; 
} 

如果你還有問題,this是檢查圖像的完整的答案,音頻,視頻,文件等

+0

這個解決方案似乎不適合我。雲端硬盤文件似乎有一個空的_data列。 https://code.google.com/p/android/issues/detail?id=63651 –

+0

@hhoang嗯,這很奇怪,如果我有這個星期的任何時間,我會尋找答案 –

+0

只是爲了澄清,它似乎是當發送的內容URI不實際存儲在設備上時,_data將爲空。例如,如果我試圖分享存儲在雲端的谷歌照片應用程序的照片。 _data列將爲空。我發現的唯一工作是複製文件,然後將新文件的絕對路徑傳遞迴我的活動。但是,我不確定這是否是最好的方法。我在這裏寫了一個SO問題,如果你可以看看。 http://stackoverflow.com/questions/29378651/get-filepath-from-google-drive-in-lollipop-mediastore-mediacolumns-data-null –