android 的binder其实是基于 openbinder实现的,openbinder的地址:http://www.angryredplanet.com/~hackbod/openbinder/docs/html/

http://blog.csdn.net/saintswordsman/article/details/5130947

欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AIDL(以及Binder),那么可以默认你对这些概念已经有了一些了解,你(大致) 知道它们是什么,它们有什么用,所以为了节约大家的眼力和时间,在此我不复制粘贴网上泛滥的博客或者翻译冗长的android文档。

关于AIDL的介绍在文档:docs/guide/developing/tools/aidl.html

关于IBinder的介绍在文档:docs/reference/android/os/IBinder.html

以及Binder:docs/reference/android/os/Binder.html

在后文中,我将以我自己的理解向你介绍相关的概念。以我目前粗浅的经验,应用程序使用AIDL的地方,几乎都和Service有关,所以你也需要知道一些关于Service的知识。日后得闲我也会继续写一些关于Service的贴。

本文将以一个例子来和你分享使用AIDL的基础技能,这个例子里有:

1、一个类mAIDLActivity,继承Activity。里面有三个按钮,text分别为StartService,StopService,CallbackTest。

2、一个类mAIDLService,继承Service。为了充分展示ADIL的功能,它做以下工作:当用户点击CallbackTest按钮时,从mAIDLActivity调用mAIDLService中的Stub 对象的一个方法invokCallBack(),而这个方法又会调用mAIDLActivity中Stub 对象的一个方法performAction(),这个方法在屏幕上显示一个toast。没什么意义,只是展示一下AIDL如何使用。

3、两个AIDL文件:forService.aidl和forActivity.aidl。对应名字,在Service和Activity中分别有对象需要用到它们定义的接口。

4、相关XML文件,略过。关于manifest中Service的语法,见docs/guide/topics/manifest /service-element.html。你也可以简单地在<application></application>中加入

<service android:name=".mAIDLService" android:process=":remote"> </service>

开发环境为Eclipse。

拣重要的先说,来看看aidl文件的内容:

文件:forActivity.aidl

  1. package com.styleflying.AIDL;
  2. interface forActivity {
  3. void performAction();
  4. }

文件:forService.aidl

  1. package com.styleflying.AIDL;
  2. import com.styleflying.AIDL.forActivity;
  3. interface forService {
  4. void registerTestCall(forActivity cb);
  5. void invokCallBack();
  6. }

这两个文件和Java文件放置的地方一样,看包名。

在Eclipse中它们将被自动编译为forActivity.java和forService.java,它们存放在gen目录下。为了方便手头无法演练的读者,代码不贴,不用细看。

再看mAIDLActivity.java:

  1. package com.styleflying.AIDL;
  2. import android.app.Activity;
  3. import android.content.ComponentName;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.IBinder;
  9. import android.os.RemoteException;
  10. import android.util.Log;
  11. import android.view.View;
  12. import android.view.View.OnClickListener;
  13. import android.widget.Button;
  14. import android.widget.Toast;
  15. public class mAIDLActivity extends Activity {
  16. private static final String TAG = "AIDLActivity";
  17. private Button btnOk;
  18. private Button btnCancel;
  19. private Button btnCallBack;
  20.  
  21. private void Log(String str) {
  22. Log.d(TAG, "------ " + str + "------");
  23. }
  24.  
  25. private forActivity mCallback = new forActivity.Stub() {
  26. public void performAction() throws RemoteException
  27. {
  28. Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();
  29. }
  30. };
  31.  
  32. forService mService;
  33. private ServiceConnection mConnection = new ServiceConnection() {
  34. public void onServiceConnected(ComponentName className,
  35. IBinder service) {
  36. mService = forService.Stub.asInterface(service);
  37. try {
  38. mService.registerTestCall(mCallback);}
  39. catch (RemoteException e) {
  40.  
  41. }
  42. }
  43. public void onServiceDisconnected(ComponentName className) {
  44. Log("disconnect service");
  45. mService = null;
  46. }
  47. };
  48. @Override
  49. public void onCreate(Bundle icicle) {
  50. super.onCreate(icicle);
  51. setContentView(R.layout.main);
  52. btnOk = (Button)findViewById(R.id.btn_ok);
  53. btnCancel = (Button)findViewById(R.id.btn_cancel);
  54. btnCallBack = (Button)findViewById(R.id.btn_callback);
  55. btnOk.setOnClickListener(new OnClickListener() {
  56. public void onClick(View v) {
  57. Bundle args = new Bundle();
  58. Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class);
  59. intent.putExtras(args);
  60. bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
  61. startService(intent);
  62. }
  63. });
  64. btnCancel.setOnClickListener(new OnClickListener() {
  65. public void onClick(View v) {
  66. unbindService(mConnection);
  67. //stopService(intent);
  68. }
  69. });
  70. btnCallBack.setOnClickListener(new OnClickListener() {
  71.  
  72. @Override
  73. public void onClick(View v)
  74. {
  75. try
  76. {
  77. mService.invokCallBack();
  78. } catch (RemoteException e)
  79. {
  80. // TODO Auto-generated catch block
  81. e.printStackTrace();
  82. }
  83. }
  84. });
  85. }
  86. }

