背景:
最近实现了一个本地版音乐播放,在编写代码过程中遇到个问题:当一首歌在Service中播放时,从后台或播放列表进入播放界面,如何使界面上显示当前播放歌曲的详情信息,如歌名、艺术家、歌词显示的位置、播放进度等。
在上一篇博客中用接口的形式实现Activity与Service无延时的交互,而在这篇中研究的如何使用Messenger实现上述需求。
原理:
Activity 在绑定 Service时,通过Messenger拿到对方引用,然后恰当的调用对应的方法即可。
步骤:
1. 在Activity和Service中分别创建一个Handler对象, 并用该Handler 创建 Messenger对象
2. 在Activity绑定Service时:Service返回其handler和自身引用,当绑定成功后,Activity使用Service返回的handler创建一个Messenger,然后发送自己的handler和自身引用
代码
Activity:
handler:
private Handler uiHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case FROMSERVICES_TAG:
service = (AudioPlayerServices) msg.obj;
//msg.arg1是用来判断每次bindService后是否需要重新播放音乐
if (msg.arg1 == AudioPlayerServices.No_RePlay) {
//播放的是同一首歌,更新界面
updateUI(service.getCurItem());
} else {
//否则播放新歌曲
service.openAudioPlayer();
}
break;
}
};
};
BindSercice:
public void onServiceConnected(ComponentName name, IBinder service) {
try {
Messenger servMessenger = new Messenger(service);
Message msg = Message.obtain();
msg.what = AudioPlayerServices.FROMUI_TAG;
msg.replyTo = uiMessenger;
msg.obj = AudioPlayerActivity.this;
servMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
Service:
private Handler servHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case FROMUI_TAG:
activity = (AudioPlayerActivity) msg.obj;
uiMessenger = msg.replyTo;
sendMessengerAndContextToUI();
break;
}
}
};
/** 向AudioPlayerActivity发送自己的Messenger和引用 */
private void sendMessengerAndContextToUI() {
try {
Message msg = Message.obtain();
msg.what = AudioPlayerActivity.FROMSERVICES_TAG;
msg.arg1 = opMusicFlag;
msg.obj = AudioPlayerServices.this;
uiMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
};