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的使用.
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方法.
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: >>>>>>>>>>>onCreateI/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方法.
相关文章推荐
- [WPF]Slider控件常用方法
- (三)基于PHP——复杂的WSDL的创建(WSDL篇)
- 什么样的公司值得加入?
- Ecstore中的微信支付怎么样配置
- sublime3 eslint 安装
- (二)基于PHP——简单的WSDL的创建(WSDL篇)
- Ecstore中的微信支付怎么样配置
- 构建之法阅读笔记02
- 调用notifyDataSetChanged无法更新ListView
- LeetCode 57 - Insert Interval
- (一)基于PHP——WSDL的创建(NON-WSDL篇)
- android TypedValue.applyDimension()的作用
- Android调用传感器和震动
- Xcode(7.2) 使用技巧(2)
- C# Winform 程序EXE单例模式的三种方案详细总结
- 54-题目1207:质因数的个数
- 如何设计用户登录
- Swift 基础学习(存储属性)
- Bundle display name – 真正显示到用户屏幕上的 App 名称
- @synthesize vs. @dynamic