WebView介绍
Android WebView在Android平台上是一个特殊的View, 基于webkit引擎、展现web页面的控件,这个类可以被用来在你的app中仅仅显示一张在线的网页,还可以用来开发浏览器。WebView内部实现是采用渲染引擎来展示view的内容,提供网页前进后退,网页放大,缩小,搜索。Android的Webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了Chrome。
现在很多APP都内置了Web网页,比如说很多电商平台,淘宝、京东、聚划算等等。WebView比较灵活,不需要升级客户端,只需要修改网页代码即可。一些经常变化的页面可以用WebView这种方式去加载网页。例如中秋节跟国庆节打开的页面不一样,如果是用WebView显示的话,只修改修改html页面就行,而不需要升级客户端。
Webview功能强大,可以直接使用html文件(本地sdcard/assets目录),还可以直接加载url,使用JavaScript可以html跟原生APP互调。
简单使用
因为需要加载网页url,所以需要在AndroidManifest.xml中添加访问网络权限。
1 <uses-permission android:name="android.permission.INTERNET" />
布局文件:activity_main.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 <WebView 8 android:id="@+id/webview" 9 android:layout_width="match_parent" 10 android:layout_height="match_parent"/> 11 12 <ProgressBar 13 android:id="@+id/progressbar" 14 style="@android:style/Widget.ProgressBar.Horizontal" 15 android:layout_width="match_parent" 16 android:layout_height="3dip" 17 android:max="100" 18 android:progress="0" 19 android:visibility="gone"/> 20 </FrameLayout>
外层FrameLayout,里面有WebView跟ProgressBar,WebView的宽高匹配父类,ProgressBar横向进度条,高度3dip,按照FrameLayout布局规则,ProgressBar会覆盖在WebView之上,默认是隐藏不显示。
MainActivity.java
1 public class MainActivity extends AppCompatActivity { 2 private WebView webView; 3 private ProgressBar progressBar; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 progressBar= (ProgressBar)findViewById(R.id.progressbar);//进度条 11 12 webView = (WebView) findViewById(R.id.webview); 13 // webView.loadUrl("file:///android_asset/test.html");//加载asset文件夹下html 14 webView.loadUrl("http://139.196.35.30:8080/OkHttpTest/apppackage/test.html");//加载url 15 16 //使用webview显示html代码 17 // webView.loadDataWithBaseURL(null,"<html><head><title> 欢迎您 </title></head>" + 18 // "<body><h2>使用webview显示 html代码</h2></body></html>", "text/html" , "utf-8", null); 19 20 webView.addJavascriptInterface(this,"android");//添加js监听 这样html就能调用客户端 21 webView.setWebChromeClient(webChromeClient); 22 webView.setWebViewClient(webViewClient); 23 24 WebSettings webSettings=webView.getSettings(); 25 webSettings.setJavaScriptEnabled(true);//允许使用js 26 27 /** 28 * LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据 29 * LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。 30 * LOAD_NO_CACHE: 不使用缓存,只从网络获取数据. 31 * LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。 32 */ 33 webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//不使用缓存,只从网络获取数据. 34 35 //支持屏幕缩放 36 webSettings.setSupportZoom(true); 37 webSettings.setBuiltInZoomControls(true); 38 39 //不显示webview缩放按钮 40 // webSettings.setDisplayZoomControls(false); 41 } 42 43 //WebViewClient主要帮助WebView处理各种通知、请求事件 44 private WebViewClient webViewClient=new WebViewClient(){ 45 @Override 46 public void onPageFinished(WebView view, String url) {//页面加载完成 47 progressBar.setVisibility(View.GONE); 48 } 49 50 @Override 51 public void onPageStarted(WebView view, String url, Bitmap favicon) {//页面开始加载 52 progressBar.setVisibility(View.VISIBLE); 53 } 54 55 @Override 56 public boolean shouldOverrideUrlLoading(WebView view, String url) { 57 Log.i("ansen","拦截url:"+url); 58 if(url.equals("http://www.google.com/")){ 59 Toast.makeText(MainActivity.this,"国内不能访问google,拦截该url",Toast.LENGTH_LONG).show(); 60 return true;//表示我已经处理过了 61 } 62 return super.shouldOverrideUrlLoading(view, url); 63 } 64 65 }; 66 67 //WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等 68 private WebChromeClient webChromeClient=new WebChromeClient(){ 69 //不支持js的alert弹窗,需要自己监听然后通过dialog弹窗 70 @Override 71 public boolean onJsAlert(WebView webView, String url, String message, JsResult result) { 72 AlertDialog.Builder localBuilder = new AlertDialog.Builder(webView.getContext()); 73 localBuilder.setMessage(message).setPositiveButton("确定",null); 74 localBuilder.setCancelable(false); 75 localBuilder.create().show(); 76 77 //注意: 78 //必须要这一句代码:result.confirm()表示: 79 //处理结果为确定状态同时唤醒WebCore线程 80 //否则不能继续点击按钮 81 result.confirm(); 82 return true; 83 } 84 85 //获取网页标题 86 @Override 87 public void onReceivedTitle(WebView view, String title) { 88 super.onReceivedTitle(view, title); 89 Log.i("ansen","网页标题:"+title); 90 } 91 92 //加载进度回调 93 @Override 94 public void onProgressChanged(WebView view, int newProgress) { 95 progressBar.setProgress(newProgress); 96 } 97 }; 98 99 @Override 100 public boolean onKeyDown(int keyCode, KeyEvent event) { 101 Log.i("ansen","是否有上一个页面:"+webView.canGoBack()); 102 if (webView.canGoBack() && keyCode == KeyEvent.KEYCODE_BACK){//点击返回按钮的时候判断有没有上一页 103 webView.goBack(); // goBack()表示返回webView的上一页面 104 return true; 105 } 106 return super.onKeyDown(keyCode,event); 107 } 108 109 /** 110 * JS调用android的方法 111 * @param str 112 * @return 113 */ 114 @JavascriptInterface //仍然必不可少 115 public void getClient(String str){ 116 Log.i("ansen","html调用客户端:"+str); 117 } 118 119 @Override 120 protected void onDestroy() { 121 super.onDestroy(); 122 123 //释放资源 124 webView.destroy(); 125 webView=null; 126 } 127 }
onCreate 查找控件,给webView设置加载url,添加js监听,监听的名称是”android”,设置webChromeClient跟webViewClient回调,通过getSettings方法获取WebSettings对象,设置允许加载js,设置缓存模式,支持缩放。
webViewClient 重写了几个方法,onPageFinished页面加载完成隐藏进度条,onPageStarted页面开始加载显示进度条,shouldOverrideUrlLoading拦截url,如果请求url是打开google,不让他请求,因为google在国内不能访问,就算请求也请求不到还不如拦截掉,直接告诉用户不能访问。
webChromeClient onJsAlert()因为WebView不支持alert弹窗,在这个方法中用AlertDialog去弹窗。onReceivedTitle获取网页标题。onProgressChanged页面加载进度,把加载进度给progressBar。
onKeyDown 如果点击系统自带返回键&&webView有上一级页面,调用goBack返回。否则不处理。什么时候辉有上一级页面呢?就是你从首页跳转到了一个新页面,点击返回的时候会返回首页。如果本来就在首页点击返回的时候会退出app。
getClient html页面的JS可以通过这个方法回调原生APP,这个方法有个注解@JavascriptInterface,这个是必须的,这个方法有个字符串参数,这个方法跟我们在onCreate中调用addJavascriptInterface传入的name一起使用的。例如html中想要回调这个方法可以这样写:javascript:android.getClient(“传一个字符串给客户端”);
onDestroy activity销毁时释放webView资源。