一、引言

  AIDL是android內(nèi)部進(jìn)程通信接口的描述語言,是實(shí)現(xiàn)跨進(jìn)程方法調(diào)用的一大利器,其中Binder和Messenger的實(shí)現(xiàn)機(jī)制都是AIDL。

二、使用下面結(jié)合示例說明其使用過程:

  本次示例的基本要求是完成一個(gè)圖書館圖書入庫和在庫圖書列表查詢的demo,

  1、為了完成這個(gè)功能,我們首先需要一個(gè)實(shí)體類Book,這個(gè)實(shí)體類需要序列化,因?yàn)橹挥行蛄谢院蟮腂ook對象才能在AIDL中使用。

  2、接下來我們需要新建Book.aidl和IBookManager.aidl

         我們需要在Book.aidl聲明這個(gè)Book類,并在IBookManager中導(dǎo)入Book.aidl并實(shí)現(xiàn)兩個(gè)功能:addBook和getBookList

  3.reBuild項(xiàng)目,這樣就會(huì)自動(dòng)生成IbookManager.java這個(gè)AIDL文件。(如果查找不到Book類,請參看我的另外一篇文章,Binder的機(jī)制淺析)

  4.接下來的我們就需要在客戶端和服務(wù)端完成對應(yīng)的工作:

 下面簡單介紹一下Service和Client中的實(shí)現(xiàn)內(nèi)容。(具體代碼在最后貼出)

Service:服務(wù)端的工作的關(guān)鍵其實(shí)在于實(shí)現(xiàn)Binder,而這個(gè)Binder的獲取就是去實(shí)例化IBookManager.Stub這個(gè)內(nèi)部類,并實(shí)現(xiàn)AIDL接口中聲明的方法 ,最后在onBind中返回這個(gè)Binder實(shí)例即可。

Client:客戶端則首先需要綁定遠(yuǎn)程服務(wù),然后在綁定成功后將服務(wù)端返回的IBinder對象轉(zhuǎn)換為AIDL接口,然后就可以通過這個(gè)接口去調(diào)用服務(wù)端的遠(yuǎn)程方法了。(這里需要注意的是,如果服務(wù)端中實(shí)現(xiàn)的方法為耗時(shí)方法,在客戶端中對它進(jìn)行遠(yuǎn)程調(diào)用的時(shí)候需要在子線程中進(jìn)行,原理在Binder機(jī)制中談到過,因?yàn)榭蛻舳嗽谶M(jìn)行遠(yuǎn)程調(diào)用的時(shí)候,會(huì)掛起自身,等待服務(wù)端的反饋,這個(gè)時(shí)候如果在主線程則會(huì)堵塞主線程)

  上面的例子相當(dāng)于是客戶端遠(yuǎn)程調(diào)用服務(wù)端中的方法,下面講的一個(gè)擴(kuò)充相當(dāng)于是服務(wù)端遠(yuǎn)程調(diào)用客戶端中的方法

  場景描述:假設(shè)還有一個(gè)需求是用戶希望圖書館在新書入庫的時(shí)候通知他

  不難發(fā)現(xiàn)這其實(shí)就是觀察者模式的經(jīng)典引用。這個(gè)時(shí)候我們需要增加一個(gè)AIDL接口,每個(gè)用戶需要實(shí)現(xiàn)這個(gè)接口并向圖書館申請新書的提醒功能,并且可以隨時(shí)取消這個(gè)提醒。而服務(wù)端則會(huì)維持一個(gè)listener的注冊表,當(dāng)新書到庫時(shí),遍歷并通知當(dāng)前已經(jīng)注冊了提醒功能的用戶新書到庫。

  這邊我們創(chuàng)建一個(gè)接口IOnNewBookArrivedListener.aidl,并且在原有的接口中新增兩個(gè)方法,注冊和注銷。

  Service:在服務(wù)端,我們首先需要實(shí)現(xiàn)注冊和注銷兩個(gè)方法,然后在實(shí)現(xiàn)一個(gè)新的方法用于不斷生成新書,并在新書到來時(shí)遠(yuǎn)程調(diào)用注冊在案的所有l(wèi)istener的onNewBookArrived方法。

  Client:首先客戶端需要注冊IOnNewBookArrivedListener到遠(yuǎn)程服務(wù)器,并且在Activity退出時(shí)解除注冊;另外,當(dāng)有新書時(shí),服務(wù)端會(huì)在有新書時(shí)回調(diào)客戶單的IOnNewBookArrivedListener方法,當(dāng)然這個(gè)方法是在客戶端的Binder線程池中進(jìn)行的,因此,為了進(jìn)行UI操作,我們需要使用一個(gè)Handler來將其切換到主線程中執(zhí)行。

  具體代碼:

  實(shí)體類:

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

package com.pignet.library.aidl;import android.os.Parcel;import android.os.Parcelable;/**
 * Created by DB on 2017/7/1. */public class Book implements Parcelable{    public int bookId;    public String bookName;    public Book(int bookId, String bookName) {        this.bookId = bookId;        this.bookName = bookName;
    }    public int getBookId() {        return bookId;
    }    public void setBookId(int bookId) {        this.bookId = bookId;
    }    public String getBookName() {        return bookName;
    }    public void setBookName(String bookName) {        this.bookName = bookName;
    }

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

    @Override    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.bookId);
        dest.writeString(this.bookName);
    }    public Book() {
    }    protected Book(Parcel in) {        this.bookId = in.readInt();        this.bookName = in.readString();
    }    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override        public Book createFromParcel(Parcel source) {            return new Book(source);
        }

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

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

  AIDL:

  

