IPC通信之AIDL
AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似。 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。 在 Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。 编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。
注:只有允许不同应用的客户端用 IPC 方式访问服务,并且想要在服务中处理多线程时,才有必要使用 AIDL。 如果您不需要执行跨越不同应用的并发 IPC,就应该通过实现一个 Binder 创建接口;或者,如果您想执行 IPC,但根本不需要处理多线程,则使用 Messenger 类来实现接口。无论如何,在实现 AIDL 之前,请您务必理解绑定服务。
AIDL接口定义
.aidl支持int,String,boolean,charSequence、List、Map这些数据类型以及实现Parcelable接口的实体类。
// IMyAidlInterface.aidl
package lennie.org.lennie.aidl;
// Declare any non-default types here with import statements
//这里需要引入回调接口,不然编译器找不到IMyCallback这个接口
import lennie.org.lennie.aidl.IMyCallback;
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);
void onCallback(IMyCallback callback);
}
// IMyCallback.aidl
package lennie.org.lennie.aidl;
// Declare any non-default types here with import statements
interface IMyCallback {
void onSuccess(int i);
void onError(String s);
}
定义好接口后,需要“”Make Module“”下工程,gradle才会自动生成aidl文件
Service端定义
package lennie.org.lennie;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import lennie.org.lennie.aidl.IMyAidlInterface;
import lennie.org.lennie.aidl.IMyCallback;
/**
* Created by win7 on 2017/7/26.
*/
public class MyService extends Service {
private static final String TAG = "MyService";
private RemoteCallbackList<IMyCallback> callbackList = new RemoteCallbackList<IMyCallback>();
//声明aidl接口
private IMyAidlInterface.Stub mIBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
Log.i(TAG, "anInt = " + anInt);
Log.v(TAG, "aLong = " + aLong);
Log.d(TAG, "aBoolean = " + aBoolean);
Log.e(TAG, "aFloat = " + aFloat);
Log.w(TAG, "aDouble = " + aDouble);
onSuccessCallback();
onErrorCallback();
}
@Override
public void registerCallback(IMyCallback callback) throws RemoteException {
if (callback != null) {
Log.i(TAG,"registerCallback===>");
callbackList.register(callback);
}
}
@Override
public void unregisterCallback(IMyCallback callback) throws RemoteException {
if (callback != null) {
callbackList.unregister(callback);
}
}
};
@Override
public IBinder onBind(Intent intent) {
//返回定义好的IBinder
return mIBinder;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"onCreate == >");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG,"onStartCommand == >");
return super.onStartCommand(intent, flags, startId);
}
private void onSuccessCallback() {
//参照源码实现
int beginBroadcast = callbackList.beginBroadcast();
for (int i = 0; i < beginBroadcast; i++) {
try {
callbackList.getBroadcastItem(i).onSuccess(1);
} catch (RemoteException e) {
e.printStackTrace();
}
}
callbackList.finishBroadcast();
}
private void onErrorCallback() {
int beginBroadcast = callbackList.beginBroadcast();
for (int i = 0; i < beginBroadcast; i++) {
try {
callbackList.getBroadcastItem(i).onError("2");
} catch (RemoteException e) {
e.printStackTrace();
}
}
callbackList.finishBroadcast();
}
@Override
public void onDestroy() {
super.onDestroy();
callbackList.kill();
}
}
客户端定义
package lennie.org.lennie;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.app.Activity;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import lennie.org.lennie.aidl.IMyAidlInterface;
import lennie.org.lennie.aidl.IMyCallback;
public class AIDLActivity extends Activity {
@BindView(R.id.tv)
TextView tv;
@BindView(R.id.tv_)
TextView tv_;
private IMyAidlInterface myAidlInterface;
//实现IMyCallback接口
private IMyCallback myCallback = new IMyCallback.Stub() {
@Override
public void onSuccess(final int i) throws RemoteException {
new Handler().post(new Runnable() {
@Override
public void run() {
tv.setText(" i = " + i);
}
});
}
@Override
public void onError(final String s) throws RemoteException {
new Handler().post(new Runnable() {
@Override
public void run() {
tv_.setText(" s = " + s);
}
});
}
};
//使用ServiceConnection与Services进行通信
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取AIDL接口对象
myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
myAidlInterface.registerCallback(myCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
Toast.makeText(AIDLActivity.this,"绑定成功",Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
try {
myAidlInterface.unregisterCallback(myCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
myAidlInterface = null;
Toast.makeText(AIDLActivity.this,"解开绑定",Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
ButterKnife.bind(this);
Intent intent = new Intent(this,MyService.class);
//在5.0及以上版本必须要加上这个
intent.setPackage("service.hht.com.serviceapplication");
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
@OnClick(R.id.bt)
public void onClick(View v) {
if(myAidlInterface!=null){
try {
myAidlInterface.basicTypes(1,1,true, 1,2.2,"123");
} catch (RemoteException e) {
e.printStackTrace();
}
}else{
Toast.makeText(AIDLActivity.this,"服务未启动",Toast.LENGTH_SHORT).show();
}
}
}
总结
aidl有大三步骤:
- 定义AIDL接口
1、如果定义回调接口,需要既定使用import,把回调接口路径引入进来
2、使用“”Make Module“” 下工程,gradle才会自动生成aidl文件
- Service暴露接口
1、声明mIBinder接口,通过mIBinder把接口暴露给客户端
2、如有回调使用RemoteCallbackList 进行接收和操作
- 客户端绑定Service
1、使用ServiceConnection进行与Service绑定,使用定义好的AIDL文件来接受IBinder(IMyAidlInterface.Stub.asInterface(IBinder))
2 、如有回调则实现回调函数
因这几天看到AIDL的接口,因此做此记录。