webview

原创 2013年12月03日 17:27:49

参考

        http://developer.android.com/guide/webapps/webview.html

基础

        webview就是一个组件,可以和textview一样使用。可以调用loadUrl("http://www.baidu.com")进行加载指定了url的网页。

        当加载一个界面后,点击其中的链接,会调用系统的浏览器进行访问。如果想要用自己的webview访问,可以设置webview.setWebViewClient(new WebViewClient());即可。

        WebViewClient中有shouldOverrideUrlLoading():返回true,就代表由应用的代码处理该url,webview不处理;返回false,就代表用webview本身进行访问(WebViewClient类中的shouldOverrideUrlLoading默认的是返回false)。还有onPageStarted(),onPageFinished()方法,因此可以在刚开始加载界面的时候弹出一个进度条,而界面加载完成之后进度条消失。

        所以可以根据url的不同,来选择用webview访问还是浏览器进行访问。调用浏览器的Intent:

        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        startActivity(intent);
        webview还可以直接加载html数据,如
mWebView.loadData("<html><body>"+str+"</body></html>", "text/html", "utf-8");

常用功能

post请求网页

        使用postUrl()进行加载即可。第一个参数为请求的链接,第二个参数为post的请求体。如下:
        Map<String, String> pairs = mWebBean.getFormPairs();
        if (pairs != null) {
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : pairs.entrySet()) {
                sb.append(entry.getKey());
                sb.append("=");
                sb.append(entry.getValue());
                sb.append("&");
            }//拼装请求参数
            byte[] post = EncodingUtils.getBytes(sb.toString(), "BASE64");//将请求参数以base64的方式进行加密
            webView.postUrl(mWebBean.getUrl(), post);
            return true;
        }

刷新

        webview的刷新很简单,调用WebView.reload()即可。

加载https

        在有些手机中,webview加载https会加载不出来。解决办法为:重写WebViewClient#onReceivedSslError,并使用handler.proceed()。如下:
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();//handler.cancel()
            }
        此种方法是认证所有的https请求。

加载错误界面

        用webview访问时,如果界面加载失败,webview会加载一个系统默认的错误界面。可以通过如下方法进行修改:
		mWebView.setWebViewClient(new WebViewClient(){
			@Override
			public void onReceivedError(WebView view, int errorCode,
					String description, String failingUrl) {
				//该方法中加载本地的错误界面。如assets目录下的error.html
				view.loadUrl("file:///android_asset/error.html");
				super.onReceivedError(view, errorCode, description, failingUrl);
			}
		});

返回键

        正确的处理应该是:如果是网页,就应该返回到上一个网页,否则就直接退出程序。代码

public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode == KeyEvent.KEYCODE_BACK && view != null && view.canGoBack()){//如果仍在网页中,就退回上一个网页
			view.goBack();
			return true;
		}else{//退到最先的一个网页,再按退出就退出程序
			finish();
		}
		return super.onKeyDown(keyCode, event);
	}
        canGoBack():当退到开始进入的网页时就返回false,从而执行下面的finish()方法。

        然而,上面处理方法有一个弊端:每一次返回上一个界面的时候,就会自动刷新(好像是底层的原因,没有办法更改)。如果不想要自动刷新,就不能用上面的方法处理返回键。为了达到不刷新的效果,只能是一个界面就用一个activity,同时不需要重写onKeyDown()方法。,这样返回的时候就是返回到上一个activity了,还是保留了原来的样子。实现方法是:

wv.setWebViewClient(new WebViewClient(){
			public boolean shouldOverrideUrlLoading(WebView view, String url) {//重新加载的时候开启新的activity,为了返回键(保证返回时内容还是原来的样子)
				Intent intent = new Intent(StudentWebActivity.this,StudentWebActivity.class);
				intent.putExtra("studentId", stuId);
				intent.putExtra("url", url);
				startActivity(intent);
				return true;//要返回true。
			}
		});

下载

        在webview中直接进行下载。代码如下:

		mWebView.setDownloadListener(new DownloadListener() {
			@Override
			public void onDownloadStart(String url, String userAgent,
					String contentDisposition, String mimetype, long contentLength) {
				//url为所需要下载的资源的链接。下面是调用系统的浏览器进行下载
				Uri uri = Uri.parse(url);
				Intent i = new Intent(Intent.ACTION_VIEW, uri);
				startActivity(i);
			}
		});

与JS互调

js调用android

        为了方便,可以写一个html,放在assets中,loadUrl("file:///android_asset/demo.html");即可。

html代码示例:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>demo.html</title>
	
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

  </head>
  <script type="text/javascript">
  	function demo(params){
  		window.android.toast(params);
  	}
  </script>
  <body>
    	<input type="button" value="提交" onclick="demo('a');" />
  </body>
</html>
在android端:
		view.addJavascriptInterface(new Object(){//网页调用android代码
			public void toast(String s){
				Toast.makeText(ShowTable.this, s, Toast.LENGTH_SHORT).show();
			}
		}, "android");

        在js中,只需要通过window.xxx就可以调用到android中的代码。其中xxx是addJavaScriptInterface中的第二个参数。

android调用js

       webview.loadUrl("javascript:getNode3()");//getNode3()就是js中的方法

常见问题

显示加载进度

        用webview加载界面时,可以在界面上方显示一个加载进度,主要通过WebChromeClient.onProgressChanged()进行更新。如下:
		mWv.setWebChromeClient(new WebChromeClient() {
			//更新加载进度
			public void onProgressChanged(WebView view, int newProgress) {
				mPb.setProgress(newProgress);
			}
			//当加载到界面的title时
			public void onReceivedTitle(WebView view, String title) {
				mTv.setText(title);
			}
		});

对话框及activity关闭后弹框处理

        网页中经常会弹出一些dialog,默认时系统会使用自己的dialog,也可重写相应的方法弹出自定义的dialog。要重写的方法WebChromeClient#onJsAlert(),WebChromeClient#onJsConfirm()与WebChromeClient#onJsPrompt()。这几个方法主要区别在于js弹框时使用的方法,如js使用alert()时,对应的是onJsAlert()。
        这些方法返回true时,代表程序自己处理了js中的弹框,webview不会再进行处理。返回false时webview还会再进行处理。这点与shouldOverrideUrlLoading()方法的返回值类似。
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                if(view != null && view.isShown() && view.getContext() != null){
                    return super.onJsAlert(view,url,message,result);
                }
                result.confirm();
                return true;
            }
        当webview所处的activity关闭后,js仍旧会弹出dialog,此时应用就会崩溃。因此在弹出之前需要进行if判断。并且该activity关闭后,不应该再弹框,所以onJsAlert()应该返回true。
        虽说自己的应用不会弹出dialog,但实际上网页中仍旧会有一个dialog存在,因此再次进入该界面时,就会加载不出来。所以需要在onJsAlert()中调用result.confirm(),保证网页的dialog消失。这样下次进来时就会再次加载出界面。

乱码

        使用loadData()加载html时,有时候会出现乱码。可以用loadDataWithBaseURL()代替loadData();如:

wv.loadDataWithBaseURL (null, html, "text/html", "utf-8",null);
如果不行就加上:
		WebSettings settings = wv.getSettings();
		settings.setDefaultTextEncodingName("utf-8");

图片过大

        加载的数据中如果有图片的话,有可能会超过屏幕,从而需要横向滑动才行。可以进行相应的缩小:

WebSettings settings = wv.getSettings();
		settings.setUseWideViewPort(true); 
        settings.setLoadWithOverviewMode(true); 
这样的缩小会将文字和图片一起缩小,可能使得文字看不见。可以采用下面方法 :
	WebSettings settings = wv.getSettings();
	settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
	settings.setLoadWithOverviewMode(true);

示例

public class ShowTable extends Activity {

	private WebView view;
	private Button btn;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		view = (WebView) findViewById(R.id.tv_left);
		btn = (Button) findViewById(R.id.btn);
		
		btn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				view.loadUrl("javascript:display_alert('sqgefergklp')");//调用js中的方法,参数需要用‘’括起来
			}
		});
		
		view.getSettings().setJavaScriptEnabled(true);
		view.loadUrl("file:///android_asset/alert.html");//加载js
		
		view.setWebChromeClient(new WebChromeClient(){
			@Override
			public boolean onJsAlert(WebView view, String url, String message,
					JsResult result) {//js中用alert()时
				final JsResult res = result;
				AlertDialog.Builder builder = new AlertDialog.Builder(ShowTable.this);
				builder.setTitle(null);
				builder.setMessage(message);
				builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						res.confirm();
					}
				});
				builder.setCancelable(false);
				builder.create();
				builder.show();
				return true;
			}
			@Override
			public boolean onJsConfirm(WebView view, String url,
					String message, JsResult result) {//js中用confirm()时
				final JsResult res = result;
				AlertDialog.Builder builder = new AlertDialog.Builder(ShowTable.this);
				builder.setTitle(null);
				builder.setMessage(message);
				builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						res.confirm();
					}
				});
				builder.setNegativeButton(android.R.string.cancel, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						res.cancel();
					}
				});
				builder.setCancelable(false);
				builder.create();
				builder.show();
				return true;
			}
			@Override
			public boolean onJsPrompt(WebView view, String url, String message,
					String defaultValue,final JsPromptResult result) {//注意最后一个参数的类型,不是JsResult,而是JsPromptResult
				//js中有prompt时。此处,自己定义一个显示的对话框,用于代替网页中本身显示的prompt对话框
				View view2 = View.inflate(ShowTable.this, R.layout.test, null);
				final EditText et = (EditText) view2.findViewById(R.id.et_text);
				et.setText(defaultValue);
				TextView tv = (TextView) view2.findViewById(R.id.tv);
				tv.setText(message);
				AlertDialog.Builder builder = new AlertDialog.Builder(ShowTable.this);
				builder.setTitle(null);
				builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						String string = et.getText().toString();
						result.confirm(string);
					}
				});
				builder.setNegativeButton(android.R.string.cancel, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						result.cancel();
					}
				});
				builder.setView(view2);
				builder.setCancelable(false);
				builder.create();
				builder.show();
				return true;
			}
		});
		view.setWebViewClient(new WebViewClient(){
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				return false;
			}
		});
		view.addJavascriptInterface(new Object(){//网页调用android代码
			public void toast(String s){
				Toast.makeText(ShowTable.this, s, Toast.LENGTH_SHORT).show();
			}
		}, "android");
	}
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode == KeyEvent.KEYCODE_BACK && view != null && view.canGoBack()){//如果仍在网页中,就退回上一个网页
			view.goBack();
			return true;
		}else{//退到最先的一个网页,再按退出就退出程序
			finish();
		}
		return super.onKeyDown(keyCode, event);
	}







                    
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android完美接入腾讯TBS浏览器WebView

  • 2017年11月13日 15:23
  • 26.79MB
  • 下载

mui 滑动切换界面 多webview模式

  • 2017年09月21日 21:27
  • 133KB
  • 下载

android webview一篇文章全面了解(基本使用,url拦截,js跟java交互)

1.前言最近几年混合应用越来越流行,及一部分功能用原生代码开发,一部分功能用html5实现。那什么时候用原生什么时候用网页呢?很多人第一反应就是经常变化的页面用网页开发,避免经常发包,不全对。其实因为...

webview与js的通讯

  • 2015年12月24日 15:56
  • 1.42MB
  • 下载

webview显示String类型的html文本

效果图: 做法: xml:    android:id="@+id/plan_open_html"         android:layout_width="match_pare...

android富文本编辑器 webview

  • 2017年11月08日 09:23
  • 24.53MB
  • 下载

WebView使用详解(二)——WebViewClient与常用事件监听

前言:生活的艰难,更会激发对梦想的渴望,但艰难的生活却往往会成为梦想的绊脚石上篇给大家简单讲了Webview中Native代码与JS相互调用的方法,这篇我们再讲讲有关各种拦截与处理的东东。一、WebV...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:webview
举报原因:
原因补充:

(最多只允许输入30个字)