接續上篇: 花栗鼠柑仔店: Android筆記: 讀書心得#11
參考資料: Amazon.com: Hello, Android: Introducing Google's Mobile Development Platform (Pragmatic Programmers) (9781934356562): Ed Burnette: Books
這段內容主要為:
第5章 多媒體
5.3 在數獨遊戲中加入聲音
[Note: 是否應該使用背景服務來播放背景音樂?]
5.4 本章回顧
5.3 在數獨遊戲中加入聲音
在這一小節, 我們將活用上一小節學到的東西, 加入一些背景音樂到先前已經建立好的數獨遊戲. 我們這邊要做的是在開場選擇畫面時先播放一首音樂, 實際遊戲時播放另外一首. 這邊展示的不僅是如何播放音樂, 更有一些程式執行時與音樂播放的考量. 要加入音樂到主畫面, 很簡單只要的覆寫Sudoku類別的兩個方法:
## src/org/example/sudoku/Sudoku.java
@Override
protected void onResume() {
super.onResume();
Music.play(this, R.raw.main);
}
@Override
protected void onPause() {
super.onPause();
Music.stop(this);
}
假如你回想在第二章所學到的, onResume()方法是在當Activity準備好跟使用者互動時會被呼叫, 這是一個開始播放音樂的一個好位子, 所以我們放一個Music.play()呼叫在這裡, Music類別待會會說明. 而R.raw.main參考至res/raw/main.mp3, 要自行複製main.mp3至res/raw/目錄.
[Note: 是否應該使用背景服務來播放背景音樂?]
從一開始到現在我們沒有提到有關Android Service類別, 但或許你在網路上其他的音樂播放範例中已經有見過. 基本上, Service是一個啟動背景程序(background process)的方式, 讓其甚至可以在現在的Activity結束後仍持續執行. Services也類似Linux的背景服務(daemons), 但不完全一樣. 假如你要寫一個一般用途的音樂播放程式, 讓你在閱讀郵件與瀏覽網頁時仍能夠繼續播放音樂, 假如是這樣的需求, 那你就需要使用Service來實作. 但一般的情況, 你只希望你的程式結束時, 音樂也停止播放, 那就不需要用到Service類別.
onPause()方法與onResume()方法是成對的, Android在重新開始(resume)一個新的Activity前會先暫停(pause)目前的Activity. 所以在我們Sudoku的範例中, 假如我們開始一個新遊戲, 那Sudoku activity會先被暫停, 然後啟動Game activity. onPause()在使用者按下Back或Home鍵時也會被呼叫, 這些地方大概就是我們想要讓我們主音樂停止的地方, 所以程式碼在onPause()中呼叫Music.stop().
我們在Game activity裡面加入一樣音樂播放的程式碼:
## src/org/example/sudoku/Game.java
@Override
protected void onResume() {
super.onResume();
Music.play(this, R.raw.game);
}
@Override
protected void onPause() {
super.onPause();
Music.stop(this);
}
假如你比對這段程式與之前我們加入到Sudoku類別的程式, 你會發現我們在音樂播放的部分指定到不同的音樂檔R.raw.game (res/raw/game.mp3). 最後一個部分是Music類別, 這部份主要管理MediaPlayer類別, 用來播放現在指定的音樂:
## src/org/example/sudoku/Music.java
package org.example.sudoku;
import android.content.Context;
import android.media.MediaPlayer;
public class Music {
private static MediaPlayer mp = null;
/** Stop old song and start new one */
public static void play(Context context, int resource) {
stop(context);
mp = MediaPlayer.create(context, resource);
mp.setLooping(true);
mp.start();
}
/** Stop the music */
public static void stop(Context context) {
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
}
}
play()方法首先呼叫stop()方法來停止目前正在播放的任何音樂, 接下來, 用MediaPlayer.create()建立一個新的MediaPlayer實體, 傳入一個程式資源本體(Context, http://developer.android.com/reference/android/content/Context.html, 用來存取整個程式資源的介面)與資源ID(resouce ID).
在我們有一個player後, 我們可以設定一個選項setLooping(true)讓其一直重複播放, 接下來就直接呼叫start()播放. stop()方法很簡單, 主要是檢查是否有MediaPlayer存在,先呼叫暫停stop()再將其釋放release(), MediaPlayer.stop()主要用來暫停目前正在播放的音樂, MediaPlayer.release() 用來釋放跟player相關的系統資源, 這些資源主要是原生碼(native code), 無法經由正常的Java 垃圾收集回收(garbage collection). 假如省略了release()是一個可以讓你的程式無預警出垂的好方法. (謹記)
接下來是比較有趣的部分 -- 試著玩一下數獨遊戲, 看看有哪一些改變. 做一些你能想到的壓力測試, 如切換不同的activity, 在不同的程式點按一下Back鍵或Home鍵, 開始程式當其已經執行到某一個點, 翻轉銀幕, 等等. 嚴謹的程式生命週期管理有時候很煩人, 但你的使用者會感謝你做出這些努力的.
5.4 本章回顧
在這章我們說明了如何用Android SDK播放聲音跟影片, 但沒有提到錄音的部分, 大部分的程式比較不需要用到錄音, 假如有需要的話, 可以參考線上文件有關MediaRecoder部分(http://developer.android.com/reference/android/media/MediaRecorder.html)
接下來第六章會提到如何將程式資料儲存, 在程序之間分享, 第七章會提到如何使用網路存取資料.
沒有留言:
張貼留言