MediaPlayer(4024): error (1, -2147483648)解決辦法
遇到此問題setDataSource用FileDescriptor代替即可,如下面紅色的程式碼。
MediaPlayer player = new MediaPlayer();
try {
Log.d(TAG, recorder.getFileName());
player.setAudioStreamType(AudioManager.STREAM_RING);
FileInputStream fis = new FileInputStream(new File(filePath));
player.setDataSource(fis.getFD());
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.stop();
mp.release();
}
});
player.setLooping(false);
player.prepare();
player.setVolume(1f, 1f);
player.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
將媒體檔案push到sdcard目錄
啟動模擬器後,在DDMS透檢視中,選擇File Explorer,選擇/mnt/sdcard目錄,點選檢視工具欄的+,將選擇的檔案push進去。
注:如果push失敗,提示Read-Only File System,請將sdcard目錄授以讀+寫許可權,命令為
- $ adb shell mount -o remount rw /
使用ls -l檢視指定目錄下的檔案及資料夾詳細資訊,許可權資訊在第一列。如
Python程式碼- $ adb shell
- # ls -l /mnt/sdcard
注:在File Explorer中,已經列出了各資料夾和檔案的許可權。如果sdcard沒有讀寫許可權,請先授權。
使用VideoView渲染媒體
為什麼要用VideoView?VideoView使用起來簡單,而且封裝了播放器,如播放錯誤,android會給出警告提示 ,不需要使用者程式設計處理這些異常。程式碼如下:
Java程式碼- viedoView.setVideoPath(filePath);//filePath = “/sdcard/test.mp3”;
- videoView.start();
簡單是簡單,但不幸的是,如果媒體源沒問題,但播放異常的話,定位就複雜一些了。
注:啟動後,系統提示”對不起,該視訊無法播放“,在LogCat中看到MediaPlayer和VideoView都指列印了一條error(1, -2147483648)的LOG。
導致此錯誤的典型原因有:
1,檔案路徑不對,如目錄錯誤,不存在的URL及URI
2,媒體檔案錯誤,或不支援的格式
3,缺少許可權
經過debug,發現問題出在VideoView#openVidio的mMediaPlayer.prepareAsync();處。
prepare失敗了,prepare的方法有兩個,還有一個是prepare(),官網給的說明,它位的不同之處是,前者是非同步執行。但個人認為,應該還有一個不同之處,前者不會丟擲異常。
使用MediaPlayer
使用MediaPlayer也很簡單。如下程式碼所示:
Java程式碼- MediaPlayer mp = new MediaPlayer();
- mp.setDataSource(this,uri);
- mp.prepare();// 使用mp.prepareAsync(),不會丟擲異常,但有錯誤LOG,為error(38,0);
- mp.start();
注:對上面那個無法播放的問題,可以在prepare()處捕獲到IO異常:
- java.io.IOException: Prepare failed.: status=0x1
對於此異常,有網友說模擬器對mp3支援不好,建議將mp3換成ogg格式再試。也有的說,使用類似以下方法 Java程式碼
- // FileInputStream fis = new FileInputStream(file);
- // mp.setDataSource(fis.getFD());
前者我沒有試過,如果有度過的,請告訴我結果。我使用的是後者,發現在建立輸入流時,丟擲了FileNotFoundException:file not exists(permission denied),關鍵在permission denied這句,應該是缺少許可權,但媒體檔案是有許可權的,sdcard目錄沒有,於是給sdcard目錄授以最大許可權。
- $ adb shell
- # chmod 777 /mnt/sdcard
討論
討論1:在準備工作中,已經使用
Python程式碼- $ adb shell mount -o remount rw /
或
Python程式碼- $ adb shell mount -o remount 777 /
給目錄授權過了,但為何sdcard目錄還是無許可權?
討論2:Android對網路播放是否存在bug,對於本地可以正常播放的3gp,mp4等視訊,放到伺服器中使用http get方式進行網路播放,卻只有少數片源可以播放,大多數在prepare()時就丟擲了異常。