跨进程调用的实现
ContentProvider
CC通过自定义ContentProvider实现跨进程通信,每个应用在AndroidManifest.xml中定义好provider。
- exported为true,表明可跨进程调用。
- applicationId在build.gradle中配置,一般是应用的包名
- aithroities是包名+provider本身的名称
<provider
android:authorities="${applicationId}.com.billy.cc.core.remote"
android:name=".remote.RemoteProvider"
android:exported="true"
/>
RemoteProvider
RemoteProvider继承了ContentProvider,重写了query()方法,返回一个RemoteCursor对象
public class RemoteProvider extends ContentProvider {
public static final String[] PROJECTION_MAIN = {"cc"};
public static final String URI_SUFFIX = "com.billy.cc.core.remote";
@Override
public boolean onCreate() {
CC.log("RemoteProvider onCreated! class:%s", this.getClass().getName());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
if (CC.isRemoteCCEnabled() || getCallingUid() == Process.myUid()) {
//获取当前ContentProvider所在进程中的RemoteCursor单例对象
return RemoteCursor.getInstance();
}
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
RemoteCursor
RemoteCursor继承了MatrixCursor,是用于跨进程通信的游标,通过bundle跨进程传递IBinder对象。
public class RemoteCursor extends MatrixCursor {
private static final String KEY_BINDER_WRAPPER = "BinderWrapper";
static final String[] DEFAULT_COLUMNS = {"cc"};
//-------------------------单例模式 start --------------
/** 单例模式Holder */
private static class CCCursorHolder {
private static final RemoteCursor INSTANCE = new RemoteCursor(DEFAULT_COLUMNS, RemoteCCService.getInstance());
}
private RemoteCursor(String[] columnNames, IBinder binder) {
super(columnNames);
binderExtras.putParcelable(KEY_BINDER_WRAPPER, new BinderWrapper(binder));
}
/** 获取CCCursor在当前进程中的单例对象 */
public static RemoteCursor getInstance() {
return RemoteCursor.CCCursorHolder.INSTANCE;
}
//-------------------------单例模式 end --------------
private Bundle binderExtras = new Bundle();
@Override
public Bundle getExtras() {
return binderExtras;
}
public static IRemoteCCService getRemoteCCService(Cursor cursor) {
if (null == cursor) {
return null;
}
Bundle bundle = cursor.getExtras();
bundle.setClassLoader(BinderWrapper.class.getClassLoader());
BinderWrapper binderWrapper = bundle.getParcelable(KEY_BINDER_WRAPPER);
if (binderWrapper != null) {
IBinder binder = binderWrapper.getBinder();
return IRemoteCCService.Stub.asInterface(binder);
}
return null;
}
}
BinderWrapper
BinderWrapper用于封装IBinder,实现Parcelable接口,使得IBinder对象可以被序列化和反序列化,并可以跨进程传递。
跨进程CC调用的流程
-
开启跨进程功能,CC查询本机支持CC组件的app(通过线程池启动任务,每隔50ms进行监听)
(1)监听本机应用的安装和卸载等事件,并更新
private void listenComponentApps() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); intentFilter.addAction(Intent.ACTION_MY_PACKAGE_REPLACED); intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED); intentFilter.addDataScheme(INTENT_FILTER_SCHEME); CC.getApplication().registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String packageName = intent.getDataString(); if (TextUtils.isEmpty(packageName)) { return; } if (packageName.startsWith(INTENT_FILTER_SCHEME)) { packageName = packageName.replace(INTENT_FILTER_SCHEME + ":", ""); } String action = intent.getAction(); CC.log("onReceived.....pkg=" + packageName + ", action=" + action); if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { REMOTE_CONNECTIONS.remove(packageName); } else { CC.log("start to wakeup remote app:%s", packageName); if (RemoteConnection.tryWakeup(packageName)) { ComponentManager.threadPool(new ConnectTask(packageName)); } } } }, intentFilter); }(2)查询所有安装的应用中支持CC组件的应用,并通过线程池定时查询该应用的 可供调用的Binder对象
class ConnectTask implements Runnable { String packageName; ConnectTask(String packageName) { this.packageName = packageName; } @Override public void run() { IRemoteCCService service = getMultiProcessService(packageName); if (service != null) { REMOTE_CONNECTIONS.put(packageName, service); } } } -
通过ContentResolver查询对应应用的RemoteProvider
private static IRemoteCCService getService(String processNameTo) { Cursor cursor = null; try { cursor = CC.getApplication().getContentResolver() .query(getDispatcherProviderUri(processNameTo) , RemoteProvider.PROJECTION_MAIN, null , null, null ); if (cursor == null) { return null; } return RemoteCursor.getRemoteCCService(cursor); } finally { if (cursor != null) { try { cursor.close(); } catch (Exception e) { CCUtil.printStackTrace(e); } } } } -
如果获取到Cursor,拿到该Cursor的bundle,并序列化为BinderWrapper,得到IBinder对象后,转换成IRemoteCCService接口对象。
public static IRemoteCCService getRemoteCCService(Cursor cursor) { if (null == cursor) { return null; } Bundle bundle = cursor.getExtras(); bundle.setClassLoader(BinderWrapper.class.getClassLoader()); BinderWrapper binderWrapper = bundle.getParcelable(KEY_BINDER_WRAPPER); if (binderWrapper != null) { IBinder binder = binderWrapper.getBinder(); return IRemoteCCService.Stub.asInterface(binder); } return null; } -
通过IRemoteCCService对象就可以执行跨进程调用对应应用上的组件
interface IRemoteCCService { void call(in RemoteCC remoteCC, in IRemoteCallback callback); void cancel(String callId); void timeout(String callId); String getComponentProcessName(String componentName); }