最近从新温习AIDL,发现技术这玩意就跟女人一样,你过久没去了解就会对它陌生却又充满新鲜感,然后查看网上的多半是胡扯,粘贴,我这里整合下,里面如果有错误望大家及时指出。废话不多说,进入主题
首先来了解几点常识:
1,一个Android应用程序对应一个进程;
2,Android应用程序进程间需要借助IPC轻量级通讯协议;
3,切勿把线程和进程的概念搞混乱。一个进程可以包含多个线程,但是一个线程只会附属于一个进程,可以理解成1对多的关系;
4,我们常见的Handler它是运行在UI主线程的,它负责的是异步处理数据,执行也是父线程和子线程;所以别把它和进程的概念混在一起。
进入主题,Android进程间的通讯:AIDL
这里我以为大家比较熟悉的C/S模式来讲解整个通讯过程;但是我并没有去新建立两个项目了,就一个项目中,模拟进程通讯。不多说,先上项目图
第一步,首先建立两个aidl文件,forActivity.adil,forService.aidl 先来看看它们内部实现
package com.aidl;
interface forActivity{
void perAction();
void showString(int count);
}
package com.aidl;
import com.aidl.forActivity;
interface forService{
void registerTestCall(forActivity fa);
void callBack();
}
一看,哎哟,这里面的编码规则和java文件一样,但是这个时候,我其他地方要调用怎么办?别着急编译器会默认在gen文件中生成对应.java文件
打开其中一个文件查看下其中源码,先不详细分析,慢慢来,就好比追女生一样,要慢慢来,急不得
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\workspace\\AndroidAIDL\\src\\com\\example\\androidaidl\\aidl\\forActivity.aidl
*/
package com.example.androidaidl.aidl;
public interface forActivity extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.androidaidl.aidl.forActivity
{
private static final java.lang.String DESCRIPTOR = "com.example.androidaidl.aidl.forActivity";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.androidaidl.aidl.forActivity interface,
* generating a proxy if needed.
*/
public static com.example.androidaidl.aidl.forActivity asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.androidaidl.aidl.forActivity))) {
return ((com.example.androidaidl.aidl.forActivity)iin);
}
return new com.example.androidaidl.aidl.forActivity.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_performAction:
{
data.enforceInterface(DESCRIPTOR);
this.performAction();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.androidaidl.aidl.forActivity
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void performAction() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_performAction = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void performAction() throws android.os.RemoteException;
}
第二步,新建mAIDLActivity.java文件,它模拟Client , 新建mAIDLService.java文件,它模拟Server;
先看看mAIDLActivity.java文件;
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) {
android.util.Log.d(TAG, "------ " + str + "------");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
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) {
//绑定服务
Intent intent = new Intent(mAIDLActivity.this,mAIDLService.class);
bindService(intent, mcConnection, Context.BIND_AUTO_CREATE);
//startService(intent);
}
});
btnCancel.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//取消绑定
unbindService(mcConnection);
/*unbindService(mConnection);
// stopService(intent);
*/ }
});
btnCallBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
//进程数据交互通讯
mService.callBack();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
forService mService;
forActivity mActivity = new forActivity.Stub() {
@Override
public void perAction() throws RemoteException {
Log("执行了啦");
}
@Override
public void showString(int count) throws RemoteException {
Log(count+"");
}
};
ServiceConnection mcConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = forService.Stub.asInterface(service);
try {
mService.registerTestCall(mActivity);
} catch (RemoteException e) {
}
}
};
}
这三个按钮的作用我就不用说了吧,那么明白的解释在那里还不懂的话,那你就别继续看了,好好看看片,撸一管撤退吧。
先分析下上述文件
ServiceConnection mcConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = forService.Stub.asInterface(service);
try {
mService.registerTestCall(mActivity);
} catch (RemoteException e) {
}
}
};
ServiceConnection的使用和介绍我上一篇博文已经说了,大家可以去看看,说实在的就是如果不是研究AIDL,这家伙我估计都不会看到.
看这句代码
mService = forService.Stub.asInterface(service);
如果直接看的话不看源码,我第一想到的就是实例化?强转,?一大堆不靠谱的逻辑,作为一个装逼程序猿,如果遇到不知道的情况,别瞎猜,看源码才是王道.来打开forService.文件
public interface forService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.aidl.forService
{
private static final java.lang.String DESCRIPTOR = "com.aidl.forService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.aidl.forService interface,
* generating a proxy if needed.
*/
public static com.aidl.forService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.aidl.forService))) {
return ((com.aidl.forService)iin);
}
return new com.aidl.forService.Stub.Proxy(obj);
}
这里我们发现,Stub是forService的内部静态抽象类,并且是继承Binder和实例化了接口forService. 查看方法adInterface中的实现,它分三步来判断
1,如果是空,直接给你空,让你一边玩去
2,如果传入的Ibinder对象就是com.aidl.forService,因为forService的继承的IInterface,看IInterface的介绍Base class for Binder interfaces. When defining a new interface, you must derive it from IInterface.那得列直接强转成forService对象返回去,万事大吉;
3.如果为空,那就new一个新的,对象嘛.程序猿从来不缺.
下面继续分析mAIDLService文件.不多说,先看源码
public class mAIDLService extends Service {
@Override
public IBinder onBind(Intent intent) {
return mIBinder;
}
forActivity mActivity;
int count=0;
forService.Stub mIBinder = new forService.Stub() {
@Override
public void registerTestCall(forActivity fa) throws RemoteException {
mActivity = fa;
}
@Override
public void callBack() throws RemoteException {
mActivity.perAction();
mActivity.showString(++count);
}
};
}
它这里相对就简单了,基本不用多说了吧,这里要注意的就是
public IBinder onBind(Intent intent) {
return mIBinder;
}
它返回的是当前new出来的forService对象.也就是我们前面ServiceConnection回调拿到的IBinder,
那这里就慢慢明朗了,整个相互间的通讯也就清楚了,当按下btnCallBack按钮的时候,首先会调用forService中的callBack方法,而callBack方法的实现中又调用了forActivity的perAction.通过forActivity和forService的这次握手,就达到了mAIDLActivity和mAIDLService一直及时通讯
说到这里有朋友跟我说ContentProvider就可以直接实现两个应用间的数据传递了啊,为什么还要用AIDL,我转头一声呵呵,我列出下面几个区分点估计大家就明白了
1.ContentProvider是单向性的,不及时的,而AIDL是双向性,及时的。就这么来说吧。ContentProvider就好比你看到一个漂亮的妹子,你一直看着她,但是她却对你无视,你看不清楚她身体的变化;AIDL就是你看到那个漂亮的妹子,她也看着,你下面的异样,立即反馈给了她,而你也看到了她嘴边的异样,这比喻好理解吗?哈哈哈
好了中间有些地方如果有错或者大家要补充的直接留言吧,然后恳请转载的指明地址,不然又是一堆废文到处跑。
下篇博文准备分析下IBinder和Binder!
参考网友论文
http://blog.csdn.net/saintswordsman/article/details/5130947
源码下载