Messenger简介

Messenger和AIDL是实现进程间通信(interprocess communication)的两种方式.

实际上,Messenger的实现其实是对AIDL的封装.

Messenger适合于多进程单线程,AIDL适合于多进程多线程,需要开发者自己实现线程安全.

google官方文档指出对于大部分的程序,service不需要执行多线程,所以应该首先考虑使用Messenger.

为什么需要进程间通信?

因为不同进程之间的数据是不共享的.

实践(以音乐播放器demo为例)

关键词: bind + messenger + handler

step1 (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:使用Messenger进行进程间通信(一)的更多相关文章

  1. android:使用Messenger进行进程间通信(二)

    //继续完善音乐播放器demo 相关文章: android:使用Messenger进行进程间通信(一):http://www.cnblogs.com/happyhacking/p/5318418.ht ...

  2. Android 基于Message的进程间通信 Messenger完全解析

    一.概述 说到Android进程间通信,大家肯定能想到的是编写aidl文件,然后通过aapt生成的类方便的完成服务端,以及客户端代码的编写.如果你对这个过程不熟悉,可以查看Android aidl B ...

  3. 【Android】17.5 利用Messenger实现进程间通信(IPC)

    分类:C#.Android.VS2015: 创建日期:2016-03-03 一.Messager类简介 本章前面曾经说过,要在Android上执行带服务的进程间通信(IPC),既可以用Messenge ...

  4. Android - 使用messager实现进程间通信(服务器端→客户端,客户端→服务器端双向)

    之前看了一篇,然后不自己动手肯定是不行的,然后自己又写了一遍. 背景: 一般使用messenger进行进程间通信的时候,我们只能进行单方向通信.但是有没有办法让服务器端和客户端进行双向通信呢? 解决思 ...

  5. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger

    Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...

  6. Android IPC机制(二)用Messenger进行进程间通信

    Messenger可以在不同进程中传递Message对象,我们在Message中加入我们想要传的数据就可以在进程间的进行数据传递了.Messenger是一种轻量级的IPC方案并对AIDL 进行了封装, ...

  7. 【起航计划 036】2015 起航计划 Android APIDemo的魔鬼步伐 35 App->Service->Messenger Service Messenger实现进程间通信

    前面LocalService 主要是提供同一Application中组件来使用,如果希望支持不同应用或进程使用Service.可以通过Messenger.使用Messgener可以用来支持进程间通信而 ...

  8. Android开发之IPC进程间通信-AIDL介绍及实例解析

    一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用 ...

  9. android中的AIDL进程间通信

    关于IPC应该不用多介绍了,Android系统中的进程之间不能共享内存,那么如果两个不同的应用程序之间需要通讯怎么办呢?比如公司的一个项目要更新,产品的需求是依附于当前项目开发一个插件,但是呢这个插件 ...

随机推荐

  1. NodeJS的代码调试和性能调优

    本文转自我的个人博客. NodeJS 自 2009 年显露人间,到现在已经六个年头了,由于各种原因,中间派生出了个兄弟,叫做 iojs,最近兄弟继续合体,衍生出了 nodejs4.0 版本,这东西算是 ...

  2. EasyPR--开发详解(5)颜色定位与偏斜扭转

    本篇文章介绍EasyPR里新的定位功能:颜色定位与偏斜扭正.希望这篇文档可以帮助开发者与使用者更好的理解EasyPR的设计思想. 让我们先看一下示例图片,这幅图片中的车牌通过颜色的定位法进行定位并从偏 ...

  3. Eclipse常用设置

    用惯了VS,再回过去用Eclipse真是一件痛苦的事.so,在这里记录下使用过程中的一些设置以做备忘. 1.代码自动提示 在我们忘记方法名或者想偷懒时,代码自动提示很管用.不过Eclipse默认是输入 ...

  4. ABP框架 - 验证数据传输对象

    文档目录 本节内容: 简介 使用数据注解 自定义验证 禁用验证 正常化 简介 一个应用的输入应当先要验证,这个输入可能来自用户或另一个应用,在一个web应用里,验证通常实现两次:在客户端和在服务端,客 ...

  5. iOS开发中静态库之".framework静态库"的制作及使用篇

    iOS开发中静态库之".framework静态库"的制作及使用篇 .framework静态库支持OC和swift .a静态库如何制作可参照上一篇: iOS开发中静态库之" ...

  6. Failure to find xxx in xxx was cached in the local repository, resolution will not be reattempted until the update interval of nexus has elapsed or updates are forced @ xxx

    问题: 在linux服务器上使用maven编译war时报错: 16:41:35 [FATAL] Non-resolvable parent POM for ***: Failure to find * ...

  7. Linux进程管理及while循环

    目录 进程的相关概念 进程查看及管理工具的使用 Linux系统作业控制 调整进程优先级 网络客户端工具 bash之while循环 20.1.进程类型 守护进程 daemon,在系统引导过程中启动的进程 ...

  8. nodejs模块中exports和module.exports的区别

    通过Node.js的官方API可以看到Node.js本身提供了很多核心模块 http://nodejs.org/api/ ,这些核心模块被编译成二进制文件,可以require('模块名')去获取:核心 ...

  9. 解析大型.NET ERP系统 查找与钻取

    查找 Lookup 窗体是一个容器,也可以把TextBox,Button也看成是一个容器,可以往容器里面添加按钮. 参考下面的实现代码,给TextBox增加查找按钮. var btn = new Bu ...

  10. 跨域的jsonP

    1.出现原因:因为web中的同源策略(域名,协议,端口号)限制了跨域访问.   2.区别于json (个人理解)json是数据交换格式,jsonp是数据通信中的交互方式   3.jsonp的get与p ...