Android IPC机制-AIDL详解

什么是AIDL?

  • 官方解释:

    AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似。 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。 在 Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。 编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理.

  • 通俗易懂:

    就是Android接口定义语言, 就是一种语言.

  • 要学习的知识:

    需要了解相关的Service知识, 而且还要了解通透, 所以我贴出我之前写的一篇文章: [四大组件] Service详解,你不知道的都在这里


为什么会有AIDL?

其实我上面的官方解释也有说到为什么会有AIDL这门语言, 主要是为了实现 进程间的通信.

也就是一个进程可以访问另一个进程的数据, 甚至调用一些方法.


定义AIDL接口

  • 准备

    1. AIDL语法

      AIDL支持下列数据类型:

      • Java中所有原语类型(如int,long,char,boolean等)

      • String、CharSequence、List、Map

      定义服务接口时,需注意:

      • 方法可带零个或多个参数,返回值或空值。

      • 所有非原语参数都需要指示数据走向的方向标记。可以是in、out或inout(见以下示例)。原语默认为 in,不能是其他方向。

    2. 两种AIDL文件
      • 定义parcelable对象

      • 定义方法接口

      注: 所有非默认支持数据类型必须通过第一类AIDL文件定义才能被使用.

  • 实例操作

    • 数据类实现Parcelable接口

      为了使一个进程能够访问到另一个进程的数据, 我们需要将类序列化, 然后再将数据传到服务端, 服务端反序列化操作, 从而获取到了数据.

      首先创建一个实体类, 并且实现Parcelable接口的一些方法, 代码如下:

      public class Book implements Parcelable {
      
          private String name;
          private String author;
      
          public Book(String name) {
              this.name = name;
          }
      
          protected Book(Parcel in) {
              name = in.readString();
              author = 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];
              }
          };
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public String getAuthor() {
              return author;
          }
      
          @Override
          public int describeContents() {
              return 0;
          }
      
          @Override
          public void writeToParcel(Parcel dest, int flags) {
              dest.writeString(name);
              dest.writeString(author);
          }
      }
    • 书写.aidl文件

      如果你是使用Android studio的话, 可以像下图创建aidl文件:

      这里写图片描述

      这里写图片描述

      • 首先创建Book.aidl
      //第一类AIDL文件
      引入一个序列化对象Book供其他AIDL文件使用
      package com.rcd.democomponents;
      parcelable Book;
      • 然后是BookManager.aidl
      //这个是第二类AIDL, 定义方法接口
      package com.rcd.democomponents;
      //这里需要导入所需要使用的非默认支持数据类型的包
      import com.rcd.democomponents.Book;
      interface BookManager {
          List<Book> getBook();
      
          void addBook(in Book book);
      }
      • 然后是Service的书写:
      public class DemoService extends Service {
      
          private static final String TAG = "demoservice";
      
          private List<Book> mBooks;
          private IBinder mBinder=new BookManager.Stub(){
      
              @Override
              public List<Book> getBook() throws RemoteException {
                  synchronized (this){
                      Log.d(TAG, "getBook: ");
                      return new ArrayList<>();
                  }
              }
      
              @Override
              public void addBook(Book book) throws RemoteException {
                  synchronized (this){
                      if(mBooks==null){
                          mBooks=new ArrayList<>();
                      }
                      if(book==null){
                          book=new Book();
                      }
                      if(!mBooks.contains(book)){
                          mBooks.add(book);
                      }
                      Log.d(TAG, "addBook: "+mBooks.toString());
                  }
              }
          };
      
          @Override
          public void onCreate() {
              super.onCreate();
              Log.d(TAG, "onCreate: ");
              mBooks=new ArrayList<>();
              Book book=new Book();
              book.setName("那时候坚持不懈的我");
              mBooks.add(book);
          }
      
          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
              Log.d(TAG, "onStartCommand: ");
              return super.onStartCommand(intent, flags, startId);
          }
      
          @Override
          public void onDestroy() {
              Log.d(TAG, "onDestroy: ");
              super.onDestroy();
          }
      
          @Nullable
          @Override
          public IBinder onBind(Intent intent) {
              return mBinder;
          }
      }

      就是实现BookManager.Stub中的两个AIDL已定义的方法来获取IBinder的实例, 然后在onBind方法返回这个mBinder.

      • 最后是客户端的代码
      public class MainActivity extends AppCompatActivity implements View.OnClickListener {
      
          private static final String TAG = "MainActivity";
          private Button mBtnStart, mBtnStop, mBtnBind, mBtnUnbind;
          private BookManager mBookManager;
          private List<Book> mBooks;
      
          private ServiceConnection mServiceConnection = new ServiceConnection() {
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                  mBookManager=BookManager.Stub.asInterface(service);
                  if(mBookManager!=null){
                      try {
                          mBooks=mBookManager.getBook();
                      } catch (RemoteException e) {
                          e.printStackTrace();
                      }
                  }
              }
      
              @Override
              public void onServiceDisconnected(ComponentName name) {
                  Log.d(TAG, "onServiceDisconnected: ");
              }
          };
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              mBtnStart = (Button) findViewById(R.id.btn_start);
              mBtnStop = (Button) findViewById(R.id.btn_stop);
              mBtnBind = (Button) findViewById(R.id.btn_bind);
              mBtnUnbind = (Button) findViewById(R.id.btn_unbind);
      
              mBtnStart.setOnClickListener(this);
              mBtnStop.setOnClickListener(this);
              mBtnBind.setOnClickListener(this);
              mBtnUnbind.setOnClickListener(this);
          }
      
          @Override
          public void onClick(View v) {
              Intent intent = new Intent(this, DemoService.class);
              switch (v.getId()) {
                  case R.id.btn_start:
                      startService(intent);
                      break;
                  case R.id.btn_stop:
                      stopService(intent);
                      break;
                  case R.id.btn_bind:
                      bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
                      break;
                  case R.id.btn_unbind:
                      unbindService(mServiceConnection);
                      break;
                  default:
                      break;
              }
          }
      
      
          //addBook_ aidl
          private void addBook(View view){
              if(mBookManager!=null){
                  Book book=new Book();
                  book.setName("你好啊");
                  try {
                      mBookManager.addBook(book);
      
                  } catch (RemoteException e) {
                      e.printStackTrace();
                  }
              }
          }
      }

      这里实现了ServiceConnection的两个方法,并且使用BookManager.Stub.asInterface(service)获取到了BookManager的实例, 所以可以调用addBook和getBook的方法.

    • 效果图

    这里写图片描述


有关AIDL今天先介绍到这里, 有兴趣的朋友可以上官网去看详细的Demo教程.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值