在 service和activity通信这篇文章的基础上,我们再来学习aidl。
aidl是android跨进程通信的常用方法
AIDL对Java类型的支持如下:
1.AIDL支持Java原始数据类型。
2.AIDL支持String和CharSequence。
3.AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个import语句,即使位于同一个包中。
4.AIDL支持传递实现了android.os.Parcelable接口的复杂类型,同样在引用这些类型时也需要import语句。(Parcelable接口告诉Android运行时在封送(marshalling)和解封送(unmarshalling)过程中实现如何序列化和反序列化对象,你可以很容易联想到java.io.Serializable接口。有些朋友可能会有疑问,两种接口功能确实类似,但为什么Android不用内置的Java序列化机制,而偏偏要搞一套新东西呢?这是因为Android团队认为Java中的序列化太慢,难以满足Android的进程间通信需求,所以他们构建了Parcelable解决方案。Parcelable要求显示序列化类的成员,但最终序列化对象的速度将快很多。另外要注意的是,Android提供了两种机制来将数据传递给另一个进程,第一种是使用Intent将数据束(Bundle)传递给活动,第二种也就是Parcelable传递给服务。这两种机制不可互换,不要混淆。也就是说,Parcelable无法传递给活动,只能用作AIDL定义的一部分)。
5.AIDL支持java.util.List和java.util.Map,但是有一些限制。集合中项的允许数据类型包括Java原始类型、String、CharSequence或是android.os.Parcelable。无需为List和Map提供import语句,但需要为Parcelable提供import语句。
6.非原始类型中,除了String和CharSequence以外,其余均需要一个方向指示符。方向指示符包括in、out、和inout。in表示由客户端设置,out表示由服务端设置,inout表示客户端和服务端都设置了该值。默认类型其实隐含了一个默认指示符in
参考自http://blog.csdn.net/liuhe688/article/details/6409708
注意事项
1、oneway关键字在跨进程调用的时候使得调用不阻塞,直接返回。在同一个进程内,oneway没有任何意义。
2、aidl文件可以引用aidl文件,但不能引用java文件。所以有时候我们想要在进程间传输某个对象,比如BaseData,首先要BaseData实现parceble,写一个java文件,然后在同样的目录下写个同名aidl文件,并注明parceble BaseData作为定义,然后其他aidl文件才能引用BaseData,可参考http://blog.csdn.net/dangnianmingyue_gg/article/details/48197293 内的PayClass。
例子
activity获取service数据关键连接点是onServiceConnected
首先写服务端的app: AidlServer
这里我们创建一个Service类MyService,在MyService中放1个计时器
public void onCreate() {
super.onCreate();
String TAG="";
LogFish.d("onCreate process name " + SystemUtil.getCurProcessName(MyService.this));
Log.i(TAG, "Service is Created");
thread = new Thread(new Runnable() {
@Override
public void run() {
// 每间隔0.1秒count加1 ,直到quit为true
while (!quit) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
});
thread.start();
}
编写aidl接口,getCount用来获取service的数据,complexCal用来做复杂计算,注意这里是跨进程的
interface IMyAidlInterface {
int getCount();
double complexCal(String str,int t);
}
service中的binder重写aidl接口方法
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public int getCount() throws RemoteException {
return count;
}
@Override
public double complexCal(String str, int t) throws RemoteException {
int ret=str.hashCode()+t;
return ret*0.3;
}
};
manifest中的MyService配置如下
<service
android:name=".MyService"
android:process="com.myservice">
<intent-filter>
<action android:name="com.example.servicetest.MyAIDLService" />
</intent-filter>
</service>
文件目录如下:
再编写客户端app:AidlClient
首先在同样目录下,放一模一样的aidl文件
再编写activity文件,代码如下
public class MainActivity extends Activity implements View.OnClickListener {
private Button bindService;
private Button unbindService;
private IMyAidlInterface myAIDLInterface;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogFish.d("process name"+ SystemUtil.getCurProcessName(MainActivity.this));
myAIDLInterface = IMyAidlInterface.Stub.asInterface(service);
try {
int cnt = myAIDLInterface.getCount();
double db = myAIDLInterface.complexCal("hello world",6);
LogFish.d("result is " + cnt);
LogFish.d( "complexCal value " + db);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService = (Button) findViewById(R.id.bind_service);
unbindService = (Button) findViewById(R.id.unbind_service);
Button bv = (Button) findViewById(R.id.get_num);
bv.setOnClickListener(this);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
Intent intent = new Intent("com.example.servicetest.MyAIDLService");
startService(intent);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bind_service:
Intent intent = new Intent("com.example.servicetest.MyAIDLService");
boolean b= bindService(intent, connection, Service.BIND_AUTO_CREATE);
LogFish.d("bind result "+b);
break;
case R.id.unbind_service:
// Intent unbindIntent = new Intent(this, com.aidl.server.MyService.class);
unbindService(connection);
LogFish.d("unbind ");
break;
default:
break;
}
}
}
Ok,代码编写完毕,先安装AidlServer,再运行AidlClient
结果如下:
05-13 19:35:07.246 1734-1734/com.aidl.client D/LogFish﹕ result is 41
05-13 19:35:07.246 1734-1734/com.aidl.client D/LogFish﹕ complexCal value is 5.382318174E8
result是指service启动到bind之间的时间,complexCal value是AidlServer计算出来的结果,AidlClient提供参数
用到module:AidlServer和AidlClient