android webview使用记录

webview的使用场景挺多的,比如说一些临时性质的活动,直接使用webview来做,效果更快,而且不用更新客户端。等等。

1 webview的基本使用


使用webview,首先要加上权限:<uses-permission android:name="android.permission.INTERNET"/>,否则会在webiew上报找不到对应的链接。



1.1 基本加载网页:

网络用:webView.loadUrl("http://www.baidu.com");
本地文件用:webView.loadUrl(file:///android_asset/XXX.html);这里的格式是固定的,文件位置 assets目录下


1.2 网页缓存模式:

LOAD_CACHE_ONLY:  不使用网络,只读取本地缓存数据
LOAD_DEFAULT: 默认缓存规则:  根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

如:www.taobao.com的cache-control为no-cache,在模式LOAD_DEFAULT下,无论如何都会从网络上取数据,如果没有网络,就会出现错误页面;

在LOAD_CACHE_ELSE_NETWORK模式下,无论是否有网络,只要本地有缓存,都使用缓存。本地没有缓存时才从网络上获取。www.360.com.cn的cache-control为max-age=60,在两种模式下都使用本地缓存数据。

总结:根据以上两种模式,建议缓存策略为,判断是否有网络,有的话,使用LOAD_DEFAULT,无网络时,使用LOAD_CACHE_ELSE_NETWORK。

	if (isNetworkConnected(webActivity.this)) {
			wSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
		} else {
			wSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
		}

	public boolean isNetworkConnected(Context context) {
		if (context != null) {
			ConnectivityManager mConnectivityManager = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo mNetworkInfo = mConnectivityManager
					.getActiveNetworkInfo();
			if (mNetworkInfo != null) {
				return mNetworkInfo.isAvailable();
			}
		}
		return false;
	}

判断网络要加上权限<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


1.3 goBcak canGoBack goForward canGoForward


这个是在后退的时候,不直接退出,而是返回到上一个页面,知道无法后退。


	@OnClick(R.id.btn_left)
	void goBack() {
		if (webView.canGoBack()) {
			webView.goBack();
		} else {
			btn_left.setEnabled(true);
		}
	}

	@OnClick(R.id.btn_right)
	void goForward() {
		if (webView.canGoForward()) {
			webView.goForward();
		} else {
			btn_right.setEnabled(true);
		}

	}

	@InjectView(R.id.btn_exit)
	Button btn_exit;

	@OnClick(R.id.btn_exit)
	void exit() {
		finish();
	}

	@OnClick(R.id.btn_refresh)
	void goRefresh() {
		webView.reload();
	}


2 WebViewClient 和 WebChromeClient 区别


WebView主要负责解析渲染,WebViewClient 和WebChromeClient是用来辅助WebView。

2.1 WebViewClient

setWebClient就是帮助WebView处理各种通知、请求事件。
onLoadResource 
onPageStart 
onPageFinish 
onReceiveError 
onReceivedHttpAuthRequest 


	webView.setWebViewClient(new WebViewClient() {

			public void onReceivedError(WebView view, int errorCode,
					String description, String failingUrl) { // Handle the error

				Toast.makeText(getApplicationContext(), "网络连接失败 ,请连接网络。",
						Toast.LENGTH_SHORT).show();

			}

		});

上面的代码处理了接收错误的情况。

2.2 WebChromeClient

setWebChromeClient辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等。

webView.setWebChromeClient(new WebChromeClient() {
			@Override
			public void onProgressChanged(WebView view, int newProgress) {
				if (newProgress == 100) {
					progressbar.setVisibility(View.GONE);
				} else {
					if (progressbar.getVisibility() == View.GONE) {
						progressbar.setVisibility(View.VISIBLE);
					}
					progressbar.setProgress(newProgress);
				}
				super.onProgressChanged(view, newProgress);
			}

		});

上面的代码会显示一个进度条,交互更加友好。


3 WebView页面中播放了音频,退出Activity后音频仍然在播放

自己在做的时候看到别人提到这点,就做了一个实验。打开百度音乐,播放音乐,然后退出,果然仍然在播放。

	/**
	 * 防止音频,视频结束后仍然播放!,Error: WebView.destroy() called while still attached!
	 */
	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (webView != null) {
			parentlayout.removeView(webView);
			webView.removeAllViews();
			webView.destroy();
		}
	}

开始直接webView.destory(),发现会报

WebView.destroy() called while still attached!

这个错误,需要在destory之前把webView从父容器中删除。


4 webview支持定位

这个是对接了一个网站,人家支持web定位,我这边没做。运营报给我的错误。




首先加上权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

添加对应的代码:
wSettings.setDatabaseEnabled(true);
		String dir = this.getApplicationContext()
				.getDir("database", Context.MODE_PRIVATE).getPath();
		// 启用地理定位
		wSettings.setGeolocationEnabled(true);
		// 设置定位的数据库路径
		wSettings.setGeolocationDatabasePath(dir);
		// 开启DomStorage缓存
		wSettings.setDomStorageEnabled(true);


//配置权限(同样在WebChromeClient中实现)  
public void onGeolocationPermissionsShowPrompt(String origin,   
               GeolocationPermissions.Callback callback) {  
    callback.invoke(origin, true, false);  
    super.onGeolocationPermissionsShowPrompt(origin, callback);  
} 

5 webview跳转到之前已经完成的功能

在一个大的Android项目中,由于客户端来不及更新和实现,经常会内嵌一些网页(在一些大型的互联网公司,PC的产品总是跑在客户端的前面),比如活动页面,通常可以内嵌用html5实现的页面,可以适配手机。但是这些网页中有好多链接,但是这些链接有些内容有是我们客户端已经实现的,比如有一个注册链接,其实客户端也实现了注册功能,我们不想再继续跳转到网页注册,而是打开客户端某个注册Activity,可以通过以下方式来实现

	webView.setWebViewClient(new WebViewClient() {
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				// TODO Auto-generated method stub
				// view.loadUrl(url);

				if (url != null && url.contains("login?")) {

					Map<String, String> mapRequest = UrlUtils.URLRequest(url);
					String userId = mapRequest.get("userid");

					if (!StringUtils.textIsNull(userId)) {
						Intent i = new Intent(webActivity.this,
								LoginActivity.class);
						Bundle bundle = new Bundle();
						bundle.putString("userID", String.valueOf(userId));
						i.putExtras(bundle);
						startActivity(i);

						finish();
					}

					return true;
				}
				return super.shouldOverrideUrlLoading(view, url);
			}

如果发现链接里面是有login?这个字段的,可以支持跳转到客户端已经支持的页面去,我写的demo里面是跳到用户登录页面。

6 js和原生交互


这个是我之前在做sdk开发的时候遇到的问题,也总结到这个里面把。

首先如果您在编写HTML5应用,需要在JS代码中访问Java中的函数,则您会用到WebView的addJavascriptInterface()函数。因为安全问题,在Android4.2中(如果应用的android:targetSdkVersion数值为17+)JS只能访问带有 @JavascriptInterface注解的Java函数。

之前,任何Public的函数都可以在JS代码中访问,而Java对象继承关系会导致很多Public的函数都可以在JS中访问,其中一个重要的函数就是 getClass()。然后JS可以通过反射来访问其他一些内容。通过引入 @JavascriptInterface注解,则在JS中只能访问 @JavascriptInterface注解的函数。这样就可以增强安全性。

如果您的应用android:targetSdkVersion数值为17或者大于17记得添加 @JavascriptInterface 注解。


		// 网页中包含JavaScript内容需调用以下方法,参数为true
		wSettings.setJavaScriptEnabled(true);
		webView.addJavascriptInterface(new JsObject(), "demo");
		
	
	
	final class JsObject {
		@JavascriptInterface
		public void clickOnAndroid() {

			mHandler.post(new Runnable() {
				@SuppressLint("JavascriptInterface")
				public void run() {
					webView.loadUrl("javascript:wave()");
				}
			});
		}
	}

对于的网页,我放在assets下面

<html>       
  <script >     
    function wave() {       
       document.getElementById("android").src="android_waving.png";       
        }       
   </script>       
 <body>       
    <a onClick="window.demo.clickOnAndroid()">       
    <img id="android" src="ic_launcher.png" mce_src="ic_launcher.png"/><br>       
            Click me!       
    </a>    
    <br/>
    <br/>
   <a href="http://test/login?userId=1234">login</a>
  </body>       
</html>    
 webview需要加进一个回调的代理类JsObject,并给它一个调用的名称:demo
js调用java方法
  <a onClick="window.demo.clickOnAndroid()">       

Java要调用js的方法,只需知道js的方法名称即可:
webView.loadUrl("javascript:wave()");

上面的例子显示出来了js调用java方法,然后java调用了js的方法,更换了图片。




7 安全的js

https://github.com/pedant/safe-java-js-webview-bridge
大家可以看下github的demo,我试了一下,对应的jsObject方法必须是static,感觉不太好使,网上没有具体的使用例子。


butterknife 配置参考:http://blog.csdn.net/hlllmr1314/article/details/36375273?utm_source=tuicool
demo地址:http://download.csdn.net/detail/jjdhshdahhdd/9056235


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值