Android Binder學(xué)習(xí)筆記(一)

本文參考《Android開發(fā)藝術(shù)探索》,建議照著代碼看文章。GitHub-完整代碼鏈接

AIDL 支持下列數(shù)據(jù)類型:

  1. Java 編程語言中的所有原語類型:byte、short 、int、long、float、double、char、boolean。
  2. List:只支持ArrayList,List的每個元素也需要是AIDL支持的數(shù)據(jù)類型。
  3. Map: 值支持HashMap,Map的key和value也需要是AIDL支持的數(shù)據(jù)類型。
  4. Parcelable:實現(xiàn)了Parcelable接口的對象。
  5. AIDL:所有的AIDL接口本身也可以在AIDL文件中使用。

Binder的跨進(jìn)程工作機制

Binder工作機制.png

通過Binder實現(xiàn)跨進(jìn)程通信,提供服務(wù)的進(jìn)程被稱為服務(wù)端,請求服務(wù)的進(jìn)程是客戶端。

服務(wù)端:服務(wù)端首先要創(chuàng)建一個AIDL文件,將暴露給客戶端的方法在這個AIDL文件中聲明,接著創(chuàng)建一個Binder類繼承AIDL接口中的Stub類,并實現(xiàn)Stub中的抽象方法。然后創(chuàng)建一個Service用來監(jiān)聽客戶端的連接請求,在Service的onBind方法中返回這個Binder類的對象。

客戶端:客戶端首先要綁定服務(wù)端的Service,綁定成功后,將服務(wù)端返回的Binder對象轉(zhuǎn)成AIDL接口所屬的類型,接著就可以調(diào)用AIDL中的方法了。

不知道上面的文字在說什么,沒關(guān)系,下面看個例子。這個例子實現(xiàn)跨進(jìn)程獲取書籍列表和添加書籍的功能。

獲取書籍列表調(diào)用過程如下圖所示,可以先大致瀏覽一下。

Android Binder學(xué)習(xí)筆記(一).jpg

我們先從服務(wù)端開始

定義一個Book類實現(xiàn)Parcelable接口,實現(xiàn)Parcelable接口是為了能夠?qū)崿F(xiàn)跨進(jìn)程傳輸。

public class Book implements Parcelable {

    private int bookId;
    private String bookName;

    public Book() {
    }

    public Book(int bookId, String bookName) {
        this.bookId = bookId;
        this.bookName = bookName;
    }

    protected Book(Parcel in) {
        bookId = in.readInt();
        bookName = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(bookId);
        dest.writeString(bookName);
    }

    /**
     * 參數(shù)是一個Parcel,用它來存儲與傳輸數(shù)據(jù)
     * @param dest
     */
    public void readFromParcel(Parcel dest) {
        //注意,此處的讀值順序應(yīng)當(dāng)是和writeToParcel()方法中一致的
        bookId = dest.readInt();
        bookName = dest.readString();
    }

    @Override
    public String toString() {
        return "{bookId:" + bookId + ",bookName:" + bookName + "}";
    }
    //省略getter/setter
   
}

如果一個AIDL文件中用到了自定義的Parcelable對象類,那么必須新建一個和它同名的AIDL文件,并在其中聲明它為parcelable類型。

為Book類聲明對應(yīng)的AIDL文件Book.aidl

// Book.aidl
package com.hm.aidlserver;

parcelable Book;

定義一個AIDL文件IBookManager.aidl,在其中聲明獲取書籍列表和添加書籍的方法。

// IBookManager.aidl
package com.hm.aidlserver;
//顯式引入Book類
import com.hm.aidlserver.Book;

interface IBookManager {

   List<Book>getBookList();
   void addBook(in Book book);
}

注意:自定義的Parcelable對象類和AIDL文件必須要顯式的import進(jìn)來,不管它們是否和當(dāng)前的AIDL文件位于同一個包內(nèi)。

聲明完了AIDL文件,重新build項目即可在build目錄下看到系統(tǒng)為我們生成的用于進(jìn)程間通信的類

../build/generated/source/aidl/debug/com/hm/aidlserver/IBookManager.java

