一、简述原理:html -> web进程 -> app主进程 -> 回调到web进程
通过广播,也可以直接 app主进程 -> web进程
1、html->web进程,这一步不用说了,webview.addJavascriptInterface(obj, "webview");
2、web进程 -> app主进程 通过aidl实现
3、app主进程 -> 回调到web进程 也是通过aidl接口实现
4、广播本身跨进程的
5、为了让组件中供web调用的 JsInterface 与业务分离,增加了一个H5Bridge.getInstance().register(JsInterfaceImpl.class)
H5Bridge内部解析JsInterfaceImpl.class的所有方法,缓存到map里,web进程接收到web请求时,把web请求的数据通过aidl传到主进程,然后主进程中根据web传回的数据,从H5Bridge的map缓存中找到对应的方法,通过反射调用执行,执行后通过传入AidlCallback接口回调到子进程。
6、web端的调用
webview.jsFunc("methodName", "{'key':'value', 'key2':'value2'}")
webview是addJavascriptInterface(, "webview")中定义的别名
jsFunc()是中转接口中@JavascriptInterface注解的统一接收web调用的函数名
methodName是客户端与web端协商的调用的方法名,第二个参数是该方法调用需要的参数
二、具体实现:
1、首先要定义两个aidl接口(注意aidl文件所在包名)
//主进程的服务返回给子进程的Binder管理器,该管理器本身也是Binder,通过它可以获取对应业务的Binder
IBinderManager.aidl
//用于h5子进程连接主进程成功后,由主进程返回给子进程的Binder,子进程可通过该binder来调用主进程中的方法
IWebBinder.aidl
//用于h5子进程调用的主进程方法执行完毕时,回调给子进程,让子进程做相应处理的Binder
IWebBinderCallback.aidl
2、编写aidl的实现
/**
* Binder管理器
*/
public class BinderManager extends IBinderManager.Stub {
public static final int BINDER_WEB_AIDL = 1;//h5进程请求主进程
private Context context;
public BinderManager(Context context) {
this.context = context;
}
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode) {
case BINDER_WEB_AIDL: {
binder = new WebBinderInterface(context);
break;
}
default:
break;
}
return binder;
}
}
/**
* 主进程中,封装了给h5进程调用的接口
*/
public class WebBinderInterface extends IWebBinder.Stub {
private Context context;
public WebBinderInterface(Context context) {
this.context = context;
}
@Override //处理web进程中h5页面穿过来的事件
public void handleJsFunction(String methodName, String params, IWebBinderCallback callback) throws RemoteException {
int pid = android.os.Process.myPid();
Logger.d(WebRemoteControl.TAG , String.format("=======WebBinderInterface.handleJsFunction(methodName:(%s) params:(%s)", pid, methodName, params));
try {
H5Bridge.getInstance().callJava(methodName, params, callback);
} catch (Exception e) {
e.printStackTrace();
}