AIDL是什么
AIDL(Android Interface Definition Language)是Android系统自定义的接口描述语言。可以用来实现进程间的通讯。
AIDL 支持的数据类型
共 4 种:
- Java 的基本数据类型
- List 和 Map
- 元素必须是 AIDL 支持的数据类型
- Server 端具体的类里则必须是 ArrayList 或者 HashMap
- 其他 AIDL 生成的接口
- 实现 Parcelable 的实体
aidl实现步骤(案例一:简单的add)
此次的demo,服务端也进行了调试,如果服务端调通了启动服务与调用方法,客户端启动服务和调用方法可直接复制过去。
服务端
1、创建项目:创建DemoAidlService项目(跟正常一样)
2、创建aidl文件:
在app(Android预览目录下)上右键 New -> AIDL -> AIDL File。此时自动创建aidl文件夹,并在aidl文件夹下创建跟DemoAidlService包名一样的路径,且创建aidl结尾的文件,
点击build后,发现build文件夹下自动生成debug文件夹下的aidl编译文件
3、添加aidl里的抽象方法:在aidl文件下添加方法(如add(in int x, in int y)
interface IAddAidlInterface {
/**
* 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);
int add(in int x, in int y);
}
4、 创建服务:创建自定义服务AddService继承自Service,在生命周期onBind()中返回值返回 aidl对象mBinder,mBinder = InAddAidlInterface.Stub(){ 可重写抽象方法,并实现逻辑 }
public class AddService extends Service {
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
IAddAidlInterface.Stub mBinder = new IAddAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public int add(int x, int y) throws RemoteException {
return x + y;//具体的实现逻辑
}
};
}
5、启动服务:启动服务时要用绑定式启动bindService,bindService(intent, mConn, Context.BIND_AUTO_CREATE),
关键是第二个mConn参数,mConn = ServiceConnection(){ 默认两个抽象方法,在连接成功方法onServiceConnected中赋值aidl对象mService = IAddAidlInterface.Stub.asInterface(service) }
注意要asInterface,不然会报错。
public class MainActivity extends AppCompatActivity {
private IAddAidlInterface mService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aboutService();
findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_x)).getText().toString());
int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_y)).getText().toString());
try {
Log.d("baibai", "服务端 相加结果:" + mService.add(x, y));
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("baibai", "服务端:连接 Service 成功");
mService = IAddAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private void aboutService() {
Intent intent = new Intent(this, AddService.class);
bindService(intent, mConn, Context.BIND_AUTO_CREATE);
}
}
6、调用方法:实际调用mService的里的方法。
客户端
1、创建项目:创建DemoAidlClient项目(跟正常一样)
2、创建aidl文件(但是跟服务端创建的方式):
不能右键New -> ……,因为如果这么创建会创建跟DemoAidlClient的包名是一样的,而我们需要的是跟服务端的包名一样,所以要自己手动创建跟服务端一样的包名路径,并把服务端的aidl复制到改包名下,build一下,客户端项目就可以引用到服务端aidl文件的抽象方法。
3、启动服务:
public class MainActivity extends AppCompatActivity {
private IAddAidlInterface mService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aboutService();
findViewById(R.id.btn_add_client).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_client_x)).getText().toString());
int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_client_y)).getText().toString());
try {
Log.d("baibai", "客户端 相加结果:" + mService.add(x, y));
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private void aboutService() {
Intent intent = new Intent();
intent.setAction("bai.bai.bai.aidl.service_add");//5.0出现以后必须使用显示启动,不然会报错(加了下一行代码可解决这个问题)
intent.setPackage("bai.bai.bai.demoaidlservice");//加了这行代码,就可以解决5.0版本后隐式启动服务报错的问题
Log.d("baibai", "aboutService");
bindService(intent, mConn, Context.BIND_AUTO_CREATE);
}
ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("baibai", "客户端:连接 Service 成功");
mService = IAddAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConn);
}
}
启动服务时要用绑定式启动bindService,bindService(intent, mConn, Context.BIND_AUTO_CREATE),
第一个参数initent:intent里没有参数,要intent.setAction(过滤条件),即隐式调用,所以要在服务端的清单文件里给service添加acton,以便客户端使用
ps:a、要在onDestory()方法里解除绑定,不然会报错。
b、绑定的时候,必须有Intent.setPackage(服务器的包名),不然会报错(5.0后必须使用显示启动服务,添加这一行代码可解决这一报错问题)。
c、只有在连接成功的时候才会调用onServiceConnected()方法,此时mBinder才不为空,类型转换的时候最好用IAddService.Stub.asInterface()方法,不要直接强制转换。
第二个参数mConn:mConn = ServiceConnection(){ 默认两个抽象方法,在连接成功方法onServiceConnected中赋值aidl对象mService = IAddAidlInterface.Stub.asInterface(service) }
注意要asInterface,不然会报错。
4、调用方法:实际调用mService的里的方法。
参考git代码:服务端:https://github.com/baiyun1234/DemoAidlService
客户端:https://github.com/baiyun1234/DemoAidlClient
参考网址:https://blog.csdn.net/guanhang89/article/details/51386404