Android Webview使用和遇到过的坑总结

本文讲的是Android Webview使用和遇到过的坑总结,WebView 用来显示网页的一个View,它使用WebKit渲染引擎显示web页面,可以加载在线的或者本地的html页面,WebView可以对页面进行一系列操作,如历史页面的向前、向后,放大和缩小,执行文本搜索,与JS交互等等;

在使用Webview时,请记得在AndroidManifest.xml文件中声明INTERNET权限:


  1. <uses-permission android:name="android.permission.INTERNET" /> 

默认情况下,WebView不支持JavaScript,web页面的错误也会被忽略,如果只是用Webview来显示网页而不用交互,默认配置就可以了,如果需要交互,就需要自定义配置了。

WebView初始化及加载URL

1、通过XML初始化:


  1. <WebView  
  2.     android:id="@+id/webview" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="fill_parent"/>  

或者直接New:


  1. WebView webview = new WebView(this); 

2、加载URL:


  1. WebView myWebView = (WebView) findViewById(R.id.webview); 
  2.  
  3. myWebView.loadUrl("http://www.example.com");  

或者可以直接加载Html:


  1. String summary = "<html><body>You scored <b>192</b> points.</body></html>"; 
  2.  
  3. myWebView.loadData(summary, "text/html", null);  

如果在加载URL的时候想添加Header信息,可以复写loadUrl()方法,如:


  1. @Override public void loadUrl(String url) { 
  2.      Map<String, String> map = new HashMap<String, String>();      
  3.        map.put("ajax", "true");      
  4.        map.put("appversion", SharedPreferencesUtil.getAppVersion(getContext()));     map.put("clientid", SharedPreferencesUtil.getClientId(getContext())); 
  5.      loadUrl(url, map); 
  6.  }  

WebSettings

WebSettings 中可以对WebView进行一系列配置,如:


  1. WebSettings settings = getSettings(); //默认是false 设置true允许和js交互 
  2. settings.setJavaScriptEnabled(true); //  WebSettings.LOAD_DEFAULT 如果本地缓存可用且没有过期则使用本地缓存,否加载网络数据 默认值 
  3. //  WebSettings.LOAD_CACHE_ELSE_NETWORK 优先加载本地缓存数据,无论缓存是否过期 
  4. //  WebSettings.LOAD_NO_CACHE  只加载网络数据,不加载本地缓存 
  5. //  WebSettings.LOAD_CACHE_ONLY 只加载缓存数据,不加载网络数据 
  6. //Tips:有网络可以使用LOAD_DEFAULT 没有网时用LOAD_CACHE_ELSE_NETWORK 
  7. settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //开启 DOM storage API 功能 较大存储空间,使用简单 
  8. settings.setDomStorageEnabled(true); //设置数据库缓存路径 存储管理复杂数据 方便对数据进行增加、删除、修改、查询 不推荐使用 
  9. settings.setDatabaseEnabled(true); final String dbPath = context.getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath(); 
  10. settings.setDatabasePath(dbPath); //开启 Application Caches 功能 方便构建离线APP 不推荐使用 
  11. settings.setAppCacheEnabled(true); final String cachePath = context.getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath(); 
  12. settings.setAppCachePath(cachePath); 
  13. settings.setAppCacheMaxSize(5 * 1024 * 1024);  

Webview中可以设置的几种缓存对比:

WebviewClient

WebCromeClient常用方法:

1、shouldOverrideUrlLoading(WebView view, String url)

在API 24以后过时,当一个url即将被webview加载时,给Application一个机会来接管处理这个url,方法返回true代表Application自己处理url;返回false代表Webview处理url。