我將該類調(diào)整了一下格式方便查看

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /Users/dumingwei/AndroidStudioProjects/AIDLDemo/aidlserver/src/main/aidl/com/hm/aidlserver/IBookManager.aidl
 */
package com.hm.aidlserver;

public interface IBookManager extends android.os.IInterface {

    //抽象方法,獲取書籍列表
    public java.util.List<com.hm.aidlserver.Book> getBookList() throws android.os.RemoteException;

    //抽象方法,添加書籍
    public void addBook(com.hm.aidlserver.Book book) throws android.os.RemoteException;

    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.hm.aidlserver.IBookManager {

        private static final java.lang.String DESCRIPTOR = "com.hm.aidlserver.IBookManager";

        //標(biāo)志獲取書籍列表的方法
        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        //標(biāo)志添加書籍的方法
        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.hm.aidlserver.IBookManager interface,
         * generating a proxy if needed.
         */
        public static com.hm.aidlserver.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            //客戶端調(diào)用queryLocalInterface(String descriptor)方法,返回的肯定是null
            //服務(wù)端調(diào)用queryLocalInterface(String descriptor)方法,返回的不是null
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.hm.aidlserver.IBookManager))) {
                return ((com.hm.aidlserver.IBookManager) iin);
            }
            //客戶端最終返回的是一個代理對象
            return new com.hm.aidlserver.IBookManager.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_getBookList: {
                    data.enforceInterface(descriptor);
                    java.util.List<com.hm.aidlserver.Book> _result = this.getBookList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBook: {
                    data.enforceInterface(descriptor);
                    com.hm.aidlserver.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.hm.aidlserver.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
                
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        //這個類是給客戶端用的
        private static class Proxy implements com.hm.aidlserver.IBookManager {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public java.util.List<com.hm.aidlserver.Book> getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.hm.aidlserver.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.hm.aidlserver.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addBook(com.hm.aidlserver.Book book) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((book != null)) {
                        _data.writeInt(1);
                        book.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }
    }
}

各個類的職責(zé)

  • IBinder :IBinder 是一個接口,代表了一種跨進(jìn)程通信的能力。只要實現(xiàn)了這個接口,這個對象就能跨進(jìn)程傳輸。IBinder的直接子類是BinderBinderProxy。這兩個類都繼承自 IBinder, 因而都具有跨進(jìn)程傳輸?shù)哪芰?;Binder代表的是服務(wù)端Binder本地對象。BinderProxy類,它是服務(wù)端的Binder對象的代理對象;實際上,在跨越進(jìn)程的時候,Binder驅(qū)動會自動完成這兩個對象的轉(zhuǎn)換,客戶端真正拿到的是服務(wù)端的Binder對象的代理對象(即一個BinderProxy類型的對象)。

  • IInterface :IInterface 代表的就是 Server 進(jìn)程對象具備什么樣的能力(能提供哪些方法,其實對應(yīng)的就是 AIDL 文件中定義的接口)。

  • Stub :編譯工具會給我們定義的AIDL 文件生成一個名為 Stub 的靜態(tài)內(nèi)部類;這個類繼承了Binder, 說明它是一個Binder本地對象,它實現(xiàn)了IInterface接口,表明它具有 Server承諾給Client 的能力。Stub是一個抽象類,具體的IInterface的相關(guān)實現(xiàn)需要開發(fā)者自己實現(xiàn)。

  • Stub.Proxy:服務(wù)端Binder對象(這個Binder對象就是我們在Service中定義的具體的Binder對象,該對象可以跨進(jìn)程通信, 并且是實現(xiàn)了IBookManager接口)的代理類,客戶端是通過BinderProxy對象獲取到服務(wù)端Binder對象的代理類Proxy,然后通過這個代理類調(diào)用服務(wù)端的方法。

自動生成的IBookManager.java中,聲明了我們在AIDL文件中定義的方法

//抽象方法,獲取書籍列表
public java.util.List<com.hm.aidlserver.Book> getBookList() throws android.os.RemoteException;

//抽象方法添加書籍
public void addBook(com.hm.aidlserver.Book book) throws android.os.RemoteException;

IBookManager.java文件中,還為我們生成了一個抽象的內(nèi)部類Stub。

