首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 簡單音頻播放器實現與常見問題排查

     編輯:程式設計綜合問答

在 Android 中使用 MediaPlayer 實現簡單音頻播放,需注意文件路徑、權限、異步準備等關鍵點,否則會出現無聲音、崩潰等問題。

問題代碼分析

MediaPlayer mp = new MediaPlayer();
mp.setDataSource("/home/usr/audio/file.mp3"); // 錯誤:電腦路徑非手機路徑
mp.prepare(); // 同步準備會阻塞主線程
mp.start();

核心問題

  1. 路徑錯誤:/home/usr/... 是 Linux/電腦路徑,Android 設備無此路徑
  2. 缺少權限:讀取外部存儲需 READ_EXTERNAL_STORAGE 權限
  3. 同步準備阻塞 UI:prepare() 在主線程執行會導致 ANR
  4. 未處理錯誤回調:無 OnErrorListener、OnCompletionListener

正確實現方案

1. 正確的文件路徑

// 原始資源 (res/raw/)
mp = MediaPlayer.create(this, R.raw.music);

// Assets 目錄
AssetFileDescriptor afd = getAssets().openFd("music.mp3");
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());

// 外部存儲 (需權限)
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC), "music.mp3");
mp.setDataSource(file.getAbsolutePath());

// 網絡流媒體
mp.setDataSource("https://example.com/music.mp3");

2. 異步準備(避免 ANR)

mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start(); // 準備完成後自動播放
    }
});
mp.prepareAsync(); // 異步準備,不阻塞主線程

3. 完整播放器封裝類

public class SimpleAudioPlayer {
    private MediaPlayer mediaPlayer;
    private Context context;
    
    public SimpleAudioPlayer(Context context) {
        this.context = context;
    }
    
    public void playRawResource(@RawRes int resId) {
        release();
        mediaPlayer = MediaPlayer.create(context, resId);
        mediaPlayer.setOnCompletionListener(mp -> release());
        mediaPlayer.start();
    }
    
    public void playFile(String filePath) {
        release();
        try {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(filePath);
            mediaPlayer.setOnPreparedListener(mp -> mp.start());
            mediaPlayer.setOnCompletionListener(mp -> release());
            mediaPlayer.setOnErrorListener((mp, what, extra) -> {
                release();
                return true;
            });
            mediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void pause() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        }
    }
    
    public void release() {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
    
    public boolean isPlaying() {
        return mediaPlayer != null && mediaPlayer.isPlaying();
    }
}

4. AndroidManifest 權限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- 後台播放需前台服務 -->

模擬器測試注意事項

  • 模擬器支持音頻播放,需在 Extended Controls 中啟用音頻
  • 文件需推送到模擬器:adb push music.mp3 /sdcard/Music/
  • 模擬器 SD 卡路徑通常為 /sdcard/ 或 /storage/emulated/0/

現代替代方案

  • ExoPlayer:Google 官方媒體播放庫,功能強大、支持 DASH/HLS、自適應碼率
  • Media3 (Jetpack):新一代媒體框架,整合 ExoPlayer、MediaController、MediaSession
  • Service + MediaSession:後台播放、鎖屏控制、藍牙耳機控制的標準架構

簡單播放器選型建議

場景推薦方案
簡單音效、短音頻SoundPool / MediaPlayer.create()
音樂播放器 AppExoPlayer + MediaSession + Foreground Service
網絡電台、直播流ExoPlayer (支持 HLS/DASH)
短視頻、視頻播放ExoPlayer / Media3
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved