Android组件之WebView

基本步骤

联网的权限android.permission.INTERNET

如果访问的页面中有Javascript,则webview必须设置支持Javascript。

webview.getSettings().setJavaScriptEnabled(true);

加载基本的url

// 创建WebView在onCreate()中
WebView webview = new WebView(this);
setContentView(webview);
Uri uri = Uri.parse("http://www.example.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

加载内容

//方式一
webview.loadUrl("http://slashdot.org/");
//方式二
webview.loadData (htmlText, "text/html","utf-8/gbk")
//方式三
webview.loadDataWithBaseURL(baseUrl,htmlText,"text/html", 
        "utf-8/gbk",historyUrl)

设置WebChromeClientsetWebChromeClient()

WebChromeClient是辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等
	onCloseWindow(关闭WebView) 
	onCreateWindow() 
	//javascript警告对话框显示 返回true/false
	onJsAlert() 
	//提示对话框 返回true/false
	onJsPrompt 
	//确认对话框 返回true/false
	onJsConfirm 
	//当前页面的加载进度
	onProgressChanged
	//通知主机应用程序的新的标识当前页面 
	onReceivedIcon 
	//通知主机应用程序的文档标题的改变
	onReceivedTitle

设置WebViewClientset WebViewClient()

帮助WebView处理各种通知、请求事件
	//更新历史记录
	doUpdateVisitedHistory() 
	//重新请求网页数据默认不重新发送
	onFormResubmission() 
	//加载给定的url指定的资源。
	onLoadResource() 
	//在页面加载开始时调用
	onPageStarted()
	//在页面加载结束时调用
	onPageFinished() 
	//报告错误信息 主要的资源不可用
	onReceivedError()
	//设置WebView对请求的回应 默认行为是取消请求。
	onReceivedHttpAuthRequest() 
	//从服务器接收到HTTP错误一直在加载资源。HTTP错误状态码> =400
	onReceivedHttpError()
 	//SSL错误加载资源时发生 默认行为是取消负载。
	onReceivedSslError() 
 	//WebView发生改变时调用
	onScaleChanged()
	//重写此方法才能够处理在浏览器中的按键事件。
	//返回true/false,true需要对事件进行处理 默认行为返回false。
	shouldOverrideKeyEvent() 
	//在点击请求的是链接是才会调用,重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。
	//提供WebViewClient时,返回true由应用程序进行处理url,返回false当前WebView处理url
	shouldOverrideUrlLoading(WebView view, String url) 

WebView的WebSettings

	WebSettings webSettings = webView.getSettings();
	//支持js 	
	setJavaScriptEnabled(true);  
	//设置支持缩放
 	setBuiltInZoomControls(true); 
	//支持缩放
	setSupportZoom(true);
	//设置缓存模式	
	setCacheMode();
	//将图片调整到适合webview的大小
	setUseWideViewPort(false); 
	//缩放至屏幕的大小
	setLoadWithOverviewMode(true);
	//支持插件
	setPluginsEnabled(true);  
	//是否支持多个窗口。
	supportMultipleWindows();
	//支持内容重新布局  
	setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); 
	//设置可以访问文件   
	setAllowFileAccess(true);  
 	//当webview调用requestFocus时为webview设置节点 默认true
	setNeedInitialFocus(true); 	 
	//支持通过JS打开新窗口 
	setJavaScriptCanOpenWindowsAutomatically(true);
	//支持自动加载图片
	setLoadsImagesAutomatically(true);  

更多设置

	 //当前加载的进度
	 getProgress ()
	 //当前加载地址的标题
	 getTitle ()
	 //停止加载 
	 stopLoading()
	 //重新加载
	 reload()
	 //视图滚动的内容这通常是由于scrollBy(int,int)scrollTo(int,int)被调用
	 onScrollChanged()

如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象。

mWebView.setWebViewClient(new WebViewClient()
	{    
    public boolean shouldOverrideUrlLoading(WebView view, String url) {    
             view.loadUrl(url);    
             return true;    
         }    
    }); 

如果希望浏览的网页回退而不是退出浏览器,需要在当前Activity中处理并消费掉该Back事件。

public boolean onKeyDown(int keyCode, KeyEvent event) 
	{    
       if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {    
            mWebView.goBack();    
            return true;    
        }    
    return super.onKeyDown(keyCode, event);    
 }

如果希望WebView可以支持Javascript

  class JsObject {
   {@literal @}JavascriptInterface
      public String toString() { return "injectedObject"; }
   }
   webView.addJavascriptInterface(new JsObject(), "injectedObject");
   webView.loadData("<!DOCTYPE html><title></title>", "text/html", null);
    webView.loadUrl("javascript:alert(injectedObject.toString())");

举个栗子

local.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
<script type="text/javascript">
	function javacalljs() {
		document.getElementById("content").innerHTML += "<br\>java调用了js函数";
	}

	function javacalljswithargs(arg) {
		document.getElementById("content").innerHTML += ("<br\>" + arg);
	}
</script>
</head>
<body>
	this is my html
	<br />
	<a onClick="window.wst.startFunction()">点击调用java代码</a>
	<br />
	<a onClick="window.wst.startFunction('hello world')">点击调用java代码并传递参数</a>
	<br />
	<div id="content">内容显示</div>
</body>
</html>

Java 
public class MainActivity extends Activity {

	private WebView contentWebView = null;
	private TextView msgView = null;

	@SuppressLint("SetJavaScriptEnabled")
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		contentWebView = (WebView) findViewById(R.id.webview);
		msgView = (TextView) findViewById(R.id.msg);
		contentWebView.getSettings().setJavaScriptEnabled(true);
		contentWebView.loadUrl("file:///android_asset/wst.html");

		Button button = (Button) findViewById(R.id.button);
		button.setOnClickListener(btnClickListener);
		contentWebView.addJavascriptInterface(this, "wst");
	}

	OnClickListener btnClickListener = new Button.OnClickListener() {
		public void onClick(View v) {
			contentWebView.loadUrl("javascript:javacalljs()");
			contentWebView.loadUrl("javascript:javacalljswithargs(" + "'来自Java的问候'" + ")");
		}
	};

	public void startFunction() {
		Toast.makeText(this, "js java ", Toast.LENGTH_SHORT).show();
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				msgView.setText(msgView.getText() + "\njs java ");

			}
		});
	}

	public void startFunction(final String str) {
		Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				msgView.setText(msgView.getText() + "\njs java " + str);

			}
		});
	}
}

常见问题

onPageStarted()别调用多次

原因: 网址的加载过程中存在重定向问题,所以会被调用多次

解决办法:

public void onPageStarted(WebView view, String url, Bitmap favicon) { 
	if(!isLoading){
		isLoading = true;
		//TODO someting
	}
}
public void onPageFinished(){
	isLoading = false;
}

onPageStarted()调用webView.canGoBack()返回 false

原因:有时在加载网址的时候,需要对当前webview的状态进行判断,例如,自定义了一些前进、后退按钮,便需要实时的刷新按钮,需要在网址发生变化时监听webView;

在onPageStarted()里设置监听,去获取webView 的状态,但是有时会出现上述问题,明明webview是可以返回的,在onPageStarted()里获取的值为false。

解决办法:经过测试onProgressChanged()方法的调用情况,发现,在网络的加载进度在30%左右以后,canGoBack() 才返回 true;所以可以在onProgressChanged() 里加入监听,或是在onPageFinished()里去监听 webView的状态。

低版本上,会出现webview 销毁时 程序发生crash的情况

原因是:销毁的时候出现问题.

解决办法:

if(webView != null) { 
	// 要首先移除 
	removeView(webView); 
	// 清理缓存 
	webView.stopLoading(); 
	webView.onPause(); 
	webView.clearHistory(); 
	webView.clearCache(true); 
	webView.clearFormData(); 
	webView.clearSslPreferences(); 
	WebStorage.getInstance().deleteAllData(); 
	webView.destroyDrawingCache(); 
	webView.removeAllViews(); 
	// 最后再去webView.destroy(); 
	webView.destroy(); 
} 

参见谷歌中国

上一篇:flutter_webview_plugin加载不出来网页


下一篇:Android 使用WebView加载Url时,显示页面无法加载解决办法