Android-深入理解AIDL

1 篇文章 0 订阅
1 篇文章 0 订阅

最近从新温习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

源码下载

http://download.csdn.net/detail/eran12101030/7993485

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值