1. 程式人生 > >Android AIDL淺析(一)

Android AIDL淺析(一)

一、什麼是AIDL?

  • AIDL是一個縮寫,全稱是Android Interface Definition Language,也就是Android介面定義語言;
  • AIDL是進行程序間通訊的常用方式

二、怎麼使用AIDL?

總體來說,使用AIDL的過程可以總結為:
  1. 定義AIDL介面
  2. 服務端對AIDL介面進行邏輯補全
  3. 客戶端通過AIDL介面呼叫服務端邏輯進行各種操作

資料跨程序傳輸過程就在這種呼叫與被呼叫過程中通過binder進行

程式碼詳析(非原始資料型別):

1. 待傳輸物件類:

public class People implements Parcelable {
private String name; private int age; private String sex; //無參建構函式 public People() { name = ""; age = 0; sex = ""; } //一般建構函式,提供給使用者構造People物件 public People(String name, int age, String sex) { this.name = name; this.age = age; this
.sex = sex; } //Android studio可自動生成,提供給系統 Creator 生成People物件 protected People(Parcel in) { name = in.readString(); age = in.readInt(); sex = in.readString(); } //這個物件是AIDL中tag為in或inout時候呼叫的,即從序列化流中建立people物件的時候呼叫 public static final Creator<People> CREATOR = new
Creator<People>() { @Override public People createFromParcel(Parcel in) { return new People(in); } @Override public People[] newArray(int size) { return new People[size]; } }; //Parcel的內容包含檔案描述符,一般傳0 @Override public int describeContents() { return 0; } //如果你需要使用out或inout的tag的話,就要自己定義這個函式,它目的是通過流修改當前people物件的屬性 public void readFromParcel(Parcel parcel) { name = parcel.readString(); age = parcel.readInt(); sex = parcel.readString(); } //將為tag為in的資料寫入流中傳輸 @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(name); parcel.writeInt(age); parcel.writeString(sex); } //無特殊意義,只是為了方便顯示 @Override public String toString() { return name + ", " + age + " years old, is a " + sex; }

2. 待傳輸物件的AIDL檔案(AIDL類1):

package com.AIDL_demo;
parcelable People;//只需要宣告本類為parcelable

3. 定義介面方法的AIDL(AIDL類2):

package com.AIDL_demo;
import com.AIDL_demo.People;

interface IMethod {
    List<People> getPeople();
}

4. 服務端:

public class MyService extends Service {

    List<People> people = new ArrayList<>();

    private final IMethod.Stub method = new IMethod.Stub() {
        @Override
        public List<People> getPeople() throws RemoteException {
            return people;
        }
    };

    public MyService() {
        People man1 = new People("Mike", 18, "male");
        people.add(man1);

        People man2 = new People("Lucy", 26, "female");
        people.add(man2);
    }

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

5. 客戶端關鍵程式碼:

//跨程序啟動service
public void bindRemoteService() {
        Intent intent = new Intent();
        intent.setAction("my_remote_service");//manifest中service的action
        intent.setPackage("com.AIDL_demo");//服務端的package名
        bindService(intent, connection, Service.BIND_AUTO_CREATE);
    }

    private IMethod method;

    private final ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            method = IMethod.Stub.asInterface(iBinder);//獲取遠端服務端的AIDL通訊物件
            if (method == null) {
                Log.d("LogTag", "IMethod is null");
                return;
            }
            try {
                List<com.AIDL_demo.People> peopleList = method.getPeople();//呼叫遠端介面獲取服務端資料
                //列印資料
                StringBuilder stringBuilder = new StringBuilder();
                for (People people : peopleList) {
                    stringBuilder.append(people.toString());
                    stringBuilder.append("\n");
                }
                Log.d("LogTag", stringBuilder.toString());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d("LogTag", "service disconnected");
        }
    };
最終執行會在客戶端Logcat中列印:
D/LogTag: Mike, 18 years old, is a male
Lucy, 26 years old, is a female

結論:成功跨程序通訊,將服務端建立的兩個People物件,傳輸到了客戶端;

注意事項

  • AIDL檔案必須和這個非原始資料類在同名包下,只是一個在Java目錄下,一個在AIDL目錄下:
    這裡寫圖片描述
  • AIDL中在引數為非預設資料型別的變數時,都需要設定定向的tag
  • ADIL中預設支援Java八大基本型別和String,CharSequence,List(元素必須是AIDL支援的,List可以使用泛型),Map(元素必須是AIDL支援,Map不支援泛型);

  • AIDL檔案可以分為兩類。一類是用來定義非預設支援的資料型別,以供其他AIDL檔案使用的,如上面程式碼中的 “AIDL類1” ;一類是用來定義方法介面,用來完成跨程序通訊的,如上面程式碼中的 “AIDL類2” 。