AIDL基本使用

AIDL的概念

AIDL:全稱(chēng)是Android Interface Definition Language(Android接口定義語(yǔ)言)条霜。它主要用在Android進(jìn)程間通信中,Android中有一種進(jìn)程間通信方式是Binder撞反,AIDL就是幫我們自動(dòng)生成了Binder相關(guān)代碼鸦列,不需要我們自己去手動(dòng)書(shū)寫(xiě)復(fù)雜的Binder類(lèi)租冠,我們只需要在AIDL接口文件中書(shū)寫(xiě)自己的調(diào)用遠(yuǎn)程服務(wù)的業(yè)務(wù)方法就可以了,大大簡(jiǎn)化了開(kāi)發(fā)過(guò)程敛熬。

AIDL支持的數(shù)據(jù)類(lèi)型

  • 八種基本數(shù)據(jù)類(lèi)型:byte肺稀、char、short应民、int话原、long猎贴、float杆融、double拙徽、boolean
  • String鞍匾,CharSequence
  • 實(shí)現(xiàn)了Parcelable接口的數(shù)據(jù)類(lèi)型
  • List 類(lèi)型。List承載的數(shù)據(jù)必須是AIDL支持的類(lèi)型产艾,或者是其它聲明的AIDL對(duì)象
  • Map類(lèi)型旷坦。Map承載的數(shù)據(jù)必須是AIDL支持的類(lèi)型白热,或者是其它聲明的AIDL對(duì)象

AIDL使用步驟

例子源自《Android開(kāi)發(fā)藝術(shù)探索》庸诱,點(diǎn)擊獲取Demo

Server端

1.首先創(chuàng)建一個(gè)Book類(lèi)和兩個(gè)aidl文件

class Book : Parcelable {
    var bookId: Int
    var bookName: String?

    constructor(bookId: Int, bookName: String?) {
        this.bookId = bookId
        this.bookName = bookName
    }

    override fun describeContents(): Int {
        return 0
    }

    override fun writeToParcel(dest: Parcel, flags: Int) {
        dest.writeInt(bookId)
        dest.writeString(bookName)
    }

    constructor(source: Parcel) {
        bookId = source.readInt()
        bookName = source.readString()
    }

    override fun toString(): String {
        return "Book{" +
                "bookId=" + bookId +
                ", bookName='" + bookName + '\'' +
                '}'
    }


    companion object CREATOR : Parcelable.Creator<Book> {
        override fun createFromParcel(parcel: Parcel): Book {
            return Book(parcel)
        }

        override fun newArray(size: Int): Array<Book?> {
            return arrayOfNulls(size)
        }
    }
}

Book.aidl文件

// Book.aidl
package com.example.helloaidl;

parcelable Book;

IBookManager.aidl文件

// IBookManager.aidl
package com.example.helloaidl;
import com.example.helloaidl.Book;

interface IBookManager {
    // 獲取圖書(shū)列表
    List<Book> getBookList();

    //添加圖書(shū)
    void addBook(in Book book);
}

2.rebuild項(xiàng)目捻浦,會(huì)自動(dòng)生成一個(gè) IBookManager的java類(lèi), 里面書(shū)寫(xiě)了Binder相關(guān)代碼桥爽。

public interface IBookManager extends android.os.IInterface
{
  /** Default implementation for IBookManager. */
  public static class Default implements com.example.helloaidl.IBookManager
  {
    // 獲取圖書(shū)列表

    @Override public java.util.List<com.example.helloaidl.Book> getBookList() throws android.os.RemoteException
    {
      return null;
    }
    //添加圖書(shū)

    @Override public void addBook(com.example.helloaidl.Book book) throws android.os.RemoteException
    {
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.example.helloaidl.IBookManager
  {
    private static final java.lang.String DESCRIPTOR = "com.example.helloaidl.IBookManager";
    
    /**
   * Stub構(gòu)造函數(shù)
   */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * 將IBinder 轉(zhuǎn)換為BookManagerService interface
     */
    public static com.example.helloaidl.IBookManager asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.example.helloaidl.IBookManager))) {
        return ((com.example.helloaidl.IBookManager)iin);
      }
      return new com.example.helloaidl.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.example.helloaidl.Book> _result = this.getBookList();
          reply.writeNoException();
          reply.writeTypedList(_result);
          return true;
        }
        case TRANSACTION_addBook:
        {
          data.enforceInterface(descriptor);
          com.example.helloaidl.Book _arg0;
          if ((0!=data.readInt())) {
            _arg0 = com.example.helloaidl.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.example.helloaidl.IBookManager
    {
      private android.os.IBinder mRemote;
      
      /**
      * Proxy構(gòu)造函數(shù)
      */
      Proxy(android.os.IBinder remote)
      {
        mRemote = remote;
      }
      @Override public android.os.IBinder asBinder()
      {
        return mRemote;
      }
      public java.lang.String getInterfaceDescriptor()
      {
        return DESCRIPTOR;
      }
      //獲取圖書(shū)列表

      @Override public java.util.List<com.example.helloaidl.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.example.helloaidl.Book> _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          boolean _status = mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().getBookList();
          }
          _reply.readException();
          _result = _reply.createTypedArrayList(com.example.helloaidl.Book.CREATOR);
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      
      //添加圖書(shū)
      @Override public void addBook(com.example.helloaidl.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);
          }
          boolean _status = mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().addBook(book);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      public static com.example.helloaidl.IBookManager sDefaultImpl;
    }
    static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    public static boolean setDefaultImpl(com.example.helloaidl.IBookManager impl) {
      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.example.helloaidl.IBookManager getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  // 鑾峰彇鍥句功鍒楄〃

  public java.util.List<com.example.helloaidl.Book> getBookList() throws android.os.RemoteException;
  //娣誨姞鍥句功

  public void addBook(com.example.helloaidl.Book book) throws android.os.RemoteException;
}