举个例子,项目中需要处理传过来的URL是一个事件还是一个HTTP链接,可以通过自定义协议头 (nativeapi://) 来过滤,如:


  1. @Override 
  2.  public boolean shouldOverrideUrlLoading(WebView view, String url) { 
  3.      Uri uri = Uri.parse(url); 
  4.      String scheme = uri.getScheme();      
  5.             if (TextUtils.isEmpty(scheme)) return true;      
  6.             if (scheme.equals("nativeapi")) {          
  7.             //如定义nativeapi://showImg是用来查看大图,这里添加查看大图逻辑 
  8.          return true; 
  9.      } else if (scheme.equals("http") || scheme.equals("https")) {          
  10.             //处理http协议 
  11.          if (Uri.parse(url).getHost().equals("www.example.com")) {             
  12.             // 内部网址,不拦截,用自己的webview加载 
  13.              return false; 
  14.          } else {              
  15.                 //跳转外部浏览器 
  16.              Intent intent = new Intent(Intent.ACTION_VIEW, uri); 
  17.              context.startActivity(intent);              
  18.                     return true; 
  19.          } 
  20.      }     return super.shouldOverrideUrlLoading(view, url); 
  21.  }  

注:如果使用的是Post请求方式,则此方法不会被回调

2、shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

在API 24以后新加的,使用同上。

3、shouldInterceptRequest(WebView view, String url)

在API 21以后过时,通知Application加载资源的请求并返回请求的资源,如果返回值是Null,Webview仍然会按正常加载资源;否则返回的数据将会被使用。

注:回调发生在子线程中,不能直接进行UI操作

4、shouldInterceptRequest(WebView view, WebResourceRequest request)

在API 21以后新加,使用同上。

5、onPageStarted(WebView view, String url, Bitmap favicon)

通知Application页面已经开始加载资源,页面加载过程中,onPageStarted至多会被执行一次。

6、onPageFinished(WebView view, String url)

通知Application页面已经加载完毕。

7、onReceivedError(WebView view, int errorCode, String description, String failingUrl)

通知Application有错误发生,这些错误是不可恢复的(即主要的资源不可用)。errorCode参数对应于一个ERROR_ *常量

WebCromeClient

1、onProgressChanged(WebView view, int newProgress)

通知Application的加载进度,newProgress取值范围[0,100],可以通过这个方法来编写一个带加载进度条的Webview,具体例子请参考:Android 编写一个带进度条的Webview

2、onReceivedTitle(WebView view, String title)

当加载页面标题有改变时会通知Application,title即为新标题。

控制Webview加载历史网页

WebView重写URL加载时,它会自动累积的历史访问的web页面。可以通过向后goBack()和向前goForward()。

举例,可以在Activity中的回退键控制向后回退到前一个页面:


  1. @Override 
  2.  public boolean onKeyDown(int keyCode, KeyEvent event) {      
  3.         // Check if the key event was the Back button and if there's history 
  4.      if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { 
  5.          webview.goBack();          
  6.                 return true; 
  7.      }     // If it wasn't the Back key or there's no web page history, bubble up to the default 
  8.      // system behavior (probably exit the activity) 
  9.      return super.onKeyDown(keyCode, event); 
  10.     }  

Webview和Js交互

1、Js调用Android接口:


  1. public class WebAppInterface { 
  2.     Context mContext;     
  3.      /** Instantiate the interface and set the context */ 
  4.     WebAppInterface(Context c) { 
  5.         mContext = c; 
  6.     }    /** Show a toast from the web page */ 
  7.     @JavascriptInterface     
  8.             public void showToast(String toast) { 
  9.         Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); 
  10.     } 
  11. }  

SDK>=17(Android4.2)以上,必须添加@JavascriptInterface声明,然后通过 addJavascriptInterface() 方式供Js调用,如:


  1. webView.addJavascriptInterface(new WebAppInterface(this), "android"); 

通过上面的配置,就可以在Js中调用了:


  1. <input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> 
  2. <script type="text/javascript"> 
  3.     function showAndroidToast(toast) { 
  4.         //调用Android中的showToast方法 
  5.         Android.showToast(toast); 
  6.     }</script>  

2、Android调用Js的接口:

