# 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将被处理跳转,否则不做处理