Android實現處理序間通訊aidl的使用

來源:互聯網
上載者:User

現在總結一下這個用法:
其實很簡單,主要就是以下的幾個步驟:
1.第一步,定義aidl檔案(可以參照IWifiManager.java的定義來實現,其實就是定義一個Interface,提供被調用的方法);
例如 (IMyService.aidl):
package com.demo;

import com.demo.Person;

interface IMyService {
        void savePersonInfo(in Person person);//注意,這裡的Person類不是基礎資料型別 (Elementary Data Type)哦,要進行處理的,見下文
        List<Person> getAllPerson();
}


2.第二步,寫一個service,實現stub類(也就是實現剛才的那些介面),return stub類的對象(也就是binder);
    建立一個類實現剛才那個aidl的介面:
public class RemoteService extends Service {

        private LinkedList<Person> personList = new LinkedList<Person>();
        
        @Override
        public IBinder onBind(Intent intent) { //activity
                return mBinder;
        }

        private final IMyService.Stub mBinder = new IMyService.Stub(){

                @Override
                public void savePersonInfo(Person person) throws RemoteException {
                        if (person != null){
                                personList.add(person);
                        }
                }

                @Override
                public List<Person> getAllPerson() throws RemoteException {
                        return personList;
                }
        };
}


註:
  這裡會看到有一個名為IMyService.Stub類,查看aidl檔案產生的Java檔案原始碼就能發現有這麼一段代碼:
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.demo.IMyService
 原來Stub類就是繼承於Binder類,也就是說RemoteService類和普通的Service類沒什麼不同,只是所返回的IBinder對象比較特別,是一個實現了AIDL介面的Binder。

 


3.第三步,在activity裡面啟動service。
通過IMyService.Stub.asInterface(service)來得到IMyService對象:
private IMyService mRemoteService;

private ServiceConnection mRemoteConnection = new ServiceConnection() {   
        public void onServiceConnected(ComponentName className, IBinder service) {   
                mRemoteService = IMyService.Stub.asInterface(service);   
        }   

        public void onServiceDisconnected(ComponentName className) {   
                mRemoteService = null;   
        }   
};
註:
 在產生的IMyService.java裡面會找到這樣的代碼:
/**
* Cast an IBinder object into an com.demo.IMyService interface,
* generating a proxy if needed.
*/
public static com.demo.IMyService asInterface(android.os.IBinder obj) {...}

 


而service的綁定沒有什麼不同:
if (mIsRemoteBound) {
        unbindService(mRemoteConnection);
}else{
        bindService(new Intent("com.demo.IMyService"),
                               mRemoteConnection, Context.BIND_AUTO_CREATE);
}

mIsRemoteBound = !mIsRemoteBound;
 
通過IPC調用/傳遞資料
    用戶端綁定service後就能通過IPC來調用/傳遞資料了,直接調用service對象的介面方法:

addPersonButton.setOnClickListener(
                new View.OnClickListener(){
                        private int index = 0;

                        @Override
                        public void onClick(View view) {
                                Person person = new Person();
                                index = index + 1;
                                person.setName("Person" + index);
                                person.setAge(20);
                                person.setTelNumber("123456");
                                try {
                                        mRemoteService.savePersonInfo(person);
                                } catch (RemoteException e) {
                                        e.printStackTrace();
                                }
                        }
                });

listPersonButton.setOnClickListener(
                new View.OnClickListener(){

                        @Override
                        public void onClick(View view) {
                                List<Person> list = null;

                                try {
                                        list = mRemoteService.getAllPerson();
                                } catch (RemoteException e) {
                                        e.printStackTrace();
                                }

                                if (list != null){
                                        StringBuilder text = new StringBuilder();

                                        for(Person person : list){
                                                text.append("\nPerson name:");
                                                text.append(person.getName());
                                                text.append("\n             age :");
                                                text.append(person.getAge());
                                                text.append("\n tel number:");
                                                text.append(person.getTelNumber());
                                        }

                                        inputPersonEdit.setText(text);
                                }else {
                                        Toast.makeText(ServiceActivity.this, "get data error",
                                                        Toast.LENGTH_SHORT).show();
                                }
                        }
                });

 

 


另外關於第一步,附加的說一下。當aidl中的介面中的傳回值或參數不是基礎資料型別 (Elementary Data Type)時,需要做如下的兩步:
1.給一個aidle的實現:
package com.demo;

parcelable Person;
 2.給一個序列化(實現java類)
public class Person implements Parcelable {

        private String name;
        private String telNumber;
        private int age;

        public Person() {}

        public Person(Parcel pl){
                name = pl.readString();
                telNumber = pl.readString();
                age = pl.readInt();
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public String getTelNumber() {
                return telNumber;
        }

        public void setTelNumber(String telNumber) {
                this.telNumber = telNumber;
        }

        public int getAge() {
                return age;
        }

        public void setAge(int age) {
                this.age = age;
        }

        @Override
        public int describeContents() {
                return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
                dest.writeString(name);
                dest.writeString(telNumber);
                dest.writeInt(age);
        }

        public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {

                @Override
                public Person createFromParcel(Parcel source) {
                        return new Person(source);
                }

                @Override
                public Person[] newArray(int size) {
                        return new Person[size];
                }

        };
}


Parcelable需要實現三個函數:
    1) void writeToParcel(Parcel dest, int flags) 將需要序列化儲存的資料寫入外部提供的Parcel對象dest。而看了網上的代碼例子,個人猜測,讀取Parcel資料的次序要和這裡的write次序一致,否則可能會讀錯資料。具體情況我沒實驗過!
    2) describeContents() 沒搞懂有什麼用,反正直接返回0也可以
    3) static final Parcelable.Creator對象CREATOR  這個CREATOR命名是固定的,而它對應的介面有兩個方法:
    createFromParcel(Parcel source) 實現從source建立出JavaBean執行個體的功能
    newArray(int size) 建立一個類型為T,長度為size的數組,僅一句話(return new T[size])即可。估計本方法是供外部類還原序列化本類數組使用。

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.