可以通过webview.loadUrl("javascript:JsMethod()")方式加载Js接口,如果有参数,直接加到JsMethod()里面即可,下面封装了两个方法,分别是加载带参数和不带参数的Js函数:


  1. /** 
  2.     * 加载带参数的JS函数 
  3.     * 
  4.     * @param JsName JS函数名 
  5.     * @param params 不定参数 
  6.     */ 
  7.    public void loadJSWithParam(String JsName, String... params) { 
  8.        String TotalParam = "";         
  9.               for (int i = 0; i < params.length; i++) {             
  10.                  if (i == params.length - 1) {                 
  11.                      //最后一个 
  12.                TotalParam += (params[i]); 
  13.            } else { 
  14.                TotalParam += (params[i] + "','"); 
  15.            } 
  16.        }        this.loadUrl("javascript:" + JsName + "('" + TotalParam + "')"); 
  17.    }    /** 
  18.     * 加载不带参数的JS函数 
  19.     * 
  20.     * @param JsName JS函数名 
  21.     */ 
  22.    public void loadJS(String JsName) {         
  23.         this.loadUrl("javascript:" + JsName + "()"); 
  24.    }  

Webview的一些优化和遇到的坑

1、Webview打开一个链接,播放一段音乐,退出Activity时音乐还在后台播放,可以通过在Activity的onPause中调用webview.onPause()解决,并在Activity的onResume中调用webview.onResume()恢复,如下:


  1. @Override 
  2.     protected void onPause() { 
  3.        h5_webview.onPause(); 
  4.        h5_webview.pauseTimers();        
  5.           super.onPause(); 
  6.     } @Override 
  7.     protected void onResume() { 
  8.        h5_webview.onResume(); 
  9.        h5_webview.resumeTimers();        
  10.           super.onResume(); 
  11.     }  

Webview的onPause()方法官网是这么解释的:

Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation. Note that this call does not pause JavaScript. To pause JavaScript globally, use pauseTimers(). To resume WebView, call onResume().

通知内核尝试停止所有处理,如动画和地理位置,但是不能停止Js,如果想全局停止Js,可以调用pauseTimers()全局停止Js,调用onResume()恢复。

2、5.0 以后的WebView加载的链接为Https开头,但是链接里面的内容,比如图片为Http链接,这时候,图片就会加载不出来,解决方法:


  1. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {  
  2. webSetting.setMixedContentMode(webSetting.getMixedContentMode()); 
  3.  }  

原因是5.0之后不支持Https和Http的混合模式,具体可参看:Android5.0 WebView中Http和Https混合问题

3、WebView与JavaScript相互调用时,如果是debug没有配置混淆时,调用时没问题的,但是当设置混淆后发现无法正常调用了,解决方法:

在proguard-rules.pro文件中配置:


  1. -keepattributes *Annotation*   
  2. -keepattributes *JavascriptInterface* 
  3. -keep public class org.mq.study.webview.DemoJavaScriptInterface{     
  4.     public <methods>; 
  5. }  

如果是内部类:  


  1. -keepattributes *Annotation* 
  2. -keepattributes *JavascriptInterface* 
  3. -keep public class org.mq.study.webview.webview.DemoJavaScriptInterface$InnerClass{     
  4.     public <methods>; 
  5. }  

本文作者:mmmqqq

来源:51CTO

原文标题:Android Webview使用和遇到过的坑总结

时间: 2024-11-03 12:05:41

Android Webview使用和遇到过的坑总结的相关文章

Android WebView使用的技巧与一些坑_Android

随着手机性能的提高,以及iOS和Android两个平台的普及,更多的App都会选择两个平台的App都进行开发,在有些时候,为了更加快速的开发,我们会采用hybird方式开发,这个时候我们需要使用webview并且自己进行一些配置.Android的webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了chrome,因此问题很多,这里分享一些我使用过程的一些技巧和遇到的坑.###webview配置### mWebview.getSettings().setJavaScri

