AIDL
跨进程通信,使用AIDL
来实现的基本步骤,以及需要注意的点。
- 创建
AIDL
中使用到的类,继承Parcelable
。- 右键,创建
AIDL
文件夹,这个文件夹是和java
文件夹同级的。- 创建一个类的
AIDL
文件,内容为parcelable Book;
这样。- 在上面创建的那个
AIDL
文件中,引入类,并写入客户端可能使用的方法。
import com.wm.aidlservice.Book;
import com.wm.aidlservice.IOnNewBookArrivedListener;
interface IBookManager {
void addBook(in Book book);
List<Book> getBookList();
void registerListener(IOnNewBookArrivedListener listener);
void unregisterListener(IOnNewBookArrivedListener listener);
}
-
创建一个
Service
,重写AIDL
里面的Stub
类,然后将Binder
返回。 -
注意
Service
,在manifest
添加category
<service
android:name=".BookManagerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.wm.aidlservice.BookManagerService"/>
</intent-filter>
</service>
- 在客户端程序里面,绑定此
Service
Intent intent = new Intent();
intent.setAction("com.wm.aidlservice.BookManagerService");
intent.setPackage("com.wm.aidlservice");
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
接下来就可以,调用服务端的方法了。
需要注意的是
-
服务端的方法,是运行在
Binder
线程中的,客户端防止发生ANR
的情况。 -
当服务端,通过观察者模式去调用客户端方法的时候,此时客户端的方法运行在
Binder
中,防止服务端出现ANR
。 -
基于2,注册和解注册的时候,需要使用
RemoteCallbackList
private RemoteCallbackList<IOnNewBookArrivedListener> listeners = new RemoteCallbackList<>();
// 注册
listeners.register(listener);
// 解注册
listeners.unregister(listener);
// 采用这种方式调用
final int N = listeners.beginBroadcast();
for (int i = 0; i < N; i++) {
IOnNewBookArrivedListener listener = listeners.getBroadcastItem(i);
if (listener != null) {
listener.onNewBookArrived(book);
}
}
listeners.finishBroadcast();
- 对
AIDL
的服务端,设置权限验证的问题,1
是在onBinder()
中设置(两个APP,无效),2是通过onTransact()
中设置,类似过滤器,可以筛选包名或者权限。
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
String packageName = null;
String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
if (packages != null && packages.length > 0) {
packageName = packages[0];
}
if (packageName == null) {
return false;
}
boolean result = checkPermission(BookManagerService.this,"com.wm.aidlservice.permission.ACCESS_BOOK_SERVICE",packageName);
if (!result) {
Log.d(TAG,"授权失败");
return false;
}
return super.onTransact(code, data, reply, flags);
}
private boolean checkPermission(Context mContext,String permissionName,String packageName) {
int permission = mContext.getPackageManager().checkPermission(permissionName,packageName);
if (permission == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
附链接:
https://www.jianshu.com/p/a8e43ad5d7d2
https://www.cnblogs.com/xqz0618/p/aidl_service.html
https://www.cnblogs.com/androidxiaoyang/p/5919372.html
网友评论