public static abstract class Stub extends android.os.Binder implements com.hm.aidlserver.IBookManager {

    //用來標(biāo)志Binder對象的名字
    private static final java.lang.String DESCRIPTOR = "com.hm.aidlserver.IBookManager";

    //標(biāo)志獲取書籍列表的方法
    static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    //標(biāo)志添加書籍的方法
    static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        
    //... 
        
        
}

注意:Stub抽象類繼承了android.os.Binder類并實現(xiàn)了com.hm.aidlserver.IBookManager接口,但是并沒有實現(xiàn)com.hm.aidlserver.IBookManager接口中的抽象方法。我們最后在服務(wù)端返回的Binder對象要繼承Stub類并實現(xiàn)com.hm.aidlserver.IBookManager接口中的抽象方法。

在Stub類中,還為我們生成了一個私有的靜態(tài)內(nèi)部類Proxy,客戶端就是使用這個代理類來實現(xiàn)和服務(wù)端進(jìn)行通信的,后面再細(xì)說。

private static class Proxy implements com.hm.aidlserver.IBookManager {
    //...
}

服務(wù)端Service的實現(xiàn)

/**
 * 服務(wù)端的Service
 */
public class BookManagerService extends Service {

    private static final String TAG = BookManagerService.class.getSimpleName();

    //使用CopyOnWriteArrayList,因為可能會有多個客戶端同時操作書籍列表造成線程同步的問題
    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
    
    public BookManagerService() {
    }
    
    /**
     * 實現(xiàn)IBookManager接口中的方法
     */
    private Binder mBinder = new IBookManager.Stub() {

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

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


    @Override
    public void onCreate() {
        super.onCreate();
        //創(chuàng)建Service的時候先主動添加兩個書籍
        mBookList.add(new Book(1, "Android"));
        mBookList.add(new Book(2, "ios"));
    }

    @Override
    public IBinder onBind(Intent intent) {
        //返回binder對象
        return mBinder;
    }
}

在BookManagerService中我們創(chuàng)建了一個Binder對象mBinder,mBinder實現(xiàn)IBookManager.aidl中定義的方法。然后我們在onBind方法中返回mBinder對象即可。

我們的書籍列表類型使用了CopyOnWriteArrayList,因為可能會有多個客戶端同時操作書籍列表造成線程同步的問題。

注意:不要忘了在AndroidManifest.xml文件中注冊BookManagerService

<service
      android:name=".BookManagerService"
      android:enabled="true"
      android:exported="true">
</service>

到這,一個簡單的服務(wù)端就實現(xiàn)了,接下來我們實現(xiàn)客戶端。

客戶端的實現(xiàn)

首先把在服務(wù)端定義的類和AIDL文件都拷貝到客戶端(具體的項目結(jié)構(gòu)可以下載源碼看一看),重新build項目即可在build目錄下看到系統(tǒng)為我們生成的用于進(jìn)程間通信的類。

綁定遠(yuǎn)程服務(wù)

    //定義IBookManager對象
    private IBookManager bookManager;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //注釋1處,注意這個的service對象是一個BinderProxy對象
            Log.e(TAG, "onServiceConnected:" + service.getClass().getCanonicalName());
            //注釋2處,獲取bookManager對象,注意這個傳入的service對象是一個BinderProxy對象
            bookManager = IBookManager.Stub.asInterface(service);
            Log.e(TAG, "onServiceConnected:" + bookManager.getClass().getCanonicalName());

            try {
                getBookList();
                bookManager.registerListener(mOnNewBookArriveListener);
            } catch (RemoteException e) {
                e.printStackTrace();
                Log.e(TAG, "onServiceConnected: error" + e.getMessage());
            }
        }
        //...
    };

綁定服務(wù)

private void bind() {
    binded = true;
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.hm.aidlserver", "com.hm.aidlserver.BookManagerService"));
    bindService(intent, connection, Context.BIND_AUTO_CREATE);
}

綁定遠(yuǎn)程服務(wù)以后,我們就可以調(diào)用服務(wù)端的方法了

獲取書籍列表

