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

Android中AIDL使用详解

2018-02-27 15:58 507 查看
简介

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();
}
}


最后贴上运行之后的效果

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