很短,相信大家很容易看明白。注意mConnection,它的onServiceConnected()中有一句mService = forService.Stub.asInterface(service);给mService赋值了,这个mService是一个 forService,而service是onServiceConnected()传进来的参数,onServiceConnected()会在连接 Service的时候被系统调用,这个service参数的值来自哪里呢?

看mAIDLService.java:

  1. package com.styleflying.AIDL;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. import android.os.RemoteCallbackList;
  6. import android.os.RemoteException;
  7. import android.util.Log;
  8. public class mAIDLService extends Service {
  9. private static final String TAG = "AIDLService";
  10. private forActivity callback;
  11. private void Log(String str) {
  12. Log.d(TAG, "------ " + str + "------");
  13. }
  14. @Override
  15. public void onCreate() {
  16. Log("service create");
  17. }
  18. @Override
  19. public void onStart(Intent intent, int startId) {
  20. Log("service start id=" + startId);
  21. }
  22.  
  23. @Override
  24. public IBinder onBind(Intent t) {
  25. Log("service on bind");
  26. return mBinder;
  27. }
  28. @Override
  29. public void onDestroy() {
  30. Log("service on destroy");
  31. super.onDestroy();
  32. }
  33. @Override
  34. public boolean onUnbind(Intent intent) {
  35. Log("service on unbind");
  36. return super.onUnbind(intent);
  37. }
  38. public void onRebind(Intent intent) {
  39. Log("service on rebind");
  40. super.onRebind(intent);
  41. }
  42. private final forService.Stub mBinder = new forService.Stub() {
  43. @Override
  44. public void invokCallBack() throws RemoteException
  45. {
  46. callback.performAction();
  47.  
  48. }
  49. @Override
  50. public void registerTestCall(forActivity cb) throws RemoteException
  51. {
  52. callback = cb;
  53.  
  54. }
  55.  
  56. };
  57. }

注意onBind(),它的返回类型为IBinder,返回了一个mBinder,看看mBinder的定义:

private final forService.Stub mBinder = new forService.Stub() {

@Override

public void invokCallBack() throws RemoteException

{

callback.performAction();

}

@Override

public void registerTestCall(forActivity cb) throws RemoteException

{

callback = cb;

}

};

它是实现了我们在AIDL中定义的方法,这个mBinder最终返回给了mAIDLActivity中的mService,于是在
mAIDLActivity中可以使用mBinder中的方法了。在mAIDLActivity中也有一个类似mBinder的对象,看看定义:

private forActivity mCallback = new forActivity.Stub()

{

public void performAction() throws RemoteException

{

Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();

}

};

我们要在界面上显示一个toast,就是在这里实现的。这个对象,在mConnection的onServiceConnected()被调用时,
通过调用mService(也就是远程的mAIDLService中的mBinder)的registerTestCall(),传递给了
mAIDLService,于是在mAIDLService中可以调用performAction()了。

很啰嗦,只为了能把这个细节说清楚。请大家认真看,我尽量避免错别字、混乱的大小写和逻辑不清的语法,相信你会看明白。是不是很简单?再啰嗦一下,做一个大致总结,我们使用AIDL是要做什么呢:

让Acticity(或者说一个进程/一个类?)和Service(或者说远端进程/远端类/对象?)获取对方的一个Stub对象,这个对象在定义
时实现了我们在AIDL中定义的方法,于是这些远程对象中的方法可以在本地使用了。如果这种使用(通信)是单向的,比如只是Activity需要通知
Service做什么,那么只要Service中有一个Stub对象,并且传给Acticity就够了。

至于如何获得远程的Stub,参看上面的代码,看mConnection、registerTestCall、onRebind,它们展示了一种方法。

另外,有时候我们可能在一个类中有多个Stub对象,它们都要给远程交互的类的实例,这个时候可以考虑使用RemoteCallbackList<>(docs/reference/android/os/RemoteCallbackList.html)。

=============================

Service的生命周期 Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy 
我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。

1 通过startService 
    Service会经历 onCreate -> onStart 
   stopService的时候直接onDestroy

如果是调用者(TestServiceHolder)自己直接退出而没有调用stopService的 
   话,Service会一直在后台运行。 
   下次TestServiceHolder再起来可以stopService。

2 通过bindService 
  
    Service只会运行onCreate, 这个时候 TestServiceHolder 和TestService绑定在一起

TestServiceHolder 退出了,Srevice就会调用onUnbind->onDestroyed 
   所谓绑定在一起就共存亡了。

那有同学问了,要是这几个方法交织在一起的话,会出现什么情况呢? 

个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又
bindService,Service只被创建一次。如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先

是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,对啊,就是stopService不好使了,只
能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。


务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可
以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务
仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特
点。


果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用
onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服
务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方
法结束服务,服务结束时会调用onDestroy()方法。


果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用
onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()
方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说
onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方
法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法.

你可以绑定一个已经通过startService()方法启动的服务。例如:一 个后台播放音乐服务可以通过startService(intend)对象来播放音乐。可能用户在播放过程中要执行一些操作比如获取歌曲的一些信息,此时 activity可以通过调用bindServices()方法与Service建立连接。这种情况下,unbindService() 及 stopServices()方法实际上不会停止服务,直到最后一次的绑定被关闭。

================================================================

Android之进程间传递自定义类型参数

【0】AIDL默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence)(好像数组也可以,只要实现了Parcelable接口),如果要传递自定义的类型该如何实现呢?

要传递自定义类型,首先要让自定义类型支持parcelable协议,实现步骤如下:

1>自定义类型必须实现Parcelable接口,并且实现Parcelable接口的public void writeToParcel(Parcel dest, int flags)方法 。

2>自定义类型中必须含有一个名称为CREATOR的静态成员,该成员对象要求实现Parcelable.Creator接口及其方法。

3>创建一个aidl文件声明你的自定义类型。

Parcelable接口的作用:实现了Parcelable接口的实例可以将自身的状态信息(状态信息通常指的是各成员变量的值)写入Parcel,也可以从Parcel中恢复其状态。 Parcel用来完成数据的序列化传递。

【1】进程间传递自定义类型的实现过程

1> 创建自定义类型,并实现Parcelable接口,使其支持parcelable协议。如:在com.hoo.domin创建Person.java:

  1. public class Person implements Parcelable
  2. private Integer id;
  3. private String name;
  4. public Person(){}
  5. public Person(Integer id, String name) {
  6. this.id = id;
  7. this.name = name;
  8. }
  9. public Integer getId() {
  10. return id;
  11. }
  12. public void setId(Integer id) {
  13. this.id = id;
  14. }
  15. public String getName() {
  16. return name;
  17. }
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21. @Override
  22. public int describeContents() {
  23. return ;
  24. }
  25. @Override
  26. public void writeToParcel(Parcel dest, int flags) {//把javanbean中的数据写到Parcel
  27. dest.writeInt(this.id);
  28. dest.writeString(this.name);
  29. }
  30. //添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口
  31. public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
  32. @Override
  33. public Person createFromParcel(Parcel source) {//从Parcel中读取数据,返回person对象
  34. return new Person(source.readInt(), source.readString());
  35. }
  36. @Override
  37. public Person[] newArray(int size) {
  38. return new Person[size];
  39. }
  40. };
  41. }

2> 在自定义类型所在包下创建一个aidl文件对自定义类型进行声明,文件的名称与自定义类型同名。

package com.hoo.domin

parcelable Person;

3> 在接口aidl文件中使用自定义类型,需要使用import显式导入,本例在com.hoo.aidl包下创建IPersonService.aidl文件,内容如下:

  1. package com.hoo.aidl;
  2. import cn.itcast.domain.Person;
  3. interface IPersonService {
  4. void save(in Person person);
  5. }

4> 在实现aidl文件生成的接口(本例是IPersonService),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。内容如下:

  1. public class ServiceBinder extends IPersonService.Stub {
  2. @Override
  3. public void save(Person person) throws RemoteException {
  4. Log.i("PersonService", person.getId()+"="+ person.getName());
  5. }
  6. }

5> 创建一个Service(服务),在服务的onBind(Intent intent)方法中返回实现了aidl接口的对象(本例是ServiceBinder)。内容如下:

  1. public class PersonService extends Service {
  2. private ServiceBinder serviceBinder = new ServiceBinder();
  3. @Override
  4. public IBinder onBind(Intent intent) {
  5. return serviceBinder;
  6. }
  7. public class ServiceBinder extends IPersonService.Stub {
  8. @Override
  9. public void save(Person person) throws RemoteException {
  10. Log.i("PersonService", person.getId()+"="+ person.getName());
  11. }
  12. }
  13. }

其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:

  1. <service android:name=".PersonService" >
  2. <intent-filter>
  3. <action android:name="com.hoo.process.aidl.PersonService " />
  4. </intent-filter>
  5. </service>

android进程间通信:使用AIDL的更多相关文章

  1. Android 进程间通信——AIDL

    代码地址如下:http://www.demodashi.com/demo/12321.html 原文地址:http://blog.csdn.net/vnanyesheshou/article/deta ...

  2. Android开发——进程间通信之AIDL(二)

    0.  前言 不论是Android还是其它操作系统.都会有自己的IPC机制.所谓IPC(Inter-Process Communication)即进程间通信.首先线程和进程是非常不同的概念,线程是CP ...

  3. 【Android】进程间通信IPC——AIDL

    AIDL官网定义AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似. 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口. 在 Androi ...

  4. Android进程间通信-AIDL实现原理

    Android进程间通信基于Proxy(代理)与Stub(桩或存根)的设计模式(如图1-1所示).其中,Proxy将特殊性接口转换成通用性接口,Stub将通用性接口转换成特殊性接口,二者之间的数据转换 ...

  5. Android 中的AIDL,Parcelable和远程服务

    Android 中的AIDL,Parcelable和远程服务      早期在学习期间便接触到AIDL,当时对此的运用也是一撇而过.只到近日在项目中接触到AIDL,才开始仔细深入.AIDL的作用    ...

  6. Android 进程间通信

    什么鬼!单例居然失效了,一个地方设置值,另个地方居然取不到,这怎么可能?没道理啊!排查半天,发现这两就不在一个进程里,才恍然大悟-- 什么是进程 按照操作系统中的描述:进程一般指一个执行单元,在 PC ...

  7. Android——进程通信/ AIDL/Message相关知识总结贴

    Android多进程通信 http://www.apkbus.com/android-83462-1-1.html Android 跨进程通信(一) http://www.apkbus.com/and ...

  8. (转载)Android:学习AIDL,这一篇文章就够了(上)

    前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说——你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓——那样就很尴尬了.不过又转念一想, ...

  9. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

  10. Android service binder aidl 关系

    /********************************************************************************** * Android servic ...

随机推荐

  1. Spring处理id相同的bean

    http://www.360doc.com/content/13/1018/05/41237_322247510.shtml(应该可以解决) http://www.2cto.com/kf/201601 ...

  2. java中事件处理探究

    事件的触发可以源于用户,也可以用代码来主动设置事件的发生.如setSelected()java.awt.event中 听众接口 事件类 适配器类 ComponentListener     Conta ...

  3. JS实时监听浏览器宽度的变化

    boot:function(){ //加载页面时执行一次 changeMargin(); //监听浏览器宽度的改变 window.onresize = function(){ changeMargin ...

  4. jQuery实现商品楼层的感觉

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. laravel学习前期遇到的小知识点(1)

    1. 目前我用的laravel 5.2.36版本web中间件成为全局中间件(不知道从5.2.26以上就改变了还是怎样,没有深究),也就是之前的版本路由里默认会有一个Route::group的web中间 ...

  6. Dalvik虚拟机进程和线程的创建过程分析

    从前面Dalvik虚拟机的运行过程分析一文可以知道,Dalvik虚拟机除了可以执行Java代码之外,还可以执行Native代码,也就是C/C++函数. 这些C/C++函数在执行的过程中,又可以通过本地 ...

  7. iPhone分辨率

    分辨率和像素 1.iPhone5           4"     分辨率320x568,像素640x1136,@2x 2.iPhone6           4.7"  分辨率3 ...

  8. gnuplot使用

    直接用yum安装gnuplot即可,例如 sudo sh -c "yum install gnuplot.x86_64 " 安装以后就可以使用了 编写gnuplot脚本 # grp ...

  9. Asp.net MVC中三大描述对象之ActionDescriptor 以及继承类ReflectedControllerDescriptor

    ActionDescriptor抽象类中几个基本的属性: ControllerName:被描述的Controller名称,去除后缀Controller的名称.例如:HomeController则为Ho ...

  10. 写了几天的博客-feel

    写博客 真的总结我自己的知识.长见识了.记录下自己遇到的东西,算是一个总结,有问题了,还可以回头看一下.很好 真的很好.