public void getBookList() {
    if (bookManager != null) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //獲取書籍列表
                    bookList = bookManager.getBookList();
                    Log.e(TAG, "query book list,list type:" + bookList.getClass().getCanonicalName());
                    Log.e(TAG, "query book list,list:" + bookList.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    } 
}

添加書籍

public void addBook() {
    if (bookManager != null) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //添加書籍
                    bookManager.addBook(new Book(bookId, "Android 進(jìn)階" + bookId));
                    bookId++;
                    //添加完畢后,重新獲取一下書籍列表
                    bookList = bookManager.getBookList();
                    Log.e(TAG, "query book list,list type:" + bookList.getClass().getCanonicalName());
                    Log.e(TAG, "query book list,list:" + bookList.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    } 
}

注意:當(dāng)客戶端調(diào)用服務(wù)端的方法時,如果是耗時方法的話,我們不能在主線程調(diào)用,否則可能會導(dǎo)致ANR,所以我們開啟新線程來調(diào)用服務(wù)端的方法。

現(xiàn)在我們已經(jīng)可以愉快的調(diào)用服務(wù)端的方法了,即實現(xiàn)了進(jìn)程間通信。

接下來我們研究一下其中的一些細(xì)節(jié)。先從客戶端我們定義的IBookManager對象和ServiceConnection對象。

深入細(xì)節(jié)

    //定義IBookManager對象
    private IBookManager bookManager;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //注釋1處,
            Log.e(TAG, "onServiceConnected:" + service.getClass().getCanonicalName());
            //注釋2處,獲取bookManager對象,注意這個傳入的service對象是一個BinderProxy對象
            bookManager = IBookManager.Stub.asInterface(service);
            Log.e(TAG, "onServiceConnected:" + bookManager.getClass().getCanonicalName());

            try {
                getBookList();
                bookManager.registerListener(mOnNewBookArriveListener);
            } catch (RemoteException e) {
                e.printStackTrace();
                Log.e(TAG, "onServiceConnected: error" + e.getMessage());
            }
        }
        //...
    };

我們打印了service的類名bookManager的類型,如下所示。

onServiceConnected:android.os.BinderProxy
onServiceConnected:com.hm.aidlserver.IBookManager.Stub.Proxy

說明當(dāng)綁定到服務(wù)端的Service的時候,服務(wù)端返回的service對象是一個BinderProxy類型的對象而我們在客戶端定義的bookManager最終指向了一個IBookManager.Stub.Proxy類型的對象。這點要注意,后面還要再說。

在注釋2處,調(diào)用了IBookManager.Stub的asInterface(android.os.IBinder obj)方法。

public static com.hm.aidlserver.IBookManager asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
        return null;
    }
    //注釋1處,客戶端調(diào)用IBinder類的queryLocalInterface(String descriptor)方法,返回的是null
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.hm.aidlserver.IBookManager))) {
        return ((com.hm.aidlserver.IBookManager) iin);
    }
    //注釋2處,客戶端最終返回的是一個代理對象
    return new com.hm.aidlserver.IBookManager.Stub.Proxy(obj);
}

注意:asInterface方法的注釋1處,客戶端調(diào)用IBinder類的queryLocalInterface(String descriptor)方法,返回的是null。為什么呢?IBinder接口有兩個實現(xiàn)類,一個是Binder,一個是BinderProxy。我們在onServiceConnected(ComponentName name, IBinder service)方法中得到的service是一個BinderProxy類型的對象。

BinderProxy的queryLocalInterface(String descriptor)方法直接返回的是null。

public IInterface queryLocalInterface(String descriptor) {
    return null;
}