3.編寫(xiě)遠(yuǎn)程服務(wù)代碼 BookManagerService朱灿,為了演示進(jìn)程間的通信機(jī)制,故需要將Service與Activity處于不同的進(jìn)程钠四,需要在AndroidManifest.xml中盗扒,把service配置成android:process=":remote"

class BookManagerService : Service() {
    private val TAG = BookManagerService::class.java.simpleName

    //使用CopyOnWriteArrayList來(lái)支持并發(fā)讀寫(xiě)
    private val mBookList = CopyOnWriteArrayList<Book>()

    override fun onBind(intent: Intent): IBinder? {
        return mBinder
    }


    private val mBinder = object : IBookManager.Stub() {
        override fun addBook(book: Book) {
            mBookList.add(book)
        }

        override fun getBookList(): List<Book> {
            return mBookList
        }

    }

}
<service
        android:name="com.example.helloaidl.BookManagerService
        android:enabled="true"
        android:exported="true"
        android:process=":remote">
</service>
客戶(hù)端

創(chuàng)建Activity,在manifest中注冊(cè),完整代碼如下:

class BookManagerActivity : AppCompatActivity() {

    private val TAG = BookManagerActivity::class.java.simpleName

    private var mRemoteBookManager: IBookManager? = null
    private var boookId = 1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        bindService()
        initListener()
    }

    //綁定遠(yuǎn)程服務(wù)端
    private fun bindService() {
        val intent = Intent(this, BookManagerService::class.java)
        intent.setPackage(packageName)
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
    }

    //注冊(cè)按鈕監(jiān)聽(tīng)侣灶,調(diào)用遠(yuǎn)程耗時(shí)方法需要開(kāi)啟線程
    private fun initListener() {
        btnGetBookList.setOnClickListener {
            Toast.makeText(this, "GetBookList", Toast.LENGTH_SHORT).show()
            Thread {
                try {
                    mRemoteBookManager?.let { mRemoteBookManager ->
                        val list = mRemoteBookManager.bookList
                        Log.i(TAG, "query book list: $list")
                    }
                } catch (e: RemoteException) {
                    e.printStackTrace()
                }
            }.start()
        }
        btnAddBook.setOnClickListener {
            Toast.makeText(this, "AddBook", Toast.LENGTH_SHORT).show()
            Thread {
                try {
                    mRemoteBookManager?.apply {
                        val newBook = Book( boookId++, "Book$boookId")
                        Log.i(TAG, "add book: $newBook")
                        addBook(newBook)
                    }
                } catch (e: RemoteException) {
                    e.printStackTrace()
                }
            }.start()
        }
    }

    override fun onDestroy() {
        unBindService()
        super.onDestroy()
    }

    private fun unBindService() {
        unbindService(mConnection)
    }

    //服務(wù)端連接狀態(tài)回調(diào)
    private var mConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.e(TAG, "onServiceConnected: $mRemoteBookManager")
            //將服務(wù)端返回的Binder對(duì)象轉(zhuǎn)換為aidl對(duì)象
            mRemoteBookManager = IBookManager.Stub.asInterface(service)
            Log.e(TAG, "onServiceConnected: $mRemoteBookManager")
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Log.i(TAG, "onServiceDisconnected ThreadName: ${Thread.currentThread().name}")
            mRemoteBookManager = null
        }
    }

}

點(diǎn)擊獲取Demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末甸祭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子褥影,更是在濱河造成了極大的恐慌池户,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伪阶,死亡現(xiàn)場(chǎng)離奇詭異煞檩,居然都是意外死亡处嫌,警方通過(guò)查閱死者的電腦和手機(jī)栅贴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)熏迹,“玉大人檐薯,你說(shuō)我怎么就攤上這事∽担” “怎么了坛缕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)捆昏。 經(jīng)常有香客問(wèn)我赚楚,道長(zhǎng),這世上最難降的妖魔是什么骗卜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任宠页,我火速辦了婚禮,結(jié)果婚禮上寇仓,老公的妹妹穿的比我還像新娘举户。我一直安慰自己,他們只是感情好遍烦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布俭嘁。 她就那樣靜靜地躺著,像睡著了一般服猪。 火紅的嫁衣襯著肌膚如雪供填。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天罢猪,我揣著相機(jī)與錄音近她,去河邊找鬼。 笑死坡脐,一個(gè)胖子當(dāng)著我的面吹牛泄私,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼晌端,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼捅暴!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起咧纠,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蓬痒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后漆羔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體梧奢,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年演痒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亲轨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸟顺,死狀恐怖惦蚊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讯嫂,我是刑警寧澤蹦锋,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站欧芽,受9級(jí)特大地震影響莉掂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜千扔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一憎妙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昏鹃,春花似錦尚氛、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至载迄,卻和暖如春讯柔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背护昧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工魂迄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惋耙。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓捣炬,卻偏偏與公主長(zhǎng)得像熊昌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子湿酸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容