Activity与Service间的单向通信,相信大家都知道,常用的有下面3种方式:
1. 通过bindService(service, conn, BIND_AUTO_CREATE)开启Service,然后在ServiceConnection的onServiceConnected回调方法中获取到Service引用,然后我们就可以访问Service中的方法了.
2. 通过broadcast(广播)的形式,当开启的Service接收到了对应的广播,就可以处理预设好的逻辑了.
3. 通过调用类名直接调用Service中定义的静态方法.
今天要将的是解决Activity与Service的双向通信的问题,即Activity可以调用Service中暴露的方法,同时Service也可以调用Activity中暴露的方法.
实现的方式:
Messenger+Handler.
原理:
分别将Activity和Service的引用发送给对方,通过Handler对象来发送引用,在Activity与Service中都定义一个Handler.
关键问题,如何拿到对方的Handler来发送引用?
通过Messenger类,他可以把一个Handler转换成IBinder,也可以把IBinder转换成Messenger.
下面将通过一个Demo来展示Messenger的使用.
目标Activity
public class AudioPlayerActivity extends BaseActivity {
private AudioPlayerService mAudioPlayerService;
//Service拿到这个handler就可以与Activity通信了
private Handler mActivityHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
LogUtils.i(AudioPlayerActivity.this, ">>>>>>>>>>>handleMessage...what=" + msg.what + " obj=" + msg.obj);
switch (msg.what) {
case AudioPlayerService.SERVICE_INTERFACE:
//获取AudioPlayerService的引用
mAudioPlayerService = (AudioPlayerService) msg.obj;
mAudioPlayerService.testCallService();
break;
}
}
};
private Messenger mActivityMessenger = new Messenger(mActivityHandler);
@Override
protected void setTitleBar(TitleBar titleBar) {
titleBar.setTitleBarBgResource(R.drawable.base_titlebar_bg);
titleBar.setLeftIcon(R.drawable.selector_btn_back, new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
titleBar.setCenterTv("最炫民族风");
}
@Override
protected boolean isHomePage() {
return false;
}
@Override
public Integer getLayoutResId() {
return R.layout.activity_audio_player;
}
@Override
public void initView() {
}
@Override
public void initListener() {
}
@Override
public void initData() {
Intent intent = getIntent();
if (null != intent) {
Bundle bundle = intent.getExtras();
if (null == bundle && bundle.size() < 0) {
mLoadView.setExceptionViewVisible(true);
} else {
//直接把bundle通过参数传到服务中,然后在service中取出来
Intent service = new Intent(this, AudioPlayerService.class);
service.putExtras(bundle);
//先通过start方式开启服务,保证服务能工作在后台
startService(service);
//再通过bind的方式开启服务,保证activity能够和service间交互
bindService(service, conn, BIND_AUTO_CREATE);
}
}
}
/**
* 服务连接器
*/
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
LogUtils.i(AudioPlayerActivity.this, ">>>>>>>>>>>onServiceConnected");
//注意:这里的binder是由AudioPlayerService的mServiceMessenger.getBinder()返回的,因此这里使用binder创建Messenger的话,就可以公用AudioPlayerService的Handler发送消息了.
Messenger messenger = new Messenger(binder);
Message msg = Message.obtain();
msg.what = AudioPlayerService.UI_INTERFACE;
msg.obj = AudioPlayerActivity.this; //这里将AudioPlayerActivity的引用发送给AudioPlayerService
msg.replyTo = mActivityMessenger;// 将Activity中的mActivityMessenger传递个Service
LogUtils.i(AudioPlayerActivity.this, "replyTo>>>>>>>>>>>" + mActivityMessenger);
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
LogUtils.i(AudioPlayerActivity.this, ">>>>>>>>>>>onServiceDisconnected");
}
};
public void updateUI(Audio audio) {
LogUtils.i(AudioPlayerActivity.this, ">>>>>>>>>>>updateUI");
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
@Override
public void reLoadData() {
}
@Override
public void onClick(View v) {
}
}
目标Service
public class AudioPlayerService extends Service {
public static final int UI_INTERFACE = 0; //获取AudioPlayerActivity引用的message what
public static final int SERVICE_INTERFACE = 1; //获取AudioPlayerService引用的message what
private int mPosition;
private ArrayList<Parcelable> mAudioList;
private static AudioPlayerActivity mAudioPlayerActivity;
private static Messenger mActivityMessenger;
//Activity拿到这个handler就可以与service通信了
private Handler mServiceHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UI_INTERFACE:
//拿到AudioPlayerActivity的引用
mAudioPlayerActivity = (AudioPlayerActivity) msg.obj;
mAudioPlayerActivity.updateUI(null);
//拿到AudioPlayerActivity的mActivityMessenger对象,来发送消息给mActivityHandler
mActivityMessenger = msg.replyTo;
Message message = Message.obtain();
message.what = SERVICE_INTERFACE;
message.obj = AudioPlayerService.this;
LogUtils.i(AudioPlayerService.this, "mActivityMessenger>>>>>>>>>>>" + mActivityMessenger);
try {
mActivityMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
};
//创建Messenger对象
Messenger mServiceMessenger = new Messenger(mServiceHandler);
@Override
public void onCreate() {
LogUtils.i(AudioPlayerService.this, ">>>>>>>>>>>onCreate");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
LogUtils.i(AudioPlayerService.this, ">>>>onBind");
return mServiceMessenger.getBinder();//返回一个Binder
}
public void testCallService() {
LogUtils.i(AudioPlayerService.this, ">>>>>>>>>>>testCallService");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.i(AudioPlayerService.this, ">>>>>>>>>>>onStartCommand");
// //获取Activity传递过来的数据
Bundle bundle = intent.getExtras();
mPosition = bundle.getInt(Constant.KEY_POSITION);
mAudioList = bundle.getParcelableArrayList(Constant.KEY_LIST);
LogUtils.i(AudioPlayerService.this, "mPosition:" + mPosition + " mAudioList:" + mAudioList);
return super.onStartCommand(intent, flags, startId);
}
}
打印的日志
I/AudioPlayerService: >>>>>>>>>>>onCreate
I/AudioPlayerService: >>>>>>>>>>>onStartCommand
I/AudioPlayerService: >>>>onBind
I/AudioPlayerActivity: >>>>>>>>>>>onServiceConnected
I/AudioPlayerActivity: replyTo>>>>>>>>>>>android.os.Messenger@41a0d208
I/AudioPlayerActivity: >>>>>>>>>>>updateUI
I/AudioPlayerService: mActivityMessenger>>>>>>>>>>>android.os.Messenger@41a0d208
I/AudioPlayerActivity: >>>>>>>>>>>handleMessage…what=1 obj=mchenys.net.csdn.blog.myplayer.module.audio.service.AudioPlayerService@41b072a8
I/AudioPlayerService: >>>>>>>>>>>testCallService
通过上面的日志,可以发现AudioPlayerService成功的调用了AudioPlayerActivity的updateUI方法,同时AudioPlayerActivity也成功的调用了AudioPlayerService的testCallService方法.