asInterface方法的注釋2處,客戶端最終返回的是一個代理對象。也就是說我們客戶端的bookManager對象是一個IBookManager.Stub.Proxy對象。我們獲取書籍列表和添加書籍都是調(diào)用IBookManager.Stub.Proxy類中的方法,接下來看一下。

    private static class Proxy implements com.hm.aidlserver.IBookManager {
        //注釋1處
        private android.os.IBinder mRemote;

        Proxy(android.os.IBinder remote) {
            mRemote = remote;
        }

        @Override
        public android.os.IBinder asBinder() {
            return mRemote;
        }

        public java.lang.String getInterfaceDescriptor() {
            return DESCRIPTOR;
        }

        @Override
        public java.util.List<com.hm.aidlserver.Book> getBookList() throws android.os.RemoteException {
            //構(gòu)建發(fā)送到服務(wù)端的數(shù)據(jù)
            android.os.Parcel _data = android.os.Parcel.obtain();
           //構(gòu)建服務(wù)端返回的數(shù)據(jù)
            android.os.Parcel _reply = android.os.Parcel.obtain();
            //要獲取的書籍列表
            java.util.List<com.hm.aidlserver.Book> _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                //注釋1處,標(biāo)記調(diào)用服務(wù)端的getBookList方法
                mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                _reply.readException();
               //獲取查詢到的書籍列表
                _result = _reply.createTypedArrayList(com.hm.aidlserver.Book.CREATOR);
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            //返回結(jié)果
            return _result;
        }

        @Override
        public void addBook(com.hm.aidlserver.Book book) throws android.os.RemoteException {
            //構(gòu)建傳到服務(wù)端的數(shù)據(jù)
            android.os.Parcel _data = android.os.Parcel.obtain();
            //構(gòu)建服務(wù)端返回的數(shù)據(jù),添加數(shù)據(jù)其實我們是沒有要求返回數(shù)據(jù)的
            android.os.Parcel _reply = android.os.Parcel.obtain();
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                if ((book != null)) {
                    _data.writeInt(1);
                    //將book對象寫入到data中
                    book.writeToParcel(_data, 0);
                } else {
                    _data.writeInt(0);
                }
                //注釋1處,標(biāo)記調(diào)用服務(wù)端的addBook方法
                mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }

    }

注釋1處,Proxy類中的mRemote就是一個BinderProxy對象。

BinderProxy的transact(int code, Parcel data, Parcel reply, int flags)方法。

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    //檢查數(shù)據(jù)大小,不能大于800K
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
    //...
    try {
        //注釋1處,
        return transactNative(code, data, reply, flags);
    } finally {
        //...
    }
}

注釋1處,調(diào)用了BinderProxy的transactNative(int code, Parcel data, Parcel reply, int flags)方法,這是一個本地方法,最終會調(diào)用服務(wù)端Binder對象的transact方法。這個Binder對象就是我們在服務(wù)端Service中返回的對象(IBookManager.Stub類型)。

     /**
     * 實現(xiàn)IBookManager接口中的方法
     */
    private Binder mBinder = new IBookManager.Stub() {

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

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

我們看一下IBookManager.Stub繼承了Binder類,并沒有重寫transact方法

Binder類transact方法

public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
            int flags) throws RemoteException {
    
    if (data != null) {
        //讀取客戶端傳遞的數(shù)據(jù)
        data.setDataPosition(0);
    }
    //注釋1處,調(diào)用onTransact方法
    boolean r = onTransact(code, data, reply, flags);
    if (reply != null) {
        //設(shè)置返回給客戶端的數(shù)據(jù)
        reply.setDataPosition(0);
    }
    return r;
}

注釋1處,調(diào)用了onTransact方法,IBookManager.Stub的重寫了onTransact方法,我們看一下。

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) 
        throws android.os.RemoteException {
    java.lang.String descriptor = DESCRIPTOR;
    switch (code) {
        case INTERFACE_TRANSACTION: {
            reply.writeString(descriptor);
            return true;
        }
        case TRANSACTION_getBookList: {
            data.enforceInterface(descriptor);
            java.util.List<com.hm.aidlserver.Book> _result = this.getBookList();
            reply.writeNoException();
            //返回數(shù)據(jù)
            reply.writeTypedList(_result);
            //返回true表示調(diào)用成功
            return true;
        }
        case TRANSACTION_addBook: {
            data.enforceInterface(descriptor);
            com.hm.aidlserver.Book _arg0;
            if ((0 != data.readInt())) {
                _arg0 = com.hm.aidlserver.Book.CREATOR.createFromParcel(data);
            } else {
                _arg0 = null;
            }
            //添加書籍
            this.addBook(_arg0);
            reply.writeNoException();
            return true;
        }
        default: {
            return super.onTransact(code, data, reply, flags);
        }
    }
}

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容