Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android多媒體-MediaPlayer喚醒鎖及音頻焦點

Android多媒體-MediaPlayer喚醒鎖及音頻焦點

編輯:關於Android編程

MediaPlayer的喚醒鎖


  一般使用MediaPlayer播放音頻流,推薦使用一個Service來承載MediaPlayer,而不是直接在Activity裡使用。但是Android系統的功耗設計裡,為了節約電池消耗,如果設備處於睡眠狀態,系統將試圖降低或者關閉一些沒設備必須的特性,包括CUP和Wifi硬件,然後,如果是一個後台播放音樂的應用,降低CUP可能導致在後台運行的時候干擾音頻的正常播放,關閉Wifi將可能導致網絡音頻流的獲取出現錯誤。

  為了確保MediaPlayer的承載的服務在系統睡眠的時候繼續正常運行下去,Android為我們提供了一種喚醒鎖(wake locks)的機制。它可以在系統睡眠的,依然保持鎖定硬件的正常工作。

  確保在MediaPlayer運行的時候,哪怕系統睡眠了CUP也能正常運行,需要使用MediaPlayer.setWakeMode()為MediaPlayer設定喚醒鎖。下面是setWakMode()的簽名:
  setWakeMode(Context context, int mode)

  第一個參數是當前上下文,第二個參數為需要加鎖的狀態,被設定為int類型的常量,定義在PowerManager這個final類中。PowerManager是專門用來管理Android功率消耗的鎖定狀態,與鎖定CUP相關的,有四種,分別設定CUP、屏幕、鍵盤等的各種保持喚醒的狀態,在這裡只需要設定為PARTIAL_WAKE_LOCK即可。

mediaPlayer = new MediaPlayer();
// 設定CUP鎖定
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
一般對於鎖而言,鎖定了通常需要解鎖,但是這裡的喚醒說與MediaPlayer關聯,所以只需要在使用完之後release()釋放MediaPlayer即可,無需顯式的為其解鎖。在使用setWakeMode設定喚醒鎖的時候,還必須為應用賦予相應的權限:

再來說說如何鎖定wifi硬件在系統睡眠的時候保持正常運行。wifi鎖通過WifiLock進行操作,而WifiLock通過WifiManager進行管理,通過WifiManager.createWifiLock()進行Wifi鎖定。

    WifiManager.WifiLock createWifiLock(int lockType, String tag)

  這個方法有多個重載,這裡介紹的這個,第一個參數設定鎖的狀態,為一個int類型的常量,定義在Context類中,這裡的應用場景一般設定為WIFI_MODE_FULL即可。第二個參數為WifiLock的標志,用於確定wifiLock的。

wifiLock= ((WifiManager) getSystemService(this.WIFI_SERVICE)).createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();                 
當然,在應用中把Wifi鎖定之後,還需要在MediaPlayer.release()的時候為wifi硬件解鎖,為避免意外關閉的情況,最好在Android組件的onDestory()裡對其進行釋放,釋放Wifi鎖使用WifiLock.release()。

/**
* 停止播放
*/
 protected void stop() {
	if (mediaPlayer != null && mediaPlayer.isPlaying()) {
              mediaPlayer.stop();
              mediaPlayer.release();
              mediaPlayer = null;
              // 釋放wifi鎖
             wifiLock.release();
             btn_play.setEnabled(true);
             Toast.makeText(this, "停止播放", 0).show();
         }
 
     }
 
     @Override
     protected void onDestroy() {
         // 在activity結束的時候回收資源
         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
             mediaPlayer.stop();
             mediaPlayer.release();
             mediaPlayer = null;
             // 釋放wifi鎖
             wifiLock.release();
         }
         super.onDestroy();
     }

