一、常见问题回顾
1、为什么要使用aidl?
答:aidl可以进行跨进程通讯。
2、aidl文件是怎么变成java代码的?
答:aidl是Android interface definition language的缩写,是一种中间语言,用于描述跨进程通信时的业务逻辑。aidl文件是通过android sdk中的名为aidl的程序生成java文件的,一般在{android-sdk}/build-tools/{android版本}/这个目录下。
3、aidl中都可以使用哪些数据类型?
答:可以使用基本的java数据类型(除了short以外),比如int, boolean, String,也可以使用List类型,如果要使用自己的类则该类需要实现Parcelable接口。
4、服务端中aidl接口的改变会不会导致未更新aidl的客户端崩溃或者出现数据混乱?
答:假如服务端中aidl更新了,客户端未更新,客户端不会报错。假如更新的接口是在接口的尾部添加的,不会出现数据混乱,如果接口在中间添加则会引发后面的函数返回结果混乱。即aidl的函数列表顺序不能乱。
二、aidl服务端开发步骤(使用Android Studio)
1、新建一个android工程
2、新建一个Service,本例为MyAidlService.java
3、新建一个aidl文件,比如IMyAidlInterface
4、为此aidl增加一个函数,比如如下,然后使用Android Studio重新编译一下项目:
Java
package com.zht.car.aidlserver;
interface IMyAidlInterface {
int getAge();
}
1
2
3
4
5
packagecom.zht.car.aidlserver;
interfaceIMyAidlInterface{
intgetAge();
}
5、在MyAidlService.java中,定义一个内部类,继承自IMyAidlInterface.Stub,比如AidlInterfaceStub
6、在MyAidlService.java中定义一个AidlInterfaceStub对象并初始化,如AidlInterfaceStub mAidlInterfaceStub = new AidlInterfaceStub();
7、在MyAidlService.java的onBind函数中返回上一步定义的对象,这样服务端的开发就完成了。
三、aidl客户端开发步骤
1、新建一个android工程
2、将服务端的aidl文件拷贝到客户端工程中,要保持aidl文件所在相对路径与服务端的路径结构一致,即让这个aidl的包名和服务端的包名一致
3、在客户端的Activity中定义一个IMyAidlInterface的对象,如:mIClientAidlInterface
4、在Activity的定义一个ServiceConnection对象,并用new进行实例化,这个ServiceConnection对象会生成以下两个回调函数的结构onServiceConnected和onServiceDisconnected
5、在上一个函数的onServiceConnected的回调中给mIClientAidlInterface赋值,如下
Java
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIClientAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
1
2
3
4
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
mIClientAidlInterface=IMyAidlInterface.Stub.asInterface(service);
}
6、通过上一步得到的mIClientAidlInterface就可以调用远端的函数了
7、哦哦、忘了还没有绑定服务,为方便简单说明,我们直接在onCreate里绑定远端服务吧,如下:
Java
Intent intent = new Intent();
//第一个参数:包名,第二个参数:服务的类的全名
intent.setClassName("com.zht.car.aidlserver", "com.zht.car.aidlserver.MyAidlService");
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
1
2
3
4
Intentintent=newIntent();
//第一个参数:包名,第二个参数:服务的类的全名
intent.setClassName("com.zht.car.aidlserver","com.zht.car.aidlserver.MyAidlService");
bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
8、客户端到此也完成了,看后面的全部代码试着写一下吧
四、代码
客户端:
package com.zht.car.aidlclient;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.zht.car.aidlserver.IMyAidlInterface;
public class MainActivity extends AppCompatActivity {
private IMyAidlInterface mIClientAidlInterface;
private String LOG_TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
//第一个参数:包名,第二个参数:服务的类的全名
intent.setClassName("com.zht.car.aidlserver", "com.zht.car.aidlserver.MyAidlService");
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
}
ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIClientAidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
Log.d(LOG_TAG, "我的年龄:" + mIClientAidlInterface.getAge());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
packagecom.zht.car.aidlclient;
importandroid.content.ComponentName;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.os.IBinder;
importandroid.os.RemoteException;
importandroid.support.v7.app.AppCompatActivity;
importandroid.os.Bundle;
importandroid.util.Log;
importcom.zht.car.aidlserver.IMyAidlInterface;
publicclassMainActivityextendsAppCompatActivity{
privateIMyAidlInterfacemIClientAidlInterface;
privateStringLOG_TAG="MainActivity";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intentintent=newIntent();
//第一个参数:包名,第二个参数:服务的类的全名
intent.setClassName("com.zht.car.aidlserver","com.zht.car.aidlserver.MyAidlService");
bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
}
ServiceConnectionmServiceConnection=newServiceConnection(){
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
mIClientAidlInterface=IMyAidlInterface.Stub.asInterface(service);
try{
Log.d(LOG_TAG,"我的年龄:"+mIClientAidlInterface.getAge());
}catch(RemoteExceptione){
e.printStackTrace();
}
}
@Override
publicvoidonServiceDisconnected(ComponentNamename){
}
};
}
服务端:
package com.zht.car.aidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyAidlService extends Service {
AidlInterfaceStub mAidlInterfaceStub = new AidlInterfaceStub();
public MyAidlService() {
}
@Override
public IBinder onBind(Intent intent) {
return mAidlInterfaceStub.asBinder();
}
class AidlInterfaceStub extends IMyAidlInterface.Stub{
@Override
public int getAge() throws RemoteException {
return 20;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
packagecom.zht.car.aidlserver;
importandroid.app.Service;
importandroid.content.Intent;
importandroid.os.IBinder;
importandroid.os.RemoteException;
publicclassMyAidlServiceextendsService{
AidlInterfaceStubmAidlInterfaceStub=newAidlInterfaceStub();
publicMyAidlService(){
}
@Override
publicIBinderonBind(Intentintent){
returnmAidlInterfaceStub.asBinder();
}
classAidlInterfaceStubextendsIMyAidlInterface.Stub{
@Override
publicintgetAge()throwsRemoteException{
return20;
}
}
}
五、完整代码下载地址
六、其他问题
1、为什么byte[]数组不能作为参数传递?
传递byte数组时需要添加上in、out、inout修饰符,如下:
interface ITestAidl{
sendData(in byte[] data);
}
1
2
3
4
5
interfaceITestAidl{
sendData(inbyte[]data);
}
打赏
微信扫一扫,打赏作者吧~