1.关于AIDL
AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。设计这门语言的目的是为了实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信。
2.Demo
首先,在AS工程中创建一个.aidl文件,该文件定义了通信接口。
// IMyAidlInterface.aidl
package com.leeee.aidltest;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* 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);
String getInfo();
}
这里我只添加了一个简单的方法getInfo(),建立.aidl文件后rebuild工程,系统会自动生成IMyAidlInterface.Stub();
然后,创建Service类(在Manifest中配置为独立进程的Service)
public class MyService extends Service {
public final static String TAG = "MyService";
private IBinder mBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public String getInfo() throws RemoteException {
return "我是 Service 返回的字符串";
}
};
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
Log.e("lyt", "onCreate");
}
@Override
public IBinder onBind(Intent intent) {
Log.e("lyt", "onBind");
return mBinder;
}
}
由于要用到aidl进行进程通信,在这个Service中,定义了一个mBinder并实现IMyAidlInterface定义的接口。在onBind()方法中返回该mBinder。
最后,写Activity。
public class MainActivity extends AppCompatActivity {
public final static String TAG = "MainActivity";
private Button startBtn = null;
IMyAidlInterface mAidlInterface;
private ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("lyt", "onServiceConnected");
mAidlInterface = IMyAidlInterface.Stub.asInterface(service);
String s = null;
try {
s = mAidlInterface.getInfo();
} catch (RemoteException e) {
e.printStackTrace();
}
Log.e("lyt", "从Service得到的字符串:" + s);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("lyt", "连接Service失败");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startBtn = (Button) findViewById(R.id.button);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, mConn, BIND_AUTO_CREATE);
}
});
}
}
测试demo,界面很简单,就包含一个button,点击后启动Service。
在自定义ServiceConnection的onServiceConnected()方法中,我们用IMyAidlInterface.stub.asInterface(service)方法在Activity进程中拿到aidl接口。通过调用这个接口中定义的方法,实现进程通信。
打印信息如下:
01-01 00:05:26.211 5474-5474/com.leeee.remoteServer E/lyt: onCreate
01-01 00:05:26.213 5474-5474/com.leeee.remoteServer E/lyt: onBind
01-01 00:05:26.224 5379-5379/com.leeee.aidltest E/lyt: onServiceConnected
01-01 00:05:26.227 5379-5379/com.leeee.aidltest E/lyt: 从Service得到的字符串:我是 Service 返回的字符串
3.总结
1.启动Service时,不能用startService()方法,因为该方法不提供ServiceConnection,不能进行通信;必须用bindService()来启动。
2.IBinder类是Service提供的唯一的通信手段。
3.若要传输数据,需要用Parcelable接口进行序列化和反序列化。若aidl文件中仅包含默认支持的数据类型需要传输,则无需序列化。
4.若某个自定义类需要进行序列化并传输,需要在定义类时implements Parcelable接口。
5.编写aidl通信的基本逻辑是:在服务端实现AIDL中定义的方法接口的具体逻辑,然后在客户端调用这些方法接口,从而达到跨进程通信的目的。