`
chjmars
  • 浏览: 76077 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Android AIDL接口定义语言

阅读更多

跨进程访问(AIDL服务)

        Android系统中的进程之间不能共 享内存,因此,需要提供一些机制在不同进程之间进行数据通信。在4个Android应用程序组件中的3个(Activity、Broadcast和 Content Provider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以,也即AIDL服务。


什么是AIDL服务
    为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
AIDL (Android Interface Definition Language)是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中 (例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。

      AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

使用AIDL实现IPC(Implementing IPC Using AIDL):

     1. 创建.aidl文件-该文件(YourInterface.aidl)定义了客户端可用的方法和数据的接口。

     2. 在makefile文件中加入.aidl文件-(Eclipse中的ADT插件提供管理功能)Android包括名为AIDL的编译器,位于tools/文件夹。

     3. 实现接口-AIDL编译器从AIDL接口文件中利用Java语言创建接口,该接口有一个继承的命名为Stub的内部抽象类(并且实现了一些IPC调用的附加方法),要做的就是创建一个继承于YourInterface.Stub的类并且实现在.aidl文件中声明的方法。

     4. 向客户端公开接口-如果是编写服务,应该继承Service并且重载Service.onBind(Intent) 以返回实现了接口的对象实例


在创建YourInterface.aidl文件时,需要注意: AIDL 服务只支持有限的数据类型,即Java基本类型、集合类型、AIDL 自动生成的接口(需要手动import),如果需要使用复杂的数据就需要做更一步处理,比如实现了android.os.Parcelable 接口的类(需要import),而且要注意为实现了Parcelable 接口的类创建一个对应的aidl文件,文件名和类名相同,文件内容为:除了package必须有parcelable YourInterface。

 

一个简单的AIDL设计

      创建AIDL文件,在这个aidl中使用的复杂的数据类型(Person,Male,Female都实现了接口android.os.Parcelable):

package com.aidl.service;

import com.aidl.service.Person;
import com.aidl.service.Male;
import com.aidl.service.Female;

interface IPersonService {
	Female getFemale(String name);
	Male getMale(String name);
	Person getPerson(String name);
	
	List<Person> getPersons();
	List<Female> getFemales();
	List<Male> getMales();
	
	void createPerson(in Person person);
	void createFemale(in String name, in String telNumber, in int age);
	void createMale(in String name, in String telNumber, in int age);
	
	int getFemaleCount();
	int getMaleCount();
	int getPersonCount();
}

 Person.aild(Male,Female类似)很简单:

package com.aidl.service;

parcelable Person; 

 此时可以编译项目,Eclipse会在gen下自动生成IPersonService.java,该类中自动生成了Stub抽象类以及asInterface()等:

package com.aidl.service;
public interface IPersonService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.aidl.service.IPersonService
{
private static final java.lang.String DESCRIPTOR = "com.aidl.service.IPersonService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.aidl.service.IPersonService interface,
 * generating a proxy if needed.
 */
public static com.aidl.service.IPersonService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.aidl.service.IPersonService))) {
return ((com.aidl.service.IPersonService)iin);
}
return new com.aidl.service.IPersonService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
/**
 * 省略......
 */
public void createPerson(com.aidl.service.Person person) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((person!=null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_createPerson, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public void createFemale(java.lang.String name, java.lang.String telNumber, int age) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
_data.writeString(telNumber);
_data.writeInt(age);
mRemote.transact(Stub.TRANSACTION_createFemale, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}

}
public com.aidl.service.Female getFemale(java.lang.String name) throws android.os.RemoteException;
public com.aidl.service.Male getMale(java.lang.String name) throws android.os.RemoteException;
public com.aidl.service.Person getPerson(java.lang.String name) throws android.os.RemoteException;
public java.util.List<com.aidl.service.Person> getPersons() throws android.os.RemoteException;
public java.util.List<com.aidl.service.Female> getFemales() throws android.os.RemoteException;
public java.util.List<com.aidl.service.Male> getMales() throws android.os.RemoteException;
public void createPerson(com.aidl.service.Person person) throws android.os.RemoteException;
public void createFemale(java.lang.String name, java.lang.String telNumber, int age) throws android.os.RemoteException;
public void createMale(java.lang.String name, java.lang.String telNumber, int age) throws android.os.RemoteException;
public int getFemaleCount() throws android.os.RemoteException;
public int getMaleCount() throws android.os.RemoteException;
public int getPersonCount() throws android.os.RemoteException;
}

 配置Manifest.xml文件,下面是一个最最简单的配置方式:

<service android:name="com.aidl.service.PersonService">
	<intent-filter>
		<action android:name="com.aidl.service.action.PersonService" />
	</intent-filter>
</service>

 实现Service,类名可以根据自己喜好来定,Service中最主要的是实现aidl中各个方法,即,Stub中没有实现的抽象方法这里需要注意onBind()返回Stub:

package com.aidl.service;

import com.aidl.service.Person.SEX;

public class PersonService extends Service {

	private final String TAG = "PersonService";

	@Override
	public void onCreate() {
		super.onCreate();

		males = new ArrayList<Male>();
		females = new ArrayList<Female>();
		mPerson = new ArrayList<Person>();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		return super.onUnbind(intent);
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mPersonBinder;
	}

	private List<Male> males;
	private List<Female> females;
	private List<Person> mPerson;
	private IPersonService.Stub mPersonBinder = new IPersonService.Stub() {

		@Override
		public Female getFemale(String name) throws RemoteException {
			Female result = null;
			if (females == null || name == null || name.length() == 0)
				return null;

			for (Female f : females) {
				if (f.getName() != null && f.getName().length() > 0
						&& f.getName().equals(name)) {
					result = f;
					break;
				}
			}

			return result;
		}

/**
 * 
 * 此处省略其余方法的实现
 *
 */

}

 接下来可以定义自己外部使用的ServiceConnection,主要是onServiceConnected()构造你的接口类型,onServiceDisconnected()断开服务时处理,通常我们的ServiceConnection是一个单例,实现了Service的连接(connect)/断开(unconnect)方法:

package com.aidl.service;

public class PersonServiceConnent implements ServiceConnection {
	private static final String TAG = "PersonServiceConnent";
	private Context mContext;

	private static PersonServiceConnent connect;
	private final static Object synObj = new Object();

	private IPersonService myInterface;

	public static final String SERVICE_ACTION = "com.aidl.service.action.PersonService";
	public static final String SERVICE_PACKAGENAME = "com.aidl.main";
	public static final String SERVICE_CLASSNAME = "com.aidl.service.PersonService";

	@Override
	public void onServiceConnected(ComponentName name, IBinder service) {
		myInterface = IPersonService.Stub.asInterface(service);

		if (myInterface == null)
			Log.i(TAG, "in onServiceConnected() getCurrentPosition == null");
		else
			Log.i(TAG, "in onServiceConnected() getCurrentPosition != null");
	}

	@Override
	public void onServiceDisconnected(ComponentName name) {
		myInterface = null;
		bConnected = false;

		Log.i(TAG, "onServiceDisconnected:" + name);
	}

	private PersonServiceConnent(Context context) {
		mContext = context;
	}

	public static PersonServiceConnent Instance(Context context) {
		if (connect == null) {
			synchronized (synObj) {
				if (connect == null)
					connect = new PersonServiceConnent(context);
			}
		}

		return connect;
	}

	private Intent mIntent = new Intent();
	private boolean bStartService = false;
	private boolean bConnected = false;
	private ComponentName mComponentName;

	public synchronized boolean connect(Context context) {
		if (context == null)
			return false;

		mContext = context;
		mIntent.setAction(SERVICE_ACTION);

		if (!bStartService) {
			mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			try {
				mComponentName = mContext.startService(mIntent);
				if (mComponentName != null) {
					bStartService = true;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		if (connect != null && !connect.bConnected) {
			connect.bConnected = mContext.bindService(mIntent, connect,
					Context.BIND_AUTO_CREATE);
			if (!connect.bConnected) {
				try {
					mContext.unbindService(connect);
				} catch (Exception e) {
				}

				try {
					mContext.startActivity(mIntent);
				} catch (Exception e) {
				}

				try {
					connect.bConnected = mContext.bindService(mIntent, connect,
							Context.BIND_AUTO_CREATE);
				} catch (Exception e) {
				}
			}
		}

		return connect.bConnected;

	}

	public void unconnect() {
		if (mContext == null)
			return;
		else
			unconnect(mContext);
	}

	public void unconnect(Context context) {
		if (context == null)
			context = mContext;

		if (context == null)
			return;

		if (connect != null) {
			if (connect.bConnected) {
				try {
					context.unbindService(connect);
					bConnected = false;
				} catch (Exception e) {
				}

				try {

					Intent tmpIntent = new Intent();
					if (mComponentName != null) {
						tmpIntent.setComponent(mComponentName);
					} else {
						tmpIntent.setClassName(SERVICE_PACKAGENAME,
								SERVICE_CLASSNAME);
					}
					context.stopService(tmpIntent);

					bStartService = false;
				} catch (Exception e) {
					Log.e(TAG, "unconnect error", e);
				}
			}
		}
	}

	/**
	 *  getFemale()供我们在外部调用ServiceConnection的时候使用,其实现就是调用Service中的方法而已
	 * @param name
	 * @return
	 */
	public Female getFemale(String name) {
		if (myInterface == null) {
			Log.i(TAG, "in getFemale() myInterface == null");
			this.connect(mContext);
			return null;
		}

		try {
			return myInterface.getFemale(name);
		} catch (RemoteException e) {
			Log.i(TAG, "getFemale()", e);
			return null;
		}
	}

/**
 * 
 * 省略其余类似getFemale方法的实现
 * 
 */

}

 在上面的ServiceConnection的代码中,onServiceConnected获取Service使用了Stub.asInterface(service),这种方式是常见的。其中的connect和unconnect也是比较常见的写法,基本类似。connect中,Intent的Action必须与AndroidManifest.xml中对应<service>的action一致。在unconnect中setClassName(String packageName, String className)的参数需要注意packageName为应用的packageName,而非简单的class的package,className为绝对class(带包名)。

 

    这样就比较完整的实现了一个AIDL,这里的例子虽然比较简单,但是AIDL实现的过程和步骤基本是一样的,而对于ServiceConnection中最主要的几个方法的写法也基本大同小异。

分享到:
评论

相关推荐

    Android AIDL使用详解

    aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口 icp:interprocess communication :内部进程通信

    Android AIDL示例

    Android AIDL简单的演示用例 Android的 AIDL是安卓接口定义语言,是Android跨进程通信的一种常用方式。

    AIDL客户端demo

    AIDL(Android 接口定义语言) 是 Android 提供的一种进程间通信 (IPC) 机制。通过这种机制,我们只需要写好 aidl 接口文件,编译时系统会帮我们生成 Binder 接口,实现进程之间的通讯。 一、如何定义aidl文件 1、...

    Android AIDL入门测试案例

    AIDL(Android接口定义语言),目的是为了实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信。 博客地址:http://blog.csdn.net/chenzheng8975/article/details/54140098

    Android-AIDL文件实现两个工程之间互相传输

    AIDL概述:AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言,设计这门语言的目的是为了实现进程间通信。接下来我写了两个demo(AildeService和AidleClient),他们之间...

    Android AIDL实现跨进程通信的示例代码

    AIDL是Android接口定义语言,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。 实现步骤 例:用 A程序去访问 B程序的MyService.java服务 在B中...

    Android Studio AIDL实现跨进程通信

    AIDL:Android Interface Definition Language,即Android接口定义语言. android studio中使用aidl实现跨进程通讯,具体步骤如下

    android项目之aidl跨进程调用举例Demo

    3. 实现接口-AIDL编译器从AIDL接口文件中利用Java语言创建接口,该接口有一个继承的命名为Stub的内部抽象类(并且实现了一些IPC调用的附加方法),要做的就是创建一个继承YourInterface.Stub的类并且实现在.aidl文件...

    基于Android AIDL进程间通信接口使用介绍

    AIDL:Android Interface Definition Language,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。 ICP:Interprocess Communication ,内部进程通信。 使用: 1、先创建一个aidl文件...

    AIDL最简单的使用步骤

    AIDL:Android Interface Definition Language,即Android接口定义语言。 为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他...

    Android接口定义语言1

    2. 实现接口 (#ImplementTheInterface)3. 向客户端公开该接口 (#ExposeTheInterface)1. 创建 .aidl

    AIDL.rar示例

    aidl(Android 接口定义语言 )

    AIDL进程间通讯demo

    AIDL进程间通讯demo,A [android] I [Interface] D [Definition] L [Language],Android接口定义语言。 作用:方便系统为我们生成代码从而实现跨进程通讯,仅此而已。(玉刚老师如是说也),也就是说这个AIDL就只是一...

    Android AIDLDemo

    Android中2个进程无法直接通信,必须通过Android系统底层间接通信,而跨进程通信有4种方式,分别对应4大组件,其中Service对应的就叫AIDL,即Android Interface Defined Language安卓接口定义语言。这个是一个简单的...

    Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)

    AIDL:Android Interface Definition Language,翻译过来就是Android接口定义语言。是用于定义服务器和客户端通信接口的一种描述语言,可以拿来生成用于IPC的代码。所以使用AIDL需要一个服务端和客户端 作用:可以在...

    AIDL服务端

    AIDL(Android 接口定义语言) 是 Android 提供的一种进程间通信 (IPC) 机制。通过这种机制,我们只需要写好 aidl 接口文件,编译时系统会帮我们生成 Binder 接口,实现进程之间的通讯。 一、如何定义aidl文件 1、...

    AIDL示例(Android Interface Definition Language)

    与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和...

    Android程序设计之AIDL实例详解

    AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象...

    Android中两个APP之间的AIDL调用测试.rar

    ①Android Interface definition language(aidl,android接口定义语言),其目的实现跨进程的调用。进程是程序在os中执行的载体,一个程序对应一个进程,不同进程就是指不同程序,aidl实现不同程序之间的调用。 ②...

Global site tag (gtag.js) - Google Analytics