您的位置:首页 > 其它

Messenger实现Activity与Service的双向通信

2016-03-09 18:24 465 查看
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方法.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: