一、常见问题回顾
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重新编译一下项目:
1 2 3 4 5 |
package com.zht.car.aidlserver; interface IMyAidlInterface { int getAge(); } |
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赋值,如下
1 2 3 4 |
@Override public void onServiceConnected(ComponentName name, IBinder service) { mIClientAidlInterface = IMyAidlInterface.Stub.asInterface(service); } |
6、通过上一步得到的mIClientAidlInterface就可以调用远端的函数了
7、哦哦、忘了还没有绑定服务,为方便简单说明,我们直接在onCreate里绑定远端服务吧,如下:
1 2 3 4 |
Intent intent = new Intent(); //第一个参数:包名,第二个参数:服务的类的全名 intent.setClassName("com.zht.car.aidlserver", "com.zht.car.aidlserver.MyAidlService"); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); |
8、客户端到此也完成了,看后面的全部代码试着写一下吧
四、代码
客户端:
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 |
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 |
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; } } } |
五、完整代码下载地址
https://download.csdn.net/download/wintergoes/11200474
六、其他问题
1、为什么byte[]数组不能作为参数传递?
传递byte数组时需要添加上in、out、inout修饰符,如下:
1 2 3 4 5 |
interface ITestAidl{ sendData(in byte[] data); } |
Sorry, the comment form is closed at this time.