MediaPlayer的音頻焦點


  眾所周知,Android是一個多任務的操作系統,所以對於音頻的播放,也許有幾個不同的媒體服務會同時播放,這樣可能導致一個比較雜亂的聲音環境,而錯過一些重要的聲音提醒。在Android2.2之後,Android提供了一種應用協商使用設備音頻輸出的機制,這種機制稱為音頻焦點。


  當應用程序需要輸出音頻或通知的時候,需要請求音頻焦點,當請求得到音頻焦點之後,監聽音頻焦點的變換,當音頻焦點變換了,根據返回回來的音頻焦點碼進行相應的處理。音頻焦點的注冊使用音頻管理器的AudioManager.requestAudioFocus()方法設定。它的簽名如下:


    int requestAudioFocus(AudioManager.OnAudioFocusChangeListener l, int streamType, int durationHint)


  這個方法的返回值是int類型,其含義被定義在AudioManager中以常量表示AUDIOFOCUS_REQUEST_FAILED(獲取音頻焦點成功)、AUDIOFOCUS_REQUEST_GRANTED(獲取音頻焦點失敗)。其中重要的是第一個參數,為音頻焦點變化的回調函數,在其中可以設定如果音頻焦點變換了,當前應用如何管理MediaPlayer,第二個參數為媒體流的類型,第三個參數為持續的狀態。


  AudioManager.OnAudioFocusChangeListener為音頻焦點變換的監聽器,其中需要實現一個方法:onAudioFocusChange(int focusChange)在音頻焦點變換的時候回調。它有一個參數,為當前表示音頻焦點對於當前應用的狀態碼,通過這個狀態碼指定對應的操作,有些時候音頻狀態改變了,並不一定需要停止音頻的播放。


  focusChange有一下幾種狀態碼:


AUDIOFOCUS_GAIN:獲得音頻焦點。
AUDIOFOCUS_LOSS:失去音頻焦點,並且會持續很長時間。這是我們需要停止MediaPlayer的播放。
AUDIOFOCUS_LOSS_TRANSIENT:失去音頻焦點,但並不會持續很長時間,需要暫停MediaPlayer的播放,等待重新獲得音頻焦點。
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:暫時失去音頻焦點,但是無需停止播放,只需降低聲音方法。

 audioManager = (AudioManager) getSystemService(this.AUDIO_SERVICE);
 int result = audioManager.requestAudioFocus(
	  new OnAudioFocusChangeListener() {

	      @Override
	     public void onAudioFocusChange(int focusChange) {
	          switch (focusChange) {
	          case AudioManager.AUDIOFOCUS_GAIN:
	              // 獲得音頻焦點
	             if (!mediaPlayer.isPlaying()) {
	                 mediaPlayer.start();
	             }
	             // 還原音量
	             mediaPlayer.setVolume(1.0f, 1.0f);
	             break;

	         case AudioManager.AUDIOFOCUS_LOSS:
	             // 長久的失去音頻焦點,釋放MediaPlayer
	             if (mediaPlayer.isPlaying())
	                 mediaPlayer.stop();
	             mediaPlayer.release();
	             mediaPlayer = null;
	             break;

	         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
	             // 展示失去音頻焦點,暫停播放等待重新獲得音頻焦點
	             if (mediaPlayer.isPlaying())
	                 mediaPlayer.pause();
	             break;
	         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
	             // 失去音頻焦點,無需停止播放,降低聲音即可
	             if (mediaPlayer.isPlaying()) {
	                 mediaPlayer.setVolume(0.1f, 0.1f);
	             }
	             break;
	         }
	     }
	 }, AudioManager.STREAM_MUSIC,
	 AudioManager.AUDIOFOCUS_GAIN);

總結


  以上就講解了MediaPlayer的一些高級的內容,在掌握了MediaPlayer的使用之後,開發有關音樂播放類的應用的時候就可以得心應手了。從用戶體驗的方面出發,如果真實開發一款播放器類的軟件,需要監聽AUDIO_BECOMING_NOISY的廣播,它會在音頻輸出源從其他輸出源變換到設備揚聲器的時候發出此廣播,監聽廣播在音頻輸出源改變到設備揚聲器的時候,停止播放,這樣確保在耳機或額外的音頻輸出硬件與設備斷開連接的時候,不至於重新從揚聲器繼續輸出音頻播放。


源碼鏈接:http://download.csdn.net/detail/duanyu218/7475569


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved