您的位置:首页 > 移动开发 > Android开发

Android IPC机制-AIDL详解

2017-03-24 22:36 393 查看

什么是AIDL?

官方解释:

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

通俗易懂:

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

要学习的知识:

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

为什么会有AIDL?

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

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

定义AIDL接口

准备

AIDL语法

AIDL支持下列数据类型:

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

String、CharSequence、List、Map

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

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

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

两种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 i
4000
n) {
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教程.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: