进程通讯AIDL,即Android Interface Definition Language(安卓接口定义语言),主要是用来跨进程访问,例如服务器端与客户端通信时,服务端与客户端如何收发数据需要通过一个规范,一个接口等
语法:
- AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。但是在使用其他AIDL生成的接口时候,除了java的八种基本类型外,其他都需要import这些接口。
- AIDL只支持接口方法,不能公开static变量。
- 接口和方法前面不要加访问权限修饰符:public ,private,protected等,也不能用static final
- 自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义 的包在同一个包中。
代码实例:
service
首先src内创建一个AIDL,并在interface内写好需要给客户端调用的方法:
interface IMyService{
void getValue();
}
新建的AIDL文件内的接口有一个初始化化的方法,可以删除掉,接着clean一下项目,make project后as会自动生成一个java文件,里面是一些接口信息。
然后创建一个继承service的类,并继承IMyservice接口,重写在Aidl内创建的方法:
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return new MyServiceImpl();
}
public class MyServiceImpl extends IMyService.Stub {
@Override
public void getValue() throws RemoteException {
Log.w("Aidl Test", "创建成功");
}
}
AndroidMainfest.xml内声明service名字:
client
然后创建一个client工程,把service工程生成的AIDL文件包括aidl目录都复制到client工程的src目录内(client重复clean,make project一次)。
接着Main绑定service,接着就可以调用服务器生成的getValue()方法了.
public class AidlClientTestActivity extends AppCompatActivity implements View.OnClickListener {
IMyService mIMyService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIMyService = IMyService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl_client_test);
Intent serviceIntern = new Intent();
//Service name
serviceIntern.setAction("com.study.Service");
//Package name
serviceIntern.setPackage("com.study.service");
bindService(serviceIntern, mConnection, Context.BIND_AUTO_CREATE);
Button aidlTest = findViewById(R.id.test);
aidlTest.setOnClickListener(this);
}
@Override
public void onClick(View v) {
witch (v.getId()) {
case R.id.test:
try {
mIMyService.getValue();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
接着编译service后,运行客户端,点击按钮就可以看到service,显示的log了
但是aidl不支持Object类型,Object类型在很多地方都能用到,这时候怎么办呢?
使用Parcelable(Parcelable是Android为我们提供的序列化的接口)即可
aidl传递对象
建立一个javabean并实现parcelable 接口:
import android.os.Parcel;
import android.os.Parcelable;
public class Events implements Parcelable {
String name;
public Events(String name) {
this.name = name;
}
public Events() {
}
public static final Creator CREATOR = new Creator() {
@Override
public Events createFromParcel(Parcel in) {
return new Events(in);
}
@Override
public Events[] newArray(int size) {
return new Events[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected Events(Parcel in) {
name = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
}
创建一个和javabens一样名字的AIDL,并声明其类型和所在的包,这种aidl在编译后不会自动生成一个java文件,因为我刚刚开始说过,aidl在除了几种基本类型外,其他类型传递需要import,所以javabens的aidl只是作声明对应类所在的位置和类型
// Events.aidl
package com.study.service;
// Declare any non-default types here with import statements
parcelable Events;
接着一样在IMyservice.aidl内声明会调用的方法,并import Events 所在的目录位置:
import com.study.service.Events;
interface IMyService {
void getValue();
void printEvents(in Events events);
}
接着clean一下工程,并在Myservic类重写该方法:
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return new MyServiceImpl();
}
public class MyServiceImpl extends IMyService.Stub {
@Override
public void getValue() throws RemoteException {
Log.w("Aidl Test", "building successful");
}
@Override
public void printEvents(Events events) throws RemoteException {
Log.w("Events call successful ", events.getName());
}
}
}
把aidl重新复制在client工程,并在client工程内建立一个目录与Events类所在的包一样,并把events类复制过去。clean 一下project,调用方法:
public class AidlClientTestActivity extends AppCompatActivity implements View.OnClickListener {
IMyService mIMyService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIMyService = IMyService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl_client_test);
Intent serviceIntern = new Intent();
//Service name
serviceIntern.setAction("com.study.Service");
//Package name
serviceIntern.setPackage("com.study.service");
bindService(serviceIntern, mConnection, Context.BIND_AUTO_CREATE);
Button aidlTest = findViewById(R.id.test);
aidlTest.setOnClickListener(this);
Button addEvents = findViewById(R.id.events);
addDevice.setOnClickListener(this);
}
@Override
public void onClick(View v) {
witch (v.getId()) {
case R.id.test:
try {
mIMyService.getValue();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.events:
try {
Events events = new Events();
events.setName("study");
mIMyService.printEvents(events);
} catch (RemoteException e) {
e.printStackTrace();
}
default:
break;
}
}
重新运行一下service,和client就可以看到log了。