1.WebView的初始化
WebView mWebView =(WebView)findViewById(R.id.show_webView);
mWebView.loadUrl(Consts.WEB_URL_BAIDU); // WEB_URL_BAIDU =“https://www.baidu.com/” ```
2.WebView的三个基本组件
2.1WebSettings(做各种设置)
- 获取设置
WebSettings webSettings = mWebView .getSettings();
- 常见设置:
// JS处理
setJavaScriptEnabled(true); //支持JS
setPluginsEnabled(true); //支持插件
setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口//缩放处理setUseWideViewPort(真); //将图片调整到适合网页流量的大小setLoadWithOverviewMode(true); //缩放至屏幕的大小setSupportZoom(真); //支持缩放,默认为真。是下面那个的前提。
setBuiltInZoomControls(true); //设置内置的缩放控件。这个取决于setSupportZoom(),若setSupportZoom(false),则该WebView不可缩放,这个不管缩放,什么都不能缩放。
setDisplayZoomControls(false); //隐藏原生的缩放控件
//内容布局
setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局
supportMultipleWindows(); //多窗口
//文件缓存
setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭网页视图中缓存
setAllowFileAccess(true); //设置可以访问文件
//其他设置
setNeedInitialFocus(true); //当的WebView调用requestFocus的时为网页流量设置节点
setLoadsImagesAutomatically(true); //支持自动加载图片
setDefaultTextEncodingName(“UTF-8”); //设置编码格式
setPluginState(PluginState.OFF); //设置是否支持闪存插件
setDefaultFontSize(20); //设置默认字体大小
2.2WebViewClient
- 处理各种请求通知事件
- 应该覆盖UrlLoading(WebView视图,字符串url)//在网页上的所有加载都经过这个方法,这个函数我们可以做很多操作。比如获取url,查看url.contains(“add”),进行添加操作
//应该覆盖UrlLoading(WebView视图,字符串url)//在网页上的所有加载都经过这个方法,这个函数我们可以做很多操作。比如获取url,查看url.contains(“add”),进行添加操作
shouldOverrideKeyEvent(WebView视图,KeyEvent事件)//处理在浏览器中的按键事件。
onPageStarted(WebView视图,字符串url,位图图标)/ /开始载入页面调用,我们可以设置一个加载的页面,告诉用户程序在等待网络响应。
onPageFinished(WebView视图,String url)//在页面加载结束时调用,我们可以关闭加载条,切换程序动作。
onLoadResource(WebView视图,String url)//在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
onReceivedError(WebView视图,int错误码,字符串描述,String failingUrl)//报告错误信息
doUpdateVisitedHistory(WebView视图,String url,布尔isReload)//更新历史记录
onFormResubmission(WebView视图,Message dontResend,Message重发)//应用程序重新请求网页数据
onReceivedHttpAuthRequest(WebView视图,HttpAuthHandler处理函数,String主机,String领域//获取返回信息授权请求
onReceivedSslError(WebView视图,SslErrorHandler处理程序,SslError错误)//让webview处理https请求。
onScaleChanged(WebView视图,float oldScale,float newScale)// WebView发生改变时调用
onUnhandledKeyEvent(WebView视图,KeyEvent事件)// Key事件未被加载时调用
2.3WebChromeClient
- 帮助webview处理js对话框,网址图标,网址标题,网址进度
- public void onProgressChanged(WebView view,int newProgress); //获得网页的加载进度,显示在右上角的的TextView控件中
- 公共无效onReceivedTitle(WebView视图,字符串标题); //获取网页中的标题用户设置自己界面中的标题,当加载出错的时候,比如无网络,这时onReceiveTitle中获取的标题为“找不到该网页”
- public void onReceivedIcon(WebView视图,位图图标); //获取的Web页中的图标
- 公共布尔onCreateWindow(WebView视图,布尔isDialog,布尔isUserGesture,消息resultMsg);
- public void onCloseWindow(WebView window);
- 公共布尔onJsAlert(WebView视图,字符串url,字符串消息,JsResult结果); //处理警告弹出框,html弹框的一种方式
- public boolean onJsPrompt(WebView view,String url,String message,String defaultValue,JsPromptResult result)//处理确认弹出框
- public boolean onJsConfirm(WebView视图,String url,String消息,JsResult结果); //处理提示弹出框
3.WebView页面导航
3.1页面跳转
- 设置WebViewClient,如果要跳转不同链接,需要自定义WebViewClient,重写shouldOverrideUrlLoading()
3.2页面回退
- 重写onKeyEvent()方法
3.3页面滑动
- 获取网页高度
3.4WebView,WebViewClient,WebChromeClient三者的区别
- WebView:主要负责解析和渲染网页
- WebViewClient:辅助WebView处理各种通知 & 请求事件
- WebChromeClient :辅助WebView处理 Javascript 的对话框,网站图标,网站标题等等
- 下面是小例子:
- activity_web.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00999999"
android:theme="@style/AppTheme"
tools:context="com.sunny.app.itjuzi_learn.webview.controller.WebActivity">
<include layout="@layout/layout_webview"/>
</RelativeLayout>
- layout_webview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white">
<!-- 加载进度条 -->
<ProgressBar
android:id="@+id/load_progressbar"
android:layout_width="match_parent"
android:layout_height="3dp"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:progressDrawable="@drawable/bar_color"
android:max="100" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp">
<!-- 获取网站的图标 -->
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 获取网站的标题-->
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@color/black"
android:text="THIS IS WEB TITLE"/>
</LinearLayout>
<!--<LinearLayout-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content"-->
<!--android:orientation="horizontal"-->
<!--android:gravity="right">-->
<!--<!–开始加载提示–>-->
<!--<TextView-->
<!--android:id="@+id/beginloading_txt"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:textSize="12sp"-->
<!--android:textColor="@color/com_claim_txt"-->
<!--android:text=""/>-->
<!--<!–获取加载进度–>-->
<!--<TextView-->
<!--android:id="@+id/loading_txt"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content"-->
<!--android:textSize="12sp"-->
<!--android:textColor="@color/grey"-->
<!--android:text=""/>-->
<!--<!–结束加载提示–>-->
<!--<TextView-->
<!--android:id="@+id/endloading_txt"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:textSize="12sp"-->
<!--android:textColor="@color/com_claim_txt"-->
<!--android:text=""/>-->
<!--</LinearLayout>-->
<!--显示网页区域-->
<WebView
android:id="@+id/show_webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="1dp"
/>
</LinearLayout>
- WebActivity.class
package com.sunny.app.itjuzi_learn.webview.controller;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.sunny.app.itjuzi_learn.R;
import com.sunny.app.itjuzi_learn.url.Consts;
/**
* webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 意思是:关闭webview中缓存
*/
public class WebActivity extends AppCompatActivity {
// private static final String APP_CACHE_DIRNAME = "/cache";
private WebView mWebView;
private WebSettings mWebSettings;
private ImageView mIcon;
private TextView mBeginLoading, mEndLoading, mLoading, mTitle;
private ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//显示进度条
requestWindowFeature(Window.FEATURE_PROGRESS); //带进度
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); //不带进度
setContentView(R.layout.activity_web);
mIcon = findViewById(R.id.icon);
mTitle = findViewById(R.id.showTitle);
// mBeginLoading = findViewById(R.id.beginloading_txt);
// mLoading = findViewById(R.id.loading_txt);
// mEndLoading = findViewById(R.id.endloading_txt);
mWebView = findViewById(R.id.show_webView);
mProgressBar = findViewById(R.id.load_progressbar);
mWebSettings = mWebView.getSettings();
// 设置缓存行为
// mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //优先使用缓存(只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。)
// mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ONLY); //不使用网络,只从本地缓存数据中读取
// mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); //(默认)根据cache-controller决定是否从网上加载数据
// mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); //不使用缓存
// 结合使用(离线加载)
// if (NetStatusUtil.isConnected(getApplicationContext())) {
// mWebSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根据cache-control决定是否从网络上取数据。
// } else {
// mWebSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//没网,则从本地获取,即离线加载
// }
//
// 设置缓存路径(路径:data/data/包名)
// String cacheDirPath = getCacheDir().getAbsolutePath() + APP_CACHE_DIRNAME;
// mWebSettings.setAppCachePath(cacheDirPath); //设置 Application Cache 目录
//关闭webview中缓存
// webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//websetting配置
mWebSettings.setJavaScriptEnabled(true); //设置该属性支持与js交互
mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
//支持插件
// mWebSettings.setPluginState(WebSettings.PluginState.ON); //适用于8<api<19,api=19时被弃用
// mWebSettings.setPluginEnable(true); //适用于api<8(当api>18时可能被隐藏或删除,编译时会报错)
mWebSettings.setDomStorageEnabled(true); //开启 DOM storage API 功能
mWebSettings.setDatabaseEnabled(true); //开启 database API 功能
// mWebSettings.setAppCacheEnabled(true); //开启 Application cache 功能
// //设置自适应屏幕,两者合用
mWebSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
mWebSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
//
缩放操作
mWebSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
mWebSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
// webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
//
其他细节操作
mWebSettings.setAllowFileAccess(true); //设置可以访问文件
mWebSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
mWebSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
//防止webView内存泄露(不在XML中定义webview,在Activity中需要时定义)
// LinearLayout linearLayout = new LinearLayout(this);
// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
// mWebView = new WebView(getApplicationContext());
// mWebView.setLayoutParams(params);
// linearLayout.addView(mWebView);
//cookei一定设置在loadUrl()之前
mWebView.loadUrl(Consts.WEB_URL_VIP);
//设置不用系统浏览器打开,直接显示在当前WebView中(只有没有setWebViewClient的时候才会调用系统的浏览器加载页面,而并不是重写WebViewClient的shouldOverrideUrlLoading()方法)?
//设置webviewClient类
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//网页版支付宝支付时需打开客户端支付,这时会有一个appliyid会携带支付信息,此时截断不使用view加载数据,而使用intent打开手机客户端(http://blog.csdn.net/chendong_/article/details/75152321)
//如果不使用intent加载数据就走原来
// if (!shouldOverrideIntentUrl(getContext(), url)) {
view.loadUrl(url, Api.makeHttpHeaders(getContext())); intent
// }
//由于WebView只能处理http,https开头的网页,就会导致其余网页打不开,需对其进行转化
try {
if (url == null) return false;
if (url.startsWith("http:") || url.startsWith("https:")) {
view.loadUrl(url); //view加载数据
return true;
} else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
} catch (Exception e) {
return false;
}
//返回值为true利用WebView打开,为false调用系统或第三方浏览器打开
// return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// super.onPageStarted(view, url, favicon);
// mBeginLoading.setText("开始加载了");
Log.d("WebActivity", "开始加载了");
}
//加载结束
@Override
public void onPageFinished(WebView view, String url) {
// super.onPageFinished(view, url);
// mEndLoading.setText("加载完成");
Log.d("WebActivity", "加载完成了");
}
//加载页面资源时会调用,每加载一个资源(比如图片)调用一次
@Override
public void onLoadResource(WebView view, String url) {
// super.onLoadResource(view, url);
// 设定加载资源的操作
}
/**
* WebView如何加载本地页面(加载页面出现404时,需要给用户展示一个相对美观本地的页面)
* 步骤:
* 1:写一个html文件(error_handle.html),用于出错时展示给用户看的提示页面
* 2:将该html文件放置到代码根目录的assets文件夹下
* 3:复写WebViewClient的onRecievedError方法
* @param view
* @param errorCode
* @param description
* @param failingUrl
*/
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// switch (errorCode) {
// case HttpStatus.SC_NOT_FOUND:
// view.loadUrl("file:///android_assets/error_handle.html");
// break;
// }
Log.d("WebActivityError", errorCode + ",\n" + description + ",\n" + failingUrl);
}
/**
* @param request
* @param error
*/
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
// super.onReceivedError(view, request, error);
Log.d("WebActivity", error + "");
}
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
Log.d("WebActivity:", errorResponse + "");
}
/**
* 处理Https请求:webView默认不处理Https请求的,页面显示空白,需要进行如下处理
* @param view
* @param handler
* @param error
*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed(); //等待证书响应
// handler.cancel(); //表示挂起连接,为默认方式
// handler.handleMessage(null); //做其他处理
}
});
mWebView.setWebChromeClient(new WebChromeClient() {
//获取网站标题
@Override
public void onReceivedTitle(WebView view, String title) {
// super.onReceivedTitle(view, title);
// mTitle.setText(title);
Log.d("WebActivity", "标题为:" + mTitle + "," + title);
}
//获取网站图标
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
mIcon.setImageBitmap(icon);
Log.d("WebActivity", "网页图标:" + icon.toString());
}
//获取加载进度
@Override
public void onProgressChanged(WebView view, int newProgress) {
// super.onProgressChanged(view, newProgress);
if (newProgress == 100) {
mProgressBar.setVisibility(View.GONE);
} else {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setProgress(newProgress); //设置进度值
}
// if (newProgress < 100) {
// String progress = newProgress + " % ";
// mLoading.setText(progress);
// } else if (newProgress == 100) {
// String progress = newProgress + "%";
// mLoading.setText(progress);
// }
// Log.d("WebActivity", "加载进度为:" + newProgress);
}
});
}
/**
* 使用intent拦截url打开应用(支付宝)???
* 目的:换起某些应用内部暴露的APP页面
*/
// private static final String ALIPAY_SCHEME = "alipays";
//
// public static boolean shouldOverrideIntentUrl(AccessControlContext context, String url) {
// Uri uri = Uri.parse(url);
// if (uri != null
// && uri.getScheme() != null
// && uri.getScheme().equals(ALIPAY_SCHEME)) {
// try {
// Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
// intent.addCategory(Intent.CATEGORY_BROWSABLE);
// intent.setComponent(null);
// intent.setSelector(null);
context.startActivity(intent); //??????
// } catch (Exception e) {
// e.printStackTrace();
// if (e instanceof ActivityNotFoundException) {
ToastUtil.show("未检测到支付宝客户端");
// }
// return true;
// }
// return true;
// }
// return false;
// }
//点击返回上一页面而不是退出浏览器
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) { //是否可以后退
//webView后退网页
mWebView.goBack();
//前进网页
// mWebView.goForward();
return true;
}
return super.onKeyDown(keyCode, event);
//点击返回,弹出提示
// if (keyCode == KeyEvent.KEYCODE_BACK){
// MyToast toast =new MyToast(this);
// toast.makeText(this,"退出",0);
// }
// return false;
}
//销毁Activity时,webView需要加载(null),移除,销毁,置空
@Override
protected void onDestroy() {
super.onDestroy();
if (mWebView != null) {
mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
//清除webview所有历史缓存,除了当前访问记录缓存
mWebView.clearHistory();
//这个api仅仅清除自动完成填充的表单数据,并不会清除webview缓存到本地的数据
mWebView.clearFormData();
//全局的内核缓存,清除的是整个整个应用程序缓存
mWebView.clearCache(true);
((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.destroy();
mWebView = null;
} else {
Log.d("WebActivity", "WebView为null'");
}
}
}
3.5WebViewClient成员方法
- shouldOverrideUrlLoading拦截的是url加载阶段,主要拦截url(网页自动重定向或手动点击网页内部链接时执行)
- shouldInterceptRequest加载的是响应主体阶段,可拦截url,js,css(拦截内部的资源加载,例如HTML或Script标签中的iframe 或 src 属性、XmlHttpRequests等)
3.6注入js
https://cloud.tencent.com/developer/article/1953091?from=15425
4.WebView缓存
在项目中如果使用到WebView控件, 当加载html页面时, 会在/data/data/包名目录下生成database与cache两个文件夹。
请求的url记录是保存在WebViewCache.db, 而url的内容是保存在WebViewCache文件夹下
4.1设置缓存
- 控制缓存行为
//设置缓存行为
/优先使用缓存(只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。)
mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);/
mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ONLY); //不使用网络,只从本地缓存数据中读取
//(默认)根据cache-controller决定是否从网上加载数据
mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); //不使用缓存
//结合使用(离线加载)
if (NetStatusUtil.isConnected(getApplicationContext())) {
mWebSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根据cache-control决定是否从网络上取数据。
} else {
mWebSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//没网,则从本地获取,即离线加载
}
//设置缓存路径(路径:data/data/包名)
String cacheDirPath = getCacheDir().getAbsolutePath() + APP_CACHE_DIRNAME;
- 关闭缓存
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
4.2清除缓存
- 方法
//清除webview所有历史缓存,除了当前访问记录缓存
mWebView.clearHistory();
//这个api仅仅清除自动完成填充的表单数据,并不会清除webview缓存到本地的数据
mWebView.clearFormData();
//全局的内核缓存,清除的是整个整个应用程序缓存
mWebView.clearCache(true);
5.WebCookies
- 个人理解Cookie:
- Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式。
- 由服务器端生成浏览器缓存的一些小量信息,session的使用离不开它。
- 收集整合用户信息,应用于用户在不同页面同步购物车商品。
- 典型应用:判定用户是否已登录网站
- 推荐链接:http://blog.csdn.net/jdsjlzx/article/details/44630187
5.1设置Cookies
- 更新中…
......
5.2清除Cookies
- 更新中…
6.WebView访问本地资源
- 注意:
从网络上下载html的过程应放在工作线程中
html下载成功后渲染出html的步骤应放在UI主线程,不然WebView会报错
html下载失败则可以使用我们前面讲述的方法来显示自定义错误界面 - 参考链接:http://blog.csdn.net/carson_ho/article/details/52693322
7.WebView问题
7.1页面空白问题
- ScroolView嵌套WebView空白:重新计算WebView高度 和 其他参考
- Websettings缺少设置:开启Dom本地存储
webSettings.setDomStorageEnabled(true);
- https与http混用:启用设置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); }