AIDL:
一种接口定义语言来公开服务的接口,跨进程访问的服务
建立AIDL服务的步骤:
服务端的实现
在Java源文件目录下建立一个aidl文件,直接通过点击new创建aidl文件,Android Studio会自动帮你新建aidl包。具体位置如图:
aidl文件位置.png
// UserInfo.aidlpackage com.ting.android.aidldemo;// Declare any non-default types here with import statementsinterface UserInfo { String getInfo(); }
aidl文件的内容与Java代码非常相似,但是要注意,不能加任何权限修饰符,AIDL不支持的数据类型。
如果UserInfo.aidl文件中的内容输入正确,我们rebuild项目,ADT会自动生成一个UserInfo.java文件,我们开发中不需要关注这个文件的内容。
编写一个Service类,MyAidlServletService类继承于Service,在MyAidlServletService类中定义了一个内部类(MyBinder),该类继承自UserInfo.Stub。
public class MyAidlServletService extends Service { public class MyBinder extends UserInfo.Stub{ @Override public String getInfo() throws RemoteException { return "这里是服务端返回的信息"; } } public MyAidlServletService() { } @Override public IBinder onBind(Intent intent) { return new MyBinder(); //这里一定要返回内部类的对象 } }
UserInfo.Stub是自动生成的,不需要关注。只需要继承之后,实现要调用的方法即可。在onBind方法中必须返回内部类的对象,否则客户端无法获取服务对象
在AndroidMainifest.xml文件中配置MyAidlServletService类。
<service android:name=".MyAidlServletService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.ting.android.aidldemo.UserInfo" /> </intent-filter> </service>
其中,"com.ting.android.aidldemo.UserInfo"是客户端要访问AIDL服务的ID。客户端要保持一致。
客户端的实现
将服务端的aidl文件包直接拷贝到客户端同样的目录下面。
客户端aidl.png
新建一个ServiceConnection,在里面获取到UserInfo的对象
/** * 需要绑定远程的Service */ private class MyServletConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { userInfo = UserInfo.Stub.asInterface(iBinder); Log.i("AIDL: ","绑定成功"); } @Override public void onServiceDisconnected(ComponentName componentName) { userInfo = null; } }
通过intent绑定Service
Intent mIntent = new Intent("com.ting.android.aidldemo.UserInfo"); //服务器配置的 action name 要保持一致。 mIntent.setPackage("com.ting.android.aidldemo"); //这里设置服务器的包名,这样避免要求显示调用 bindService(mIntent, new MyServletConn(), BIND_AUTO_CREATE);
传递复杂数据的AIDL服务
AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据就需要做进一步处理,AIDL服务支持的数据类型如下:
Java的简单类型(int、char、boolean),不需要导入(import)
String和CharSequence。不需要导入(import)
List和Map。但是要注意,List和Map对象的元素类型必须是AIDL服务支持的数据类型。不需要导入(import)
AIDL自动生成的接口。需要导入(import)
实现android.os.Parcelable接口的类,需要导入(import)
对于传递需要导入的复杂数据类型,具体的操作步骤如下
服务端实现
创建一个IMyAidlInterface.aidl文件
// IMyAidlInterface.aidlpackage com.ting.android.aidldemo;//注意:这里有一个巨坑,这包名不能加aidl。不然会报错import com.ting.android.aidldemo.Product;interface IMyAidlInterface { Map getMap(in String country, in Product product); Product getProduct(); }
Product是一个实现android.os.Parcelable接口的类,需要使用import导入这个类。如果方法的类型是非简单类型,例如,String、List或者自定义的类,需要使用in、out或inout进行修饰,其中in表示这个值可以被客户端设置,out表示这个值可以被服务端设置,inout表示这个值既可以被客户端设置,又可以被服务端设置。
编写Product类,该类是用于传递的数据类型
public class Product implements Parcelable { private int id; private String name; private float price; public static final Parcelable.Creator<Product> CREATOR = new Parcelable.Creator<Product>() { @Override public Product createFromParcel(Parcel parcel) { return new Product(parcel); } @Override public Product[] newArray(int i) { return new Product[i]; } }; public Product() { } Product(Parcel in) { readFromParcel(in); } @Override public int describeContents() { return 0; } public void readFromParcel(Parcel parcel) { id = parcel.readInt(); name = parcel.readString(); price = parcel.readFloat(); } @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeInt(id); parcel.writeString(name); parcel.writeFloat(price); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } @Override public String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + '}'; } }
Product类必须实现android.os.Parcelable接口,该接口用于序列化。在Product类中必须有一个静态常量,常量名必须是CREATOR,而且CREATOR常量的数据类型必须是Parcelable.Creator。通过实现newArray和createFromParcel方法可以将序列化的数据转换为Product对象和Product数组。在readFromParcel方法中需要从序列化数据读取相应的值。在writeToParcel方法中需要将要序列化数据写入Parcel对象。从这一点,对象序列化和反序列化的过程是通过手工完成的。
编写一个Product.aidl文件
package com.ting.android.aidldemo;parcelable Product;
编写一个IMyAidlInterface类
// IMyAidlInterface.aidlpackage com.ting.android.aidldemo;//注意:这里有一个巨坑,这包名不能加aidl。不然会报错import com.ting.android.aidldemo.Product;interface IMyAidlInterface { Map getMap(in String country, in Product product); Product getProduct(); }
在Androidmainifest.xml文件中配置IMyAidlInterface
<service android:name=".MyService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.ting.android.aidldemo.MyService"/> </intent-filter>
作者:一只胖胖胖胖猿
链接:https://www.jianshu.com/p/d9e3b4d4361a
共同学习,写下你的评论
评论加载中...
作者其他优质文章