android:使用Messenger进行进程间通信(一)
2016-03-25 10:16
495 查看
Messenger简介
Messenger和AIDL是实现进程间通信(interprocess communication)的两种方式.实际上,Messenger的实现其实是对AIDL的封装.
Messenger适合于多进程单线程,AIDL适合于多进程多线程,需要开发者自己实现线程安全.
google官方文档指出对于大部分的程序,service不需要执行多线程,所以应该首先考虑使用Messenger.
为什么需要进程间通信?
因为不同进程之间的数据是不共享的.实践(以音乐播放器demo为例)
关键词: bind + messenger + handlerstep1 (AndroidManifest.xml)在AndroidManifest.xml中注册service,并设置为其android:process属性赋值
注意① 忘记注册service的话,程序不会响应,但是也不会崩溃的...注意② 此处设置该service为一个全局进程,意即不同应用程序可以共享该进程,若process以":"开头,则表示其为该应用程序的私有进程.
<service android:name=".MusicService" android:process="com.example.janiszhang.musicplayer.service.process"/>
step2 (MusicService)在service中实现一个继承Handler的子类(),用于处理由activity发来的message
class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); mActivityMessenger = msg.replyTo; switch (msg.what) { case 0: mMediaPlayer.stop(); i = msg.arg1; mMediaPlayer = MediaPlayer.create(MusicService.this, mMusicDatas.get(i).getSrc()); if(isPlaying) { mMediaPlayer.start(); } //mRemoteViews.setTextViewText(R.id.music_name, mMusicDatas.get(i).getName()); //mRemoteViews.setTextViewText(R.id.singer_name, mMusicDatas.get(i).getSinger()); //mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); break; case 1: if(msg.arg1==1){ isPlaying =false; mMediaPlayer.pause(); //mRemoteViews.setImageViewResource(R.id.btn_play, R.drawable.note_btn_play); //mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } else { isPlaying = true; i = msg.arg2; mMediaPlayer = MediaPlayer.create(MusicService.this, mMusicDatas.get(i).getSrc()); mMediaPlayer.start(); //mRemoteViews.setImageViewResource(R.id.btn_play, R.drawable.note_btn_pause); //mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } break; default: break; } } }
step3 (MusicService)实例化自定义的handler,作为参数,创建一个Messenger
Messenger mMessenger = new Messenger(new IncomingHandler());
step4 (MusicService)实现onBind()方法
@Nullable @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); }
step5 (MusicActivity) 创建一个ServiceConnection实例,在onServiceConnected方法中获取到service返回的messenger.
private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mMessenger = new Messenger(service); } @Override public void onServiceDisconnected(ComponentName name) { } };
step6 (MusicActivity)bindservice
Intent intent = new Intent(this, MusicService.class); bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
step7 bind成功后,就可以获取到一个Messenger的实例,通过该实例activity可以向另外一个进程中的service发送message,例如:
mNextBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mIndex = (mIndex+1)>=mMusicDatas.size()? 0 : mIndex+1; setMusicNameAndSingerName(mIndex); if(mMessenger != null) { Message message = Message.obtain(null, 0); message.arg1 = mIndex; message.replyTo = mActivityMessenger; try { mMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } } });
至此,基于Messenger的由activity到service的进程间通信就是实现完成了.
遇到的问题:
当我试图Message实例的obj赋值为true时,会导致异常:java.lang.RuntimeException: Can't marshal non-Parcelable objects across processes.
意思是说obj应该是一个实现了Parcelable接口的对象.
解决方案:对于这种情况,应该使用bundle来传递数据.
总结一下:
1.activity与service以bind的方式通信.
2.service中创建一个用于处理数据的handler,并以之为参数创建一个Messenger,通过onbind返回给activity.
3.activity使用service返回的Messenger实例send message
github地址:https://github.com/zhangbz/MusicPlayer
相关文章推荐
- Android Studio配置SVN服务器
- Android fragment嵌套fragment失去Context的问题
- Android SDK开发包国内下载地址
- android4.4增加ethernet
- Android Fragment实现按钮间的切换
- 初涉Android Studio从官方文档开始(1)
- android view获取在屏幕上的绝对坐标
- Android Studio 签名打包过程图解
- Android压缩图片到100K以下并保持不失真的高效方法
- Android的ViewHolder的使用
- Android Studio如何使用快捷键生成get,set,tostring,构造函数
- 二维码合成,将苹果和安卓(ios和android)合成一个二维码,让用户扫描一个二维码就可以分别下载苹果和安卓的应用
- android 属性动画
- Android开发具体解释之ListView具体解释一
- android 的中文意思
- android-----BroadcastReceiver广播接收器
- CoordinateLayout 事件流程分析
- android开发 九宫格
- android实验四201306114104彭得源
- 最明白的Android——活动的启动模式