Android AIDL不同应用通信
简介
AIDL(Android接口定义语言),用于定义客户端与服务端进程间IPC通信接口。在Android,不同进程无法共享内存,所以使用AIDL通信
服务端使用AIDL的流程
1、在AIDL文件中定义接口IRemoteInterface(方法与变量)
2、Rebuild项目生成IBinder接口IRemoteInterface.Stub
3、实现IBinder接口内部的Stub抽象类(方法的具体实现),可以在Service中匿名实现
4、实现RemoteService重写onBind()来向客户端公开接口(return binder)
可以再Service中重写匿名内部类binder实例。然后再onbind中return
客户端使用AIDL流程
客户端需要包含AIDL文件,才能拥有接口类访问权限(IRemoteInterface)
在Activity中调用bindService连接服务。binderService需要intent(service),connection。
intent
Intent intent = new Intent();
intent.setAction("com.example.settinglib.fruitservice");
intent.setPackage("com.example.administrator.testdemo");//设置服务端的package
bindService(intent, mConnection, BIND_AUTO_CREATE);
connection
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接后拿到 Binder,转换成 AIDL,在不同进程会返回个代理
mAidl = IFruitManger.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
之后就可以用该接口调用服务端的方法
高级技巧
服务端创建各种实体类,实体类需要实现Parcelable接口。只有可序列化的数据才可以在不同进程间传送
public class Fruit implements Parcelable {
private String mName ;
private int mNumber;
public Fruit(Parcel source) {
mName = source.readString();
mNumber = source.readInt();
}
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
public int getmNumber() {
return mNumber;
}
public void setmNumber(int mNumber) {
this.mNumber = mNumber;
}
public Fruit(String name, int number) {
this.mName = name;
this.mNumber = number;
}
public static final Creator<Fruit> CREATOR = new Creator<Fruit>() {
@Override
public Fruit createFromParcel(Parcel in) {
return new Fruit(in);
}
@Override
public Fruit[] newArray(int size) {
return new Fruit[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(mName);
parcel.writeInt(mNumber);
}
@Override
public String toString() {
return String.format("[mName:%s, mNumber:%s]", mName, mNumber);
}
}
创建AIDL文件Fruit.aidl
package com.example.settinglib;
parcelable Fruit;
创建IFruitManager.aidl
aidl中,除了基本数据类型,其他数据类型必须用 in/out/inout 其中一种标识
in:输入型参数
out:输出型参数
intout:输入输出型参数
package com.example.settinglib;
import com.example.settinglib.Fruit;
import com.example.settinglib.INewFruitAddListener;
interface IFruitManger {
void addFruit(in Fruit fruit);
List<Fruit> getFruitList();
void registerListener(INewFruitAddListener listener);
void unregisterListener(INewFruitAddListener listener);
}
创建服务监听器INewFruitAddListener
package com.example.settinglib;
import com.example.settinglib.Fruit;
interface INewFruitAddListener {
void onINewFruitAdd(in Fruit fruit);
}
创建服务FruitService
public class FruitService extends Service {
private ArrayList<Fruit> mFruits;
//它是线程安全的
private AtomicBoolean mIsServiceDestory = new AtomicBoolean(false);
private RemoteCallbackList<INewFruitAddListener> mListenerList = new RemoteCallbackList<INewFruitAddListener>();
@Override
public IBinder onBind(Intent intent) {
//检测权限,客服端没有注册这个权限,就不让绑定服务
int check = checkCallingOrSelfPermission("com.example.settinglib.permission.ACCESS_FRUIT_SERVICE");
if (check == PackageManager.PERMISSION_DENIED){
Log.e("date", "PERMISSION_DENIED: ACCESS_FRUIT_SERVICE" );
return null;
}
mFruits = new ArrayList<Fruit>();
mFruits.add(new Fruit("apple", 2));
mFruits.add(new Fruit("banana", 4));
return mIBinder;
}
/**
* 创建生成的本地 Binder 对象,实现 AIDL 制定的方法
*/
private IBinder mIBinder = new IFruitManger.Stub() {
@Override
public void addFruit(Fruit fruit) throws RemoteException {
mFruits.add(fruit);
}
@Override
public List<Fruit> getFruitList() throws RemoteException {
return mFruits;
}
@Override
public void registerListener(INewFruitAddListener listener) throws RemoteException {
mListenerList.register(listener);
}
@Override
public void unregisterListener(INewFruitAddListener listener) throws RemoteException {
mListenerList.unregister(listener);
}
};
private void onINewFruitAdd(Fruit fruit) throws RemoteException {
mFruits.add(fruit);
int number = mListenerList.beginBroadcast();
for (int i = 0; i < number; i++) {
INewFruitAddListener listener = mListenerList.getBroadcastItem(i);
if (listener != null) {
try {
listener.onINewFruitAdd(fruit);
} catch (RemoteException e) {
Log.e("date", "onINewFruitAdd: " + e.getMessage());
}
}
}
mListenerList.finishBroadcast();
}
@Override
public void onCreate() {
super.onCreate();
new Thread(new ServiceWork()).start();
}
@Override
public void onDestroy() {
super.onDestroy();
mIsServiceDestory.set(true);
}
/**
*模拟,每隔3s 向客服端添加一条数据
* */
private class ServiceWork implements Runnable {
@Override
public void run() {
while (!mIsServiceDestory.get()) {
try {
Thread.sleep(3000);
int fruitId = mFruits.size() + 1;
onINewFruitAdd(new Fruit("茄子", fruitId));
} catch (Exception e) {
Log.e("date", "ServiceWork: " + e.getMessage());
}
}
}
}
}
注册服务
<service
android:name=".FruitService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.settinglib.fruitservice"/>
</intent-filter>
</service>
客户端连接服务
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接后拿到 Binder,转换成 AIDL,在不同进程会返回个代理
mAidl = IFruitManger.Stub.asInterface(service);
try {
if (mAidl != null)
mAidl.registerListener(mFruitListener);
} catch (RemoteException e) {
Log.e(TAG, "onCreate: " + e.getMessage());
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
try {
//mAidl为服务端进行的Service对象,通过asBinder()可以获得Binder对象
mAidl.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
Log.e(TAG, "onServiceDisconnected: " + e);
}
}
};
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mAidl == null) return;
//解除死亡通知,如果Binder死亡了,不会在触发binderDied方法
mAidl.asBinder().unlinkToDeath(mDeathRecipient, 0);
mAidl = null;
//重新绑定服务
Intent intent = new Intent();
intent.setAction("com.example.settinglib.fruitservice");
intent.setPackage("com.example.administrator.testdemo");//设置服务端的package
bindService(intent, mConnection, BIND_AUTO_CREATE);
}
};
客户端监听数据
private INewFruitAddListener mFruitListener = new INewFruitAddListener.Stub() {
@Override
public void onINewFruitAdd(Fruit fruit) throws RemoteException {
Log.e(TAG, "onINewFruitAdd: ");
weakHandler.obtainMessage(FRUIT_ADD,fruit).sendToTarget();
}
};
private HandlerUtil.WeakHandler weakHandler = new HandlerUtil.WeakHandler(this);
@Override
public void handleMessage(Message message) {
switch (message.what) {
case FRUIT_ADD:
Fruit fruit = (Fruit) message.obj;
Log.e("date", "添加新的水果了: " + fruit.getmName() + fruit.getmNumber());
ToastUtils.showShortToast("添加新的水果了: " + fruit.getmName() + fruit.getmNumber());
break;
}
}
各种操作
private ExecutorService mSingleThread= Executors.newSingleThreadExecutor();
private void queryData() {
if (!mSingleThread.isShutdown()){
mSingleThread.execute(new Runnable() {
@Override
public void run() {
List<Fruit> fruitList = null;
try {
fruitList = mAidl.getFruitList();
ToastUtils.showShortToast("水果的数量: " + fruitList.size());
for (int i = 0; i < fruitList.size(); i++) {
Log.e("date", fruitList.get(i).getmName());
}
} catch (RemoteException e) {
}
}
});
}
}