Android中AIDL使用详解

简介
AIDL:Android Interface Definition Language,即Android接口定义语言,用于生成Android不同进程间进行进程通信(IPC)的代码,一般情况下一个进程是无法访问另一个进程的内存的。如果某些情况下仍然需要跨进程访问内存数据,这时候Android系统就要将其对象分解成能够识别的原数据,编写这一组操作的代码是一项繁琐的工作,但是AIDL对底层进行了抽象的封装,简化了跨进程操作。

AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

接下来介绍在AndroidStudio中使用ALDL在进程间通讯(也就是两个应用的通讯)分别从服务端和客户端两个方面

1. 服务端:
服务端首先要创建一个Service用来监听客户端的连接请求,然后创建ALDL文件,将暴露给客户端的接口在这个ALDL文件的申明,最后在Service中实现这个ALDL的接口实现

2. 客户端:
客户端首先需要绑定服务端的Service,绑定成功之后,将服务器返回的Binder对象转换成ALDL接口所属的类型,接着就可以调用ALDL中的方法

3. ALDL接口的创建:
首先看ALDL接口的创建,如下所示,我们创建
自定义类要实现Parcelable
服务端的ALDL部署
结构图

/**
  *自定义类型
  **/
public class Book implements Parcelable {
    private int bookId;
    private 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 Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

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

    @Override
    public String toString() {
        return "Book{" +
                "bookId=" + bookId +
                ", bookName='" + bookName + '\'' +
                '}';
    }
}

下面是两个ALDL文件

Book.aidl

// Book.aidl
package com.example.administrator.wuandy;

// Declare any non-default types here with import statements
//ALDL中使用自定义的Parcelable为其声明类型
parcelable Book;

IBookManger.aidl

// IBookManger.aidl
package com.example.administrator.wuandy;
import com.example.administrator.wuandy.Book;

// Declare any non-default types here with import statements

interface IBookManger {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

     List<Book>getBookList();

     void addBook(in Book book);

     String getBookName();
}

运行你的aidl会报错,log显示找不到Book的定义,没错现在你的Book在aidl包下,编译时不会去它下面找类,此时你需要做以下工作,在build.gradle文件中加入以下代码。。

 sourceSets{
        main{
                  java.srcDirs = ['src/main/java', 'src/main/aidl']
            }  
   }

编译成功之后会出现
这里写图片描述
ALDL文件支持的格式那些数据类型呢?如下所示

  • 基本数据类型
  • String和CharSequence
  • list:只支持ArrayList,里面的每个元素都必须能够被ALDL支持
  • Map:只支持HashMap,里面的每个元素都必须被ALDL支持,包括key和value
  • Parcelable:所有实现了Parcelable的对象
  • ALDL:所有ALDL接口本身也可以在ALDL文件中使用

注意
1.ALDL中除了基本数据类型,其他类型的参数必须表上方向:in 、out、inout,in表示输入型参数,out表示输出型参数,inout表示输入输出型参数
2. ALDL接口中只支持方法,不支持声明静态变量,
3.为了方便ALDL开发,建议将所有和ALDL相关的类和文件全部放入同一个包中,这样我们可以直接将整个包复制到客户端工程中,ALDL包的结构在客户端和服务端保持一致,否则会错。因为客户端要反序列化服务端中和ALDL接口相关的所有类,如果类的完整路径不对就无法成功反序列化。

4.远程服务端Service的实现

package com.example.administrator.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;

import com.example.administrator.wuandy.Book;
import com.example.administrator.wuandy.IBookManger;
import com.orhanobut.logger.Logger;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018/2/8.
 */

public class MyService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }
    class MyBinder extends IBookManger.Stub{
    private List<Book> books=new ArrayList<>();
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public List<Book> getBookList() throws RemoteException {
            Book book=new Book(1,"ANDROID");
            books.add(book);
            Book book1=new Book(2,"IOS");
            books.add(book1);
            Logger.d("MyBinder:集合_getBookList()"+books.size());
            return books;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            books.add(book);
            Logger.d("MyBinder:集合_addBook()"+books.size());
        }

        @Override
        public String getBookName() throws RemoteException {
            return "Java";
        }


    }
}

Service的注册

  <service android:name="com.example.administrator.service.MyService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.Andy.ALDL"></action>
            </intent-filter>
        </service>

5.客户端的实现

package com.example.administrator.wuandy;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
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.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

  private IBookManger iBookManger;
  private Button start;
  private TextView content;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       start=findViewById(R.id.start);
       content=findViewById(R.id.content);
       start.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               Intent intent=new Intent();
               intent.setAction("com.Andy.ALDL");
               intent.setPackage("com.example.administrator.wuandy");
               bindService(intent, new ServiceConnection() {
                   @Override
                   public void onServiceConnected(ComponentName name, IBinder service) {
                       iBookManger=IBookManger.Stub.asInterface(service);
                       Toast.makeText(MainActivity.this,"远程服务连接上了",Toast.LENGTH_SHORT).show();
                   }

                   @Override
                   public void onServiceDisconnected(ComponentName name) {

                   }
               },BIND_AUTO_CREATE);
           }
       });
       content.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               try {
                   content.setText(iBookManger.getBookList().toString());
               } catch (RemoteException e) {
                   e.printStackTrace();
               }
           }
       });

    }

    @Override
    protected void onDestroy() {
      //注意要解绑
        super.onDestroy();
    }
}

最后贴上运行之后的效果
这里写图片描述

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值