在當前應用的Activity 中如何對正在播放的music 進行控制

     Android 1.6的源碼共包括了21個核心應用,分佈在 package/apps下,其中 Music 應用提供了音樂播放功能,在各 GPhone 中差不多都能看到。但是這些核心應用本不屬於 Framework,因此無法在 SDK Document 中看到其類和方法的說明,更無法在外部引入它們的類,Music也不例外。

      工作中遇到這麼一個應用場景:用戶在文檔閱讀的 Activity 中,要能夠控制音樂播放,包括:上一首、下一首、暫停和繼續,以及獲取正在播放的音樂的名稱。由於無法引入 Music 應用的類,自然也就無法通過 API 直接實現這些功能。

查遍了 Dev Guide 和 Reference,也沒有找到蛛絲馬跡,於是索性直接進入到 Music 的源碼探個究竟。經過初步的分析,將問題的焦點定位在 com.android.music.MediaPlaybackService 上,該類是個 Service 類,負責在後臺播放音樂等工作。

該類聲明並實例化了一個 BroadcastReceiver,並在 onCreate 中進行了註冊,那麼這個 BroadcastReceiver 到底接收哪些 Intent 呢?通過代碼可以一目瞭然:

       IntentFilter commandFilter = new IntentFilter();
       commandFilter.addAction(SERVICECMD);  
       commandFilter.addAction(TOGGLEPAUSE_ACTION);
       commandFilter.addAction(PAUSE_ACTION);  
      commandFilter.addAction(NEXT_ACTION);  
      commandFilter.addAction(PREVIOUS_ACTION); 
      registerReceiver(mIntentReceiver, commandFilter);

找到上述代碼中的常量聲明,可以看出這些就是控制音樂播放的action name了。
public static final String SERVICECMD = “com.android.music.musicservicecommand”;   
public static final String CMDNAME = “command”;   
public static final String CMDTOGGLEPAUSE = “togglepause”;   
public static final String CMDSTOP = “stop”;   
public static final String CMDPAUSE = “pause”;   
public static final String CMDPREVIOUS = “previous”;   
public static final String CMDNEXT = “next”;    
public static final String TOGGLEPAUSE_ACTION = “com.android.music.musicservicecommand.togglepause”;  
 public static final String PAUSE_ACTION = “com.android.music.musicservicecommand.pause”;  
 public static final String PREVIOUS_ACTION = “com.android.music.musicservicecommand.previous”;  
 public static final String NEXT_ACTION = “com.android.music.musicservicecommand.next”;
 
     然後再回過頭來看 BroadcastReceiver是如何處理這些 Intent 的,通過其 onCreate 方法可以看出控制音樂播放有兩種方式。其一是設置 action name 爲 SERVICECMD,然後通過 Intent 的 extra 設置 command,其值可以是 CMDTOGGLEPAUSE、CMDSTOP、CMDPAUSE、CMDPREVIOUS 或 CMDNEXT。
其二是設置 action name 爲 TOGGLEPAUSE_ACTION、PAUSE_ACTION、PREVIOUS_ACTION 或 NEXT_ACTION。

看起來第二種方式更簡潔,依此思路,逆向操作也就可以解決起初的問題了,如下代碼演示瞭如何控制下一首:

 
        Intent intent = new Intent (”com.android.music.musicservicecommand.next”);   
        sendBroadcast(intent);

       如果我們在此基礎上更深入一步,控制音樂播放的同時,我們還需要得到正在播放的音樂名稱,這又該怎麼實現呢?
Android Framework 提供了非常棒的 android.media,凡音樂播放都離不開 MediaPlayer,該類定義了七個內部類,其中 MediaPlayer.OnPreparedListener 是這麼描述的:

Interface definition for a callback to be invoked when the media source is ready for playback.

 

媒體文件準備結束,準備播放時,Android 就會調用這個這個內部類,在 MediaPlaybackService 則是 notifyChange(String what) 方法進行處理:

           private void notifyChange(String what) {       
                      Intent i = new Intent(what);       
                      i.putExtra(”id”, Integer.valueOf(getAudioId()));       
                      i.putExtra(”artist”, getArtistName());       
                       i.putExtra(”album”,getAlbumName());       
                       i.putExtra(”track”, getTrackName());       
                       sendBroadcast(i);     
            // ……    }
那麼在我們的應用當中,則需要創建 一個BroadcastReceiver,過濾對應的 action name,也就是常量 META_CHANGED 對應的值即可達到目標。
到了這裏,回顧一下解決問題的過程,不由讓人有些憤憤不平,爲什麼 Android 不把接口以文檔的形式公佈於衆呢?真是“猶抱琵琶半遮面”。–或者它有公佈,我沒有看到?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章