android webview使用记录

来源:互联网 发布:类似于知乎的网站 编辑:程序博客网 时间:2024/06/02 12:39

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 errorToast.makeText(getApplicationContext(), "网络连接失败 ,请连接网络。",Toast.LENGTH_SHORT).show();}});

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

2.2 WebChromeClient

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

webView.setWebChromeClient(new WebChromeClient() {@Overridepublic 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! */@Overrideprotected 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() {@Overridepublic 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内容需调用以下方法,参数为truewSettings.setJavaScriptEnabled(true);webView.addJavascriptInterface(new JsObject(), "demo");final class JsObject {@JavascriptInterfacepublic 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