美文网首页
AIDL基本使用

AIDL基本使用

作者: dashixun | 来源:发表于2019-12-25 17:24 被阅读0次

    AIDL的概念

    AIDL:全称是Android Interface Definition Language(Android接口定义语言)。它主要用在Android进程间通信中,Android中有一种进程间通信方式是Binder,AIDL就是帮我们自动生成了Binder相关代码,不需要我们自己去手动书写复杂的Binder类,我们只需要在AIDL接口文件中书写自己的调用远程服务的业务方法就可以了,大大简化了开发过程。

    AIDL支持的数据类型

    • 八种基本数据类型:byte、char、short、int、long、float、double、boolean
    • String,CharSequence
    • 实现了Parcelable接口的数据类型
    • List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
    • Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

    AIDL使用步骤

    例子源自《Android开发艺术探索》,点击获取Demo

    Server端

    1.首先创建一个Book类和两个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 {
        // 获取图书列表
        List<Book> getBookList();
    
        //添加图书
        void addBook(in Book book);
    }
    
    

    2.rebuild项目,会自动生成一个 IBookManager的java类, 里面书写了Binder相关代码。

    public interface IBookManager extends android.os.IInterface
    {
      /** Default implementation for IBookManager. */
      public static class Default implements com.example.helloaidl.IBookManager
      {
        // 获取图书列表
    
        @Override public java.util.List<com.example.helloaidl.Book> getBookList() throws android.os.RemoteException
        {
          return null;
        }
        //添加图书
    
        @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构造函数
       */
        public Stub()
        {
          this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * 将IBinder 转换为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构造函数
          */
          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.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;
          }
          
          //添加图书
          @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.编写远程服务代码 BookManagerService,为了演示进程间的通信机制,故需要将Service与Activity处于不同的进程,需要在AndroidManifest.xml中,把service配置成android:process=":remote"

    class BookManagerService : Service() {
        private val TAG = BookManagerService::class.java.simpleName
    
        //使用CopyOnWriteArrayList来支持并发读写
        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>
    
    客户端

    创建Activity,在manifest中注册,完整代码如下:

    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()
        }
    
        //绑定远程服务端
        private fun bindService() {
            val intent = Intent(this, BookManagerService::class.java)
            intent.setPackage(packageName)
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
        }
    
        //注册按钮监听,调用远程耗时方法需要开启线程
        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)
        }
    
        //服务端连接状态回调
        private var mConnection = object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                Log.e(TAG, "onServiceConnected: $mRemoteBookManager")
                //将服务端返回的Binder对象转换为aidl对象
                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
            }
        }
    
    }
    

    点击获取Demo

    相关文章

      网友评论

          本文标题:AIDL基本使用

          本文链接:https://www.haomeiwen.com/subject/yxacoctx.html