2011-12-01

在 Android 裡播放音樂(MediaPlayer)

Android 提供兩個播放聲音的類別,用播放音樂檔的 MediaPlayer 和播放音效檔的 SoundPool,這邊要練習的是 MediaPlayer。

請先參考 在 Android 裡讀取 SD 卡裡的檔案在 Android 裡使用 ListActivity, ListView, ListAdpater,將 SD 卡裡的 MP3 以 ListView 的方式呈現。

main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@android:id/list" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />
    <TextView
        android:id="@android:id/empty" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="查無曲目" />

</LinearLayout>
MediaPlayerActivity
public class MediaPlayerActivity extends ListActivity implements
        OnItemClickListener {

    private static final String TAG = "MediaPlayerActivity";
    private Map<String, String> filePathMap;
    private MediaPlayer mp;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        this.setListAdapter(this.createListAdapter());
        ListView lv = (ListView) this.findViewById(android.R.id.list);
        // 註冊點擊播放效果
        lv.setOnItemClickListener(this);
    }

    private ListAdapter createListAdapter() {
        File sdCardDir = Environment.getExternalStorageDirectory();
        File musicDir = new File(sdCardDir, "music");
        File wuDir = new File(musicDir, "伍佰&China Blue_單程車票");
        // TODO - 未區別是否為可播放之檔案格式
        File[] files = wuDir.listFiles();
        List<String> list = new ArrayList<String>();
        this.filePathMap = new HashMap<String, String>();
        for (File f : files) {
            if (f.isFile()) {
                // 在 ListView 上顯示檔案名稱
                list.add(f.getName());
                // 保留完整路徑,供稍後播放使用
                this.filePathMap.put(f.getName(), f.getAbsolutePath());
                this.log("取得..." + f.getAbsolutePath());
            }
        }
        String[] data = list.toArray(new String[] {});
        // 使用 Android 內建的 ListView item 格式
        return new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, data);
    }

    @Override
    public void onItemClick(AdapterView<?> av, View iv, int position, long id) {
        String fileName = ((TextView) iv).getText().toString();
        // 取得完整路徑
        String filePath = this.filePathMap.get(fileName);
        this.log("click " + filePath);
        // 若正在播放,先停掉
        this.stopPlay();
        // 播放
        try {
            this.log("play " + fileName);
            // 不同於 SoundPool,每一首歌都得使用全新的 MediaPlayer
            this.mp = new MediaPlayer();
            this.mp.setDataSource(filePath);
            this.mp.prepare();
            this.mp.start();
        }
        catch (IllegalArgumentException e) {
            Log.e(TAG, e.getMessage(), e);
        }
        catch (IllegalStateException e) {
            Log.e(TAG, e.getMessage(), e);
        }
        catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        this.log("onPause...");
        this.stopPlay();
    }

    @Override
    protected void onResume() {
        super.onResume();
        this.log("onResume...");
    }

    private void stopPlay() {
        if (this.mp != null) {
            if (this.mp.isPlaying()) {
                this.log("stop the current play");
                this.mp.stop();
            }
        }
    }

    private void log(String msg) {
        Log.d(TAG, msg);
    }
}

MediaPlayer 有一些使用注意事項:
  • 暫停播放用 pause(),停止播放用 stop(),連續播放用 setLooping()。
  • 播放中如果按下 Home 或其他功能離開,音樂會繼續播放。
  • MediaPlayer 不用時要呼叫 release() 來釋放資源,呼叫的時機有 onPause() 或者 onDestroy(),onPause()  是一離開馬上停止播放,onDestroy() 是關閉該 app 時才停止。
  • 暫停播放後要繼續播放,要先呼叫 prepare() 後再呼叫 start()。

相關文章

    沒有留言:

    張貼留言