1、BridgeWebView开原地址
GitHub上的开源地址:https://github.com/open-android/BridgeWebView
1. 在project的build.gradle添加如下代码
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
2. 在Module的build.gradle添加依赖
compile 'com.github.open-android:BridgeWebView:v1.0'
3.布局文件中使用
<com.itheima.view.BridgeWebView
android:id="@+id/bdwebview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
4.Activity初始化通信桥梁
mBdwebview = (BridgeWebView) findViewById(R.id.bdwebview);//初始化BridgeWebView
mBdwebview.loadUrl("http://10.0.3.2:63343/BridgeWebView/index.html");//显示H5页面
mBdwebview.addBridgeInterface(new MyJavaSctiptInterface(mBdwebview, this));//注册桥梁类,该类负责H5和android通信
5.桥梁类提方法给js调用
public class MyJavaSctiptInterface{
private Activity mActivity;
public MyJavaSctiptInterface(Activity mActivity) {
this.mActivity = mActivity;
}
public void callPhone(String[] strs){//拨号
JSONObject jsonObject = new JSONObject(strs[0]);
String phone = jsonObject.optString("phone");
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone));
mActivity.startActivity(intent);
}
}
6.js中调用android方法
$("#btn1").on("click", function(){
var method = "callPhone";//js调用的android方法名
var params = {"phone":"10086", "callback":""};//callback用于回调js
callAndroidMethod(method, params);
});
/**
* 统一管理js调用安卓方法
* @param method 方法名
* @param params 向android传参数 数组格式
*/
var callAndroidMethod = function(method, params){
window.jsInterface.invokeMethod(method, [JSON.stringify(params)]);
}
2、接入webView
图片.png
图片.png
1、 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HelloAA"
tools:targetApi="31"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
添加的"android:usesCleartextTraffic="true"表示启用域名明文,支持http请求。
2、network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
3、WebView在使用setUserAgentString时的坑
在 Android 中,使用 setUserAgentString() 方法设置 WebView 的用户代理字符串是有效的。但是需要注意以下几点:
- 1、此方法必须在 WebView 加载网页之前调用,否则将不起作用。
- 2、如果您在加载网页之后调用此方法,则必须重新加载网页才能使更改生效。
- 3、请确保在调用此方法之前正确获取了 WebView 对象。如果您在没有实例化 WebView 的情况下调用此方法,它将无法正常工作。
以下是一个示例代码:
WebView webView = new WebView(context);
WebSettings webSettings = webView.getSettings();
webSettings.setUserAgentString("Your User Agent String");
webView.loadUrl("http://www.example.com");
请注意,在这个示例中,我们在设置用户代理字符串之前获取了 WebView 对象,并且在加载网页之前设置了用户代理字符串。如果您按照这个流程进行,那么 setUserAgentString() 就应该能够正常工作。
如果要追加设置
WebSettings settings = webView.getSettings();
String ua = settings.getUserAgentString();// 获取默认的UA
settings.setUserAgentString(ua + "; ****");// UA追加自定义标识符
4、webview设置setUserAgentString 之后,用Fiddler拦截器查看,发现User-Agent没有加上去
如果你在使用 setUserAgentString 方法设置 User-Agent 后,却无法在 Fiddler 中看到对应的 User-Agent 信息,可能是因为 WebView 在某些情况下会忽略该设置。以下是一些可能的原因:
- 1、User-Agent 设置不正确:请检查你使用 setUserAgentString 设置的字符串是否符合规范。
- WebView 缓存了旧的 User-Agent:尝试清除 WebView 的缓存并重新加载页面,或者使用 WebSettings.setUserAgentString(String userAgent) 方法来覆盖全局的 User-Agent 设置。
- 其他应用程序更改了 User-Agent:有些应用程序(如 VPN 或广告拦截器)可能会更改应用程序的 User-Agent,从而影响 WebView 的 User-Agent 设置。试着关闭这些应用程序并重新测试。
如果以上解决方法都没有成功,你可以尝试从代码层面上重置 User-Agent,具体方式如下:
webView.getSettings().setUserAgentString(null);
webView.getSettings().setUserAgentString("your custom user agent string");
5、net::ERR_UNKNOWN_URL_SCHEME错误
解决上述问题后,我重新安装了应用,结果应用在加载出网页后有马上出现了这个错误“net::ERR_UNKNOWN_URL_SCHEME……网页无法打开”。仔细观察报错页面,我发现“http/https://”协议变成了“baiduboxapp://utils?……”。
出现这种情况的原因是:WebView 只支持 http 和 https 协议,而我们的请求链接(url)在加载完成后却发生了变化。这种现象叫重定向。
解决办法:在创建 WebViewClient 对象时,通过重写 shouldOverrideUrlLoading(WebView view, String url)方法对会发生重定向的 url 进行拦截。以下是拦截的代码:
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
WebView.HitTestResult hit = view.getHitTestResult();
//hit.getExtra()为null或者hit.getType() == 0都表示即将加载的URL会发生重定向,需要做拦截处理
if (TextUtils.isEmpty(hit.getExtra()) || hit.getType() == 0) {
//通过判断开头协议就可解决大部分重定向问题了,有另外的需求可以在此判断下操作
Log.e("重定向", "重定向: " + hit.getType() + " && EXTRA()" + hit.getExtra() + "------");
Log.e("重定向", "GetURL: " + view.getUrl() + "\n" +"getOriginalUrl()"+ view.getOriginalUrl());
Log.d("重定向", "URL: " + url);
}
if (url.startsWith("http://") || url.startsWith("https://")) {//加载的url是http/https协议地址
view.loadUrl(url);
return false; //返回false表示此url默认由系统处理,url未加载完成,会继续往下走
} else { //加载的url是自定义协议地址
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
});
通过以上方法,应该就能正常使用WebView打开网页了。
6、我的完整代码
private fun initWebview() {
Log.d("lyy", "-----打开的网址:------url:${url}")
edit?.setText(url)
bdwebview?.loadUrl(url) //显示H5页面
bdwebview?.addBridgeInterface(
MyJavaSctiptInterface(
this@MainActivity
)
)
//支持JavaScript脚本
bdwebview?.getSettings()?.setJavaScriptEnabled(true);
bdwebview?.setWebViewClient(object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
val hit = view.hitTestResult
//hit.getExtra()为null或者hit.getType() == 0都表示即将加载的URL会发生重定向,需要做拦截处理
if (TextUtils.isEmpty(hit.extra) || hit.type == 0) {
//通过判断开头协议就可解决大部分重定向问题了,有另外的需求可以在此判断下操作
Log.e("重定向", "重定向: " + hit.type + " && EXTRA()" + hit.extra + "------")
Log.d("重定向", "URL: $url")
}
return if (url.startsWith("http://") || url.startsWith("https://")) { //加载的url是http/https协议地址
view.loadUrl(url)
false //返回false表示此url默认由系统处理,url未加载完成,会继续往下走
} else { //加载的url是自定义协议地址
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
}
true
}
}
})
}
class MyJavaSctiptInterface(private val mActivity: Activity) {
fun callPhone(strs: Array<String?>) { //拨号
val jsonObject = JSONObject(strs[0])
val phone = jsonObject.optString("phone")
val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:$phone"))
mActivity.startActivity(intent)
}
}









网友评论