Android WebView使用的技巧与一些坑

随着手机性能的提高,以及iOS和Android两个平台的普及,更多的App都会选择两个平台的App都进行开发,在有些时候,为了更加快速的开发,我们会采用hybird方式开发,这个时候我们需要使用webview并且自己进行一些配置.Android的webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了chrome,因此问题很多,这里分享一些我使用过程的一些技巧和遇到的坑. ###webview配置### mWebview.getSettings().setJavaScr

Android WebView 上传文件支持全解析_Android

默认情况下情况下,使用Android的WebView是不能够支持上传文件的.而这个,也是在我们的前端工程师告知之后才了解的.因为Android的每个版本WebView的实现有差异,因此需要对不同版本去适配.花了一点时间,参考别人的代码,这个问题已经解决,这里把我踩过的坑分享出来. 主要思路是重写WebChromeClient,然后在WebViewActivity中接收选择到的文件Uri,传给页面去上传就可以了.创建一个WebViewActivity的内部类 public class XHSWeb

android webview定制contextmenu

问题描述 android webview定制contextmenu 10C 如何实现图种的webview的上下文菜单.需求是获取选中的内容,进行操作. 解决方案 http://www.2cto.com/kf/201310/248762.html 解决方案二: android的ContextMenuAndroid ContextMenuandroid ContextMenu 解决方案三: webview里的问题是可以实现你说的功能,不需要单独设置. 解决方案四: 你把属性设置对就不会错了 解决方案

android webview中如何获得输入框输入的内容

问题描述 android webview中如何获得输入框输入的内容 求高手指点,寻求热心好人帮助.如何获得webview中登录框我输入的内容. 详细: 通过webView打开一个URL网址.打开后有一个登录页面,页面有个userID和Password的输入框,和一个登录按钮,输入帐号密码后点击登录按钮,如何获得我输入的帐号和密码????? url是用别公司的登录页面地址.不知道他的数据 解决方案 http://www.eoeandroid.com/forum.php?mod=viewthread

Android webview通过http get下载文件下载两次的现象和解决方法

一.现象 一般通过Android webview进行下载文件的方法是 1.重写DownloadListener的onDownloadStart方法,在onDownloadStart方法中弹出对话框提示用户有新的文件需要下载 2.用户点击确定之后,通过http get下载文件 由于Android webview的实现,以上的下载文件步骤涉及到了两次get的操作.第一次是用户在webview中点击下载链接时,webview自动发送http get请求,这个时候服务器除了将文件信息发送过来之外,会同时

android webview中图片 长按点击保存本地 部分手机不能实现。

问题描述 android webview中图片 长按点击保存本地 部分手机不能实现. 代码如下 private String imgurl = """"; /*** * 功能:长按图片保存到手机 */@Overridepublic void onCreateContextMenu(ContextMenu menu View v ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu v menuInfo)

android webView 上传图片

问题描述 android webView 上传图片 博客:http://blog.csdn.net/woshinia/article/details/19030437 中有上传 图片的功能,但是遇到了一个问题.(博客评论2L). A: 正常情况下,一路选择到图库,并且也选择了图片,这都没问题.但是如果在弹出选择对话框后,敲击对话框之外的任何地方,或者直接点击返回键,取消掉对话框,这个时候,再次点击网页按钮,就没有任何反应了. 此时的webview就只能看,上面的任何操作都变的无效了,包括网页链接

应用-android webview 怎么实现退出功能

问题描述 android webview 怎么实现退出功能 就是做了一个APP的壳,里面直接套webview 请问这样的话 退出应用的功能怎么实现呢? 解决方案 网页上做个链接,捕获链接跳转即可 解决方案二: Android webView 实现与JSAndroid Webview实现文件下载功能Android: 扩展WebView 和ViewPager实现viewpager中的水平滑动,类似Gmail的效果 解决方案三: 记得是重写WebView的goback方法. 解决方案四: 退出的时候还