1. 使用 WebView 加载 HTML 四种方式
//方式1:直接加载服务器对应的 URL
webView.loadUrl("http://baidu.com");
//方式2:加载开发项目资源文件夹下的 HTML 文件
webView.loadUrl("file:///android_asset/test.html");
//方式3:加载手机 sdcard 上的 HTML 文件
webView.loadUrl("content://com.ansen.webview/sdcard/test.html");
//方式4 使用 WebView 直接解析并显示 HTML 代码
webView.loadDataWithBaseURL(null
,"<html>
<head>
<title> 欢迎 </title>
</head>" +
"<body><h2>你可以使用 WebView 解析 HTML 源码</h2>
</body>
</html>"
, "text/html"
, "utf-8"
, null);
2. WebViewClient与WebChromeClient区别
WebViewClient主要帮助WebView处理各种通知、请求事件的,有以下常用方法:
- onPageFinished 页面请求完成
- onPageStarted 页面开始加载
- shouldOverrideUrlLoading 拦截url
- onReceivedError 访问错误时回调,例如访问网页时报错404,在这个方法回调的时候可以加载错误页面。
WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等,有以下常用方法。
- onJsAlert webview不支持js的alert弹窗,需要自己监听然后通过dialog弹窗
- onReceivedTitle 获取网页标题
- onReceivedIcon 获取网页icon
- onProgressChanged 加载进度回调
3. WebSettings 常用设置
webSettings.setJavaScriptEnabled //是否允许使用 JS
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//设置缓存方式,共有四种可选
- LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
- LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
- LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
- LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
webSettings.setBuiltInZoomControls(false); // 是否使用内置缩放机制
webSettings.setDisplayZoomControls(true); // 是否显示内置缩放控件
4. WebView 官方文档介绍
https://developer.android.google.cn/reference/android/webkit/WebView
5. 使用 WebView 需要权限
<uses-permission android:name="android.permission.INTERNET" />
6. 参考文档
https://www.jianshu.com/p/a6f7b391a0b8
https://blog.csdn.net/lowprofile_coding/article/details/77928614
7. WebView 示例代码
MainActivity
package com.demo.thorn.webviewdemo; import android.graphics.Bitmap; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.ProgressBar; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private WebView webView; private ProgressBar progressBar; private final static int KIND_1 = 1; private final static int KIND_2 = 2; private final static int KIND_3 = 3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); progressBar= findViewById(R.id.progressbar);//进度条 webView =findViewById(R.id.webview); initWebView(KIND_1);//加载 asset 文件夹下 html //initWebView(KIND_2);//加载 url //initWebView(KIND_3);//使用 webview 示 html } private void initWebView(int loadKind) { initWebViewSettings(); webView.addJavascriptInterface(this,"android");//添加js监听 这样 html 就能调用客户端 webView.setWebChromeClient(webChromeClient);//处理 JS 的弹窗操作 webView.setWebViewClient(webViewClient);//处理 JS 返回的结果 //选择加载模式 switch (loadKind){ case KIND_1: webView.loadUrl("file:///android_asset/test.html"); break; case KIND_2: webView.loadUrl("http://www.baidu.com/"); break; case KIND_3: webView.loadDataWithBaseURL(null,"<html><head><title> Welcome </title></head>" + "<body><h2>This is Your Body</h2></body></html>", "text/html" , "utf-8", null); break; default: break; } } private void initWebViewSettings() { WebSettings webSettings= webView.getSettings(); webSettings.setJavaScriptEnabled(true);//允许使用js /** * LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据 * LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。 * LOAD_NO_CACHE: 不使用缓存,只从网络获取数据. * LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。 */ webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//不使用缓存,只从网络获取数据. //支持屏幕缩放 webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(true); //不显示webview缩放按钮 webSettings.setDisplayZoomControls(false); } //WebViewClient主要帮助WebView处理各种通知、请求事件 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) {//页面开始加载 progressBar.setVisibility(View.VISIBLE); } @Override public void onPageFinished(WebView view, String url) {//页面加载完成 progressBar.setVisibility(View.GONE); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.i("jin","拦截 url:"+url); if(url.equals("http://www.google.com/")){ Toast.makeText(MainActivity.this,"国内不能访问google,拦截该 url ",Toast.LENGTH_LONG).show(); return true;//表示我已经处理过了 } return super.shouldOverrideUrlLoading(view, url); } }; //WebChromeClient 主要辅助 WebView 处理 Javascript 的对话框、网站图标、网站 title 、加载进度等 private WebChromeClient webChromeClient=new WebChromeClient(){ //不支持js的alert弹窗,需要自己监听然后通过dialog弹窗 @Override public boolean onJsAlert(WebView webView, String url, String message, JsResult result) { AlertDialog.Builder localBuilder = new AlertDialog.Builder(webView.getContext()); localBuilder.setMessage(message).setPositiveButton("确定",null); localBuilder.setCancelable(false); localBuilder.create().show(); //注意: //必须要这一句代码:result.confirm()表示: //处理结果为确定状态同时唤醒WebCore线程 //否则不能继续点击按钮 result.confirm(); return true; } //获取网页标题 @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); Log.i("jin","网页标题:"+title); } //加载进度回调 @Override public void onProgressChanged(WebView view, int newProgress) { progressBar.setProgress(newProgress); } }; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { Log.i("jin","是否有上一个页面:"+webView.canGoBack()); if (webView.canGoBack() && keyCode == KeyEvent.KEYCODE_BACK){//点击返回按钮的时候判断有没有上一页 webView.goBack(); // goBack()表示返回webView的上一页面 return true; } return super.onKeyDown(keyCode,event); } /** * JS 调用 android 的方法 * @param str * @return */ @JavascriptInterface //仍然必不可少 public void getClient(String str){ Log.i("jin","客户端接收到了数据:"+str); } @Override protected void onDestroy() { super.onDestroy(); //释放资源 webView.destroy(); webView=null; } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.demo.thorn.webviewdemo.MainActivity"> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent"/> <ProgressBar android:id="@+id/progressbar" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="3dip" android:max="100" android:progress="0" android:visibility="gone"/> </android.support.constraint.ConstraintLayout>
test.html (文件路径:WebViewDemo\app\src\main\assets\test.html)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>这里是标题! </title> <style type="text/css"> dd { margin-top:30px; /* 上外边距30像素 */ } </style> </head> <body> <div id="wrap"> <div id="header"><h1>这里是 Header </h1> </div> <div id="main"> <dl> <dd><a href="http://www.baidu.com">点击跳转到百度</a></dd> <dd><a href="http://www.google.com">点击跳转到google</a></dd> <dd> <button id='callback_client' onclick="callBackClient()" type="button">用 js 调用客户端中的方法 </button> </dd> </dl> </div> </body> <script> function callBackClient(){ alert("调用客户端的 getClient 方法,并传递了数据");//弹窗 javascript:android.getClient("WebView 中传递的数据");//调用客户端的 getClient 方法,并传递了数据 } </script> </html>