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

package com.styleflying.AIDL;
interface forActivity {
void performAction();
}

文件:forService.aidl

package com.styleflying.AIDL;
import com.styleflying.AIDL.forActivity;
interface forService {
void registerTestCall(forActivity cb);
void invokCallBack();
}

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

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

再看mAIDLActivity.java:

package com.styleflying.AIDL;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class mAIDLActivity extends Activity {
private static final String TAG = "AIDLActivity";
private Button btnOk;
private Button btnCancel;
private Button btnCallBack; private void Log(String str) {
Log.d(TAG, "------ " + str + "------");
} private forActivity mCallback = new forActivity.Stub() {
public void performAction() throws RemoteException
{
Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();
}
}; forService mService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
mService = forService.Stub.asInterface(service);
try {
mService.registerTestCall(mCallback);}
catch (RemoteException e) { }
}
public void onServiceDisconnected(ComponentName className) {
Log("disconnect service");
mService = null;
}
};
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
btnOk = (Button)findViewById(R.id.btn_ok);
btnCancel = (Button)findViewById(R.id.btn_cancel);
btnCallBack = (Button)findViewById(R.id.btn_callback);
btnOk.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Bundle args = new Bundle();
Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class);
intent.putExtras(args);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
startService(intent);
}
});
btnCancel.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
unbindService(mConnection);
//stopService(intent);
}
});
btnCallBack.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v)
{
try
{
mService.invokCallBack();
} catch (RemoteException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}

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

看mAIDLService.java:

package com.styleflying.AIDL;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
public class mAIDLService extends Service {
private static final String TAG = "AIDLService";
private forActivity callback;
private void Log(String str) {
Log.d(TAG, "------ " + str + "------");
}
@Override
public void onCreate() {
Log("service create");
}
@Override
public void onStart(Intent intent, int startId) {
Log("service start id=" + startId);
} @Override
public IBinder onBind(Intent t) {
Log("service on bind");
return mBinder;
}
@Override
public void onDestroy() {
Log("service on destroy");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log("service on unbind");
return super.onUnbind(intent);
}
public void onRebind(Intent intent) {
Log("service on rebind");
super.onRebind(intent);
}
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; } };
}

注意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. 4.SQL语言基础

    4.1语言分类和用户模式 4.1.1语言分类 1)数据查询语言 用语检索数据库中的数据,主要是select语句,是操作数据库时最为频繁使用. 2)数据操纵语言 用语改变数据库中的数据,主要包括inse ...

  2. 从外国html5网站上扒来一个鼠标经过的css3 效果,感觉很不错

    鼠标经过的时候,感觉有点像一张纸卷上去的感觉. 下面是代码 <div class="main-container types"> <div class=" ...

  3. C++ 类访问控制(public/protected/private)

    第一:private, public, protected 访问标号的访问范围. private:只能由1.该类中的函数.2.其友元函数访问. 不能被任何其他访问,该类的对象也不能访问. protec ...

  4. java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解(勿删)

    head first java里写到“java是通过值传递的,也就是通过拷贝传递”,由此得出结论,方法无法改变调用方传入的参数.该怎么理解呢? 看例子: public class Test1 { pu ...

  5. jquery validation插件

    jQuery Validate验证框架详解 jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation 一.导 ...

  6. WPF提示框效果

    WPF提示框效果 1,新建WPF应用程序 2,添加用户控件Message 3,在Message中编写如下代码 <Border x:Name="border" BorderTh ...

  7. js中的forin

    前言 自己在平时没事干练练手,发现的以前一直以为是错的.幸亏今天知道了,要不说起来自己还不知道呢. 过程 遍历前置页面上的textbox,给他们赋值(js). 一开始自己用forin遍历的. 如论如何 ...

  8. CentOS6.5 yum安装桌面环境

    安装原因 安装centos6.5时选择了minimal CentOS最小化安装方式 需要使用浏览器拨号连接内网 安装过程 通过yum grouplist查询在 group 软件包中,Desktop.D ...

  9. ListView的setOnItemClickListener和setOnItemLongClickListener同时响应的问题

    lvContentList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(A ...

  10. 新年之际,盘点一些APP开发技巧

    (原文:Reader Submissions - New Year's 2015 作者:Mattt Thompson 译者:培子 校对:蓝魂) 回顾过去一年发生在我们身边的事情时,有一点不得不提:对苹 ...