最近在做項目的時候遇到一個小問題,就是需要自己寫一個View來控制系統音樂播放器的播放行為,並且要能得到正在播放的音樂的信息,可能剛開始是想省點時間,所以就沒有直接去看源碼,而是上網搜索了一下,但令我十分驚訝的是網上竟然沒有這個,難道說沒有童鞋做過這個?嘿嘿,啥都不說了,開始:
獲得系統正在播放的音樂的信息,查看源碼可以知道,在Music應用中有一個MediaPlaybackService.java文件,內部的代碼我就不寫了,總之就是在播放音樂的時候會在四種情況下發送廣播,這些廣播里面包含了正在播放的音樂的信息,所以我們只要寫一個廣播來接受這些信息就可以了:
MusicBroadcastReceiver mbr = null;//定義
class MusicBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { artistName = intent.getStringExtra("artist"); album = intent.getStringExtra("album"); track = intent.getStringExtra("track"); playing = intent.getBooleanExtra("playing",false); duration = intent.getLongExtra("duration",3000); position = intent.getLongExtra("position",1000); Toast.makeText(TestActivity.this, "playing:" + playing, Toast.LENGTH_SHORT).show(); if(playing){ sd.setVisibility(View.VISIBLE); } else{ if((!sd.isOpened())){ sd.setVisibility(View.GONE); } } if(playing){ ((ImageView)findViewById(R.id.play)).setImageResource(R.drawable.music_pause); }else{ ((ImageView)findViewById(R.id.play)).setImageResource(R.drawable.music_play); } ((TextView)findViewById(R.id.musicName)).setText(track ); ((TextView)findViewById(R.id.musicInfo)).setText(artistName + " / " + album); } }
上面寫的是一個廣播界接收者,需要在適當的時機進行注冊,由於MediaPlaybackService發送的是一個粘性廣播,所以我們的這個接收者在應用打開的時候也可以接收到這個廣播,不需要管上面我的那些個TextView或者是ImageView。
注冊廣播:
@Override
protected void onResume() {
/**
* com.android.music.metachanged
* com.android.music.queuechanged",
* "com.android.music.playbackcomplete"
* "com.android.music.playstatechanged"
*/
mbr = new MusicBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.android.music.metachanged");
intentFilter.addAction("com.android.music.queuechanged");
intentFilter.addAction("com.android.music.playbackcomplete");
intentFilter.addAction("com.android.music.playstatechanged");
registerReceiver(mbr, intentFilter);
super.onResume();
}
注銷廣播:
@Override
protected void onPause() {
if(mbr != null){
unregisterReceiver(mbr);
}
super.onPause();
}
控制音樂的播放:
同樣在Music應用中有一個MediaButtonIntentReceiver接受着,當我們我們可以發送特定的廣播來控制音樂的播放,如下:
private static final String SERVICECMD = "com.android.music.musicservicecommand";
private static final String CMDNAME = "command";
/* private static final String CMDTOGGLEPAUSE = "togglepause";
private static final String CMDSTOP = "stop";*/
private static final String CMDPAUSE = "pause";
private static final String CMDPLAY = "play";
private static final String CMDPREVIOUS = "previous";
private static final String CMDNEXT = "next";
public void click(View v){
Intent intent = new Intent(SERVICECMD);
switch(v.getId()){
case R.id.pre:{
intent.putExtra(CMDNAME, CMDPREVIOUS);
}break;
case R.id.play:{
if(playing){
intent.putExtra(CMDNAME,CMDPAUSE);
((ImageView)findViewById(R.id.play)).setImageResource(R.drawable.music_play);
}else{
intent.putExtra(CMDNAME,CMDPLAY);
((ImageView)findViewById(R.id.play)).setImageResource(R.drawable.music_pause);
}
}break;
case R.id.next:{
intent.putExtra(CMDNAME,CMDNEXT);
}break;
}
sendBroadcast(intent);
}
放送廣播的時候也可以不給Inent設置Extra,只需要把:
private static final String SERVICECMD = "com.android.music.musicservicecommand";
private static final String CMDNAME = "command";
/* private static final String CMDTOGGLEPAUSE = "togglepause";
private static final String CMDSTOP = "stop";*/
private static final String CMDPAUSE = "pause";
private static final String CMDPLAY = "play";
private static final String CMDPREVIOUS = "previous";
private static final String CMDNEXT = "next";
替換為
private static final String pause = "com.android.music.musicservicecommand.pause";
private static final String next = "com.android.music.musicservicecommand.next";
private static final String stop = "com.android.music.musicservicecommand.stop";
private static final String previous = "com.android.music.musicservicecommand.previous";
然后new Intent(pause/next/stop/previous);等通過sendBroadcast(intent);發送也可以,但是我沒有親自驗證過,大家可以試一下,第一種是驗證過的。
貼出原理圖:下面是我做鎖屏的時候的圖,左邊的部分是鎖屏相關的,不要受它影響。