// Book.aidlpackage com.pignet.library.aidl;// Declare any non-default types here with import statementsparcelable Book;

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

// IBookManager.aidlpackage com.pignet.library.aidl;// Declare any non-default types here with import statementsimport com.pignet.library.aidl.Book;import com.pignet.library.aidl.IOnNewBookArrivedListener;interface IBookManager{
    List<Book> getBookList();    void addBook(in Book book);    void registerListener(IOnNewBookArrivedListener listener);    void unregisterListener(IOnNewBookArrivedListener listener);

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

// IOnNewBookArrivedListener.aidlpackage com.pignet.library.aidl;import com.pignet.library.aidl.Book;interface IOnNewBookArrivedListener {    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.     */

    void onNewBookArrived(in Book newBook);
}

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 

  Service端:

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

package com.pignet.library;import android.app.Service;import android.content.Intent;import android.content.pm.PackageManager;import android.os.Binder;import android.os.IBinder;import android.os.RemoteCallbackList;import android.os.RemoteException;import android.os.SystemClock;import android.support.annotation.Nullable;import android.util.Log;import com.pignet.library.aidl.Book;import com.pignet.library.aidl.IBookManager;import com.pignet.library.aidl.IOnNewBookArrivedListener;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.atomic.AtomicBoolean;/**
 * Created by DB on 2017/7/2. */public class BookManagerService extends Service {    private  static  final String TAG ="BookManagerService";    //原子類,Service是否銷毀
    private AtomicBoolean mIsServiceDestroyed = new AtomicBoolean(false);    //并發(fā)容器BookList
    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();    //并發(fā)容器 Listeners
    private RemoteCallbackList<IOnNewBookArrivedListener> mListeners = new RemoteCallbackList<>();    //實(shí)例化Binder,實(shí)例化AIDL中的Stub內(nèi)部類,
    private Binder mBinder = new IBookManager.Stub(){

        @Override        public List<Book> getBookList() throws RemoteException {
            SystemClock.sleep(5000);            return mBookList;
        }

        @Override        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);

        }        /**
         * 注冊監(jiān)聽器,監(jiān)聽圖書進(jìn)庫
         * @param listener
         * @throws RemoteException         */
        @Override        public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
            mListeners.register(listener);
        }        /**
         * 解除注冊監(jiān)聽器,取消監(jiān)聽圖書進(jìn)庫
         * @param listener
         * @throws RemoteException         */
        @Override        public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
            mListeners.unregister(listener);

        }

    };    //初始化圖書館中的圖書    @Override    public void onCreate() {        super.onCreate();
        mBookList.add(new Book(1,"Android"));
        mBookList.add(new Book(2,"Java"));        //啟動(dòng)后臺(tái)線程
        new Thread(new ServiceWorker()).start();

    }

    @Nullable
    @Override    public IBinder onBind(Intent intent) {        int check = checkCallingOrSelfPermission("com.pignet.library.permission.ACCESS_BOOK_SERVICE");        if(check == PackageManager.PERMISSION_DENIED){
            Log.d(TAG, "failed ");            return null;
        }        return mBinder;
    }    //后臺(tái)線程,負(fù)責(zé)不斷產(chǎn)生新書入庫
    private class ServiceWorker implements Runnable{

        @Override        public void run() {            while(!mIsServiceDestroyed.get()){                try{
                    Thread.sleep(5000);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }               int bookId = mBookList.size()+1;
                Book newBook = new Book(bookId,"new Book#"+bookId);
                Log.d(TAG, "run: "+bookId);                try {
                    onNewBookArrived(newBook);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }        private void onNewBookArrived(Book newBook) throws RemoteException {
            mBookList.add(newBook);            final int N= mListeners.beginBroadcast();            for(int i=0;i<N;i++){
                IOnNewBookArrivedListener listener = mListeners.getBroadcastItem(i);                if(listener!=null){                    try{
                        listener.onNewBookArrived(newBook);
                    }catch (RemoteException e){
                        e.printStackTrace();
                    }
                }
            }
            mListeners.finishBroadcast();
        }


    }
}

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

client:

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動(dòng)開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

package com.pignet.library;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import com.pignet.library.aidl.Book;import com.pignet.library.aidl.IBookManager;import com.pignet.library.aidl.IOnNewBookArrivedListener;import org.w3c.dom.Text;import java.util.List;public class BookManagerActivity extends AppCompatActivity {
    Button btnGetBookList;
    Button btnAddBook;
    TextView tvBookList;
    EditText etBook;
    IBookManager bookManager;    private  static StringBuilder stringBuilder;    private static final  String TAG="BookManagerActivity";    private static final  int MESSAGE_NEW_BOOK_ARRIVED=1;    private IBookManager mRemoteBookManager;    //建立連接

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnGetBookList = (Button) findViewById(R.id.btn_getBookList);
        btnAddBook = (Button) findViewById(R.id.btn_addBook);
        tvBookList = (TextView) findViewById(R.id.tv_bookList);
        etBook = (EditText) findViewById(R.id.et_addBook);        //綁定Service
        Intent intent =new Intent(BookManagerActivity.this,BookManagerService.class);
        
        bindService(intent,mConnection, Context.BIND_AUTO_CREATE);        //增加圖書
        btnAddBook.setOnClickListener(new View.OnClickListener() {
            @Override            public void onClick(View v) {                if(etBook.getText().toString().length()>1){
                    Log.d(TAG, "add Book");
                    Book book = null;                    try {
                        book = new

http://www.cnblogs.com/hustzhb/p/7119762.html