# WebViewBridge **Repository Path**: CrossRun/webviewbridge ## Basic Information - **Project Name**: WebViewBridge - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-10-13 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WebappCommon # 项目介绍 提供Android原生和H5交互的能力,WebViewBridge ,从网上学习了很多,基本的原理都是一样,通过url传递参数,然后调用js返回。本项目不直接提供封装好的WebView,是因为想要更好的扩展性,封装好的WebView在需要处理一些url的场景,就很麻烦甚至无法做到。涉及到具体的一些方法,本项目也不提供,有很多优秀项目可以实现二维码,选取图片,定位等等功能,不再重复。 # 使用方法 下列步骤中,有的步骤会提供多个选择,只许任选其一即可。 ### 步骤一:实例化一个 `BridgeJSEval` 如果用的是Android原生的WebView,只需要使用 RawJSEval 即可,
如果使用的是 腾讯X5内核或者其他的,需要自己继承`BridgeJSEval` 里面的代码模仿 RawJSEval 引用改一下就行了 ### 步骤二:实例化一个`BridgeHelper` 选择1,构造方法直接传入 当前Activity和步骤一的BridgeJSEval ```java bridgeHelper = new BridgeHelper(activity,new RawJSEval(webView)); ``` 选择2,自己实例化一个WebViewBridgePluginManager,可以使用项目中的WebViewBridgePluginManagerAdapter,WebViewBridgePluginManagerAdapter 需要传入步骤一的BridgeJSEval,同时重写 getActivityContext 这个方法,返回Activity。 ```java bridgePluginInterfaceAdapter = new BridgePluginInterfaceAdapter(new RawJSEval(webView)) { @Override public Activity getActivityContext() { return WebViewActivity.this; } }; bridgeHelper = new BridgeHelper(bridgePluginInterfaceAdapter); ``` ### 步骤三:插入 WebViewClient 里面 注意!注意!注意!根据自己实际需求,判断是否使用 BridgeUtil.decode2UTF8() 有时候传入的参数包含中文,如果直接使用,url里面会有类似乱码的东西,需要这个帮助转换。
bridgeHelper.shouldOverrideUrlLoading 这个方法可以只传入url,也可以传入url和flag,如果,flag=true 将会自动判断通过url是否可以打开手机里的某些应用,可以打开就将会自动打开。 ```java webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (bridgeHelper.shouldOverrideUrlLoading(BridgeUtil.decode(url))){ return true; } //todo som return super.shouldOverrideUrlLoading(view, url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); bridgeHelper.onPageFinished(url); } }); ``` ### 步骤四,编写插件方法 选择1,继承WebViewBridgePlugin ```java public class TestPlugin extends WebViewBridgePlugin { @Override public void handlerBridgeMsg(String msg, BridgeCallBackFunction callBackFunction) { Toast.makeText(getContext(), msg, Toast.LENGTH_LONG).show(); callBackFunction.onCallBackFunction(Calendar.getInstance().getTime().toString()); } } ``` 选择2,继承WebViewBridgePluginWithActivityLife 这个会在Activity发生生命周期变化的时候同时调用,需要自己重写 Activity 生命周期,并调用 bridgeHelper 相应的方法。对Activity生命周期敏感以及需要 onRequestPermissionsResult 和 onActivityResult ,必须继承WebViewBridgePluginWithActivityLife,一定别忘了需要自己重写 Activity 生命周期,并调用 bridgeHelper 相应的方法。 ```java public class TestPlugin extends WebViewBridgePluginWithActivityLife { @Override public void handlerBridgeMsg(String msg, BridgeCallBackFunction callBackFunction) { Toast.makeText(getContext(), msg, Toast.LENGTH_LONG).show(); callBackFunction.onCallBackFunction(Calendar.getInstance().getTime().toString()); } @Override public void onResume() { Log.e("console","onResume"); } @Override public void onPause() { Log.e("console","onPause"); } } ``` 无论选择那种方法,请根据自己需要重写 getPluginName 这个方法,返回你的插件名称,插件名称是js调用的依据。 ### 步骤五:注册方法供Js调用 选择1,只传入调用名称和class,只适用于无构造参数的,有些插件没必要初始化时候加载。请注意,务必保证传入的插件名称 和 getPluginName 返回的名称一致。 ```java bridgeHelper.pluginRegister("test", TestPlugin.class); ``` 选择2,传入实例化以后的插件 ```java bridgeHelper.pluginRegister(new TestPlugin()); ``` ### 步骤六,调用js方法 例子如下,在需要的时候调用即可 ```java bridgeHelper.callHandler("tohtml" , json.toString() , new BridgeCallBackFunction() { @Override public void onCallBackFunction(String msg) { Log.e("console", "Android | callHandler = " + BridgeUtil.decode(msg)); } }); ``` # 软件架构 ## WebViewBridgeHandler 核心的插件执行方法,最终都会是执行到这里 #### WebViewBridgePlugin 插件方法的包装,会有一些封装好的方法
`getRequestCode` :类似 `startActivityForResult()`,`requestPermissions()` 这些方法中需要一个`requestCode`,为了防止code冲突,通过这个方法获取一个累加的code,建议在需要的插件里面,每次初始化的时候,提前申请好code保存下来使用 `needContext` :为了防止内存溢出,Activity回收等情况,在每次执行方法前都会判断下Context是否还存在,如果不需要,在构造方法里面传入false即可 `getPluginName` :获取插件的名称,不重写的话,默认class类名同时把第一个字母改成小写 ## WebViewBridgePluginManager 插件的管理类,统一管理插件,包括生命周期,权限申请回调等等,负责返回申请的`requestCode`。 #### WebViewBridgePluginManagerAdapter 插件管理类的一个内置的实现类,可以直接使用,只需要重新`getActivityContext`返回一个`Activity`即可。 ## BridgeJSEval 对`WebView`的一些操作,由于有的项目用的是原生,有的用的是腾讯X5,所以本项目不绑定webview,通过此接口实现对`WebView`的交互。 #### RawJSEval `BridgeJSEval`的关于系统自带`WebView`的一个实现类。 ## BridgeHelper 入口,最基本用法实例化只许传入`Activity`和`BridgeJSEval`。根据自己的需要,是否在`Activity`生命周期里调用。最好在`onDestory`里面调用以防止内存泄漏 ```java bridgePluginInterfaceAdapter = new BridgePluginInterfaceAdapter(new RawJSEval(webView)) { @Override public Activity getActivityContext() { return WebViewActivity.this; } //可以重写这个方法引入自己的webbridge.js @Override public String getBridgeJS() { return BridgeUtil.assetFile2Str(WebViewActivity.this, "b.js"); // return BJS.js; } }; bridgeHelper = new BridgeHelper(bridgePluginInterfaceAdapter); bridgeHelper.registerHandler("test", TestPlugin.class);//注册时候不会实例化类,调用的时候才会 //引入自己的bridge.js 的话,看情况是否需要设置成自定义的头 // bridgeHelper.setkCustomProtocolScheme(); // bridgeHelper.setkCustomreturnHost(); // bridgeHelper.setkQueueHasMessage(); ``` ```java bridgeHelper = new BridgeHelper(this,new RawJSEval(webView)); ``` 最大的优点就是入侵小,只需要在如下使用即可,有些项目有自己的其他逻辑,可以自行处理。 ```java webView.setWebViewClient(new WebViewClient() { // @Override // public boolean shouldOverrideUrlLoading(WebView view, String url) { // if (!bridgeHelper.shouldOverrideUrlLoading(url)){ // //自己的业务逻辑 // } // return true; // } // @Override // public boolean shouldOverrideUrlLoading(WebView view, String url) { // return bridgeHelper.shouldOverrideUrlLoading(url); // } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); bridgeHelper.onPageFinished(url); } }); ``` 上面被注释两种方法都行,使用时需要选择一种,`shouldOverrideUrlLoading`返回true代表此请求由本项目的交互过程处理了,`shouldOverrideUrlLoading`可以传入`(url)`也可以传入`(url,flag)`,`flag=true`的时候,有些可以当作跳转intent的url将被处理跳转,否则不做处理