继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android WebView

慕神8447489
关注TA
已关注
手记 1273
粉丝 174
获赞 956

      Android WebView

        一、简介

        WebView在Android平台上是一个特殊的View, 基于webkit引擎、展现web页面的控件,这个类可以被用来在你的app中仅仅显示一张在线的网页,还可以用来开发浏览器。WebView内部实现是采用渲染引擎来展示view的内容,提供网页前进后退,网页放大,缩小,搜索。Android的Webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了Chrome内核。

        现在很多APP都内置了Web网页,比如说很多电商平台,淘宝、京东、聚划算等等。WebView比较灵活,不需要升级客户端,只需要修改网页代码即可。一些经常变化的页面可以用WebView这种方式去加载网页。例如中秋节跟国庆节打开的页面不一样,如果是用WebView显示的话,只修改修改html页面就行,而不需要升级客户端。

        二、基本使用

        1、添加网络权限

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


        2、添加布局

<WebView

    android:id="@+id/wv_webview"

    android:layout_width="match_parent"

    android:layout_height="match_parent"/>

        3、基本代码运用

webView = (WebView) findViewById(R.id.wv_webview);

// webView.loadUrl("file:///android_asset/test.html");//加载asset文件夹下html

webView.loadUrl("http://139.196.35.30:8080/OkHttpTest/apppackage/test.html");//加载url

webView.addJavascriptInterface(this,"android");//添加js监听 这样html就能调用客户端

webView.setWebChromeClient(webChromeClient);//辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度条webView.setWebViewClient(webViewClient); //帮助WebView处理各种通知、请求事件

WebSettings webSettings=webView.getSettings();//对WebView进行配置和管理

webSettings.setJavaScriptEnabled(true);//允许使用js

LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据

LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。

LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.  

LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//不使用缓存,只从网络获取数据.

//支持屏幕缩放

webSettings.setSupportZoom(true);

webSettings.setBuiltInZoomControls(true);

        三、常用方法

        1、WebView常用方法

wvWebview.loadUrl(String url);// 加载网络链接 url

wvWebview.canGoBack();// 判断 WebView 当前是否可以返回上一页

wvWebview.goBack();// 回退到上一页

wvWebview.onResume();// 在调用onPause()后,可以调用该方法来恢复WebView 的运行

wvWebview.resumeTimers();// 恢复pauseTimers时的所有操作

wvWebview.onPause();// 类似 Activity 生命周期,页面进入后台不可见状态

wvWebview.pauseTimers();// 该方法面向全局整个应用程序的webview,它会暂停所有webview的layout,parsing,JavaScript Timer。当程序进入后台时,该方法的调用可以降低CPU功耗。

wvWebview.destroy();// 销毁 WebView

wvWebview.clearHistory();// 清空历史

wvWebview.clearCache(true);// 包括硬盘

wvWebview.reload();// 重新加载当前请求

wvWebview.removeAllViews();// 清除子view。

wvWebview.clearSslPreferences();// 清除ssl信息。

wvWebview.clearMatches();// 清除网页查找的高亮匹配字符。

wvWebview.removeJavascriptInterface(String interfaceName);// 删除interfaceName对应的注入对象

wvWebview.addJavascriptInterface(Object object,String interfaceName);//注入 java 对象。

wvWebview.setVerticalScrollBarEnabled(true);// 设置垂直方向滚动条。

wvWebview.setHorizontalScrollBarEnabled(true);// 设置横向滚动条。

wvWebview.loadUrl(String url, Map additionalHttpHeaders);// 加载制定url并携带http header数据。。

wvWebview.stopLoading();// 停止 WebView 当前加载。

wvWebview.freeMemory();// 释放内存,不过貌似不好用。

wvWebview.clearFormData();// 清除自动完成填充的表单数据。需要注意的是,该方法仅仅清除当前表单域自动完成填充的表单数据,并不会清除WebView存储到本地的数据。

        2、WebSettings(对WebView进行配置和管理) 常用方法

finalString filesDir = getContext().getFilesDir().getPath();

finalString databaseDir = filesDir.substring(0, filesDir.lastIndexOf("/")) + DATABASES_SUB_FOLDER;

WebSettings webSettings = wvWebview.getSettings();

if(webSettings ==null)return;

webSettings.setJavaScriptEnabled(true);// 支持 Js 使用

webSettings.setDomStorageEnabled(true);// 开启DOM缓存

webSettings.setDatabaseEnabled(true);// 开启数据库缓存

webSettings.setLoadsImagesAutomatically(true);// 支持自动加载图片

webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);// 设置 WebView 的缓存模式

webSettings.setAppCacheEnabled(true);// 支持启用缓存模式

// Android 私有缓存存储,如果你不调用setAppCachePath方法,WebView将不会产生这个目录

webSettings.setAppCachePath(getCacheDir().getAbsolutePath());

if(Build.VERSION.SDK_INT <19) {// 数据库路径

    webSettings.setDatabasePath(databaseDir);

}

webSettings.setSupportZoom(true);// 支持缩放

webSettings.setUserAgentString("");// 设置 UserAgent 属性

webSettings.setAllowFileAccess(true);// 允许加载本地 html 文件/false

// 允许通过 file url 加载的 Javascript 读取其他的本地文件,Android 4.1 之前默认是true,在 Android 4.1 及以后默认是false,也就是禁止

webSettings.setAllowFileAccessFromFileURLs(false);

// 允许通过 file url 加载的 Javascript 可以访问其他的源,包括其他的文件和 http,https 等其他的源,

// Android 4.1 之前默认是true,在 Android 4.1 及以后默认是false,也就是禁止

// 如果此设置是允许,则 setAllowFileAccessFromFileURLs 不起做用

webSettings.setAllowUniversalAccessFromFileURLs(false);

webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

        3、WebChromeClient(辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度条)常用方法

wvWebview.setWebChromeClient(newMyWebChromeClient());

publicclassMyWebChromeClientextendsWebChromeClient{

/**输出 Web 端日志 */

@Override

publicbooleanonConsoleMessage(ConsoleMessage consoleMessage){

returnsuper.onConsoleMessage(consoleMessage);

        }

/** * 当前 WebView 加载网页进度 */

@Override

publicvoidonProgressChanged(WebView view,intnewProgress){

super.onProgressChanged(view, newProgress);

        }

/*** Js 中调用 alert() 函数,产生的对话框*/

@Override

publicbooleanonJsAlert(WebView view, String url, String message, JsResult result){

returnsuper.onJsAlert(view, url, message, result);

        }

/** * 处理 Js 中的 Confirm 对话框*/

@Override

publicbooleanonJsConfirm(WebView view, String url, String message, JsResult result){

returnsuper.onJsConfirm(view, url, message, result);

        }

/** * 处理 JS 中的 Prompt对话框 */

@Override

publicbooleanonJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result){

returnsuper.onJsPrompt(view, url, message, defaultValue, result);

        }

/*** 接收web页面的icon*/

@Override

publicvoidonReceivedIcon(WebView view, Bitmap icon){

super.onReceivedIcon(view, icon);

        }

/** * 接收web页面的 Title */

@Override

publicvoidonReceivedTitle(WebView view, String title){

super.onReceivedTitle(view, title);

        }

    }

        4、WebViewClient(帮助WebView处理各种通知、请求事件)常用方法

wvWebview.setWebViewClient(newMyWebViewClient());

publicclassMyWebViewClientextendsWebViewClient{

/*** 当WebView得页面Scale值发生改变时回调 */

@Override

publicvoidonScaleChanged(WebView view,floatoldScale,floatnewScale){

super.onScaleChanged(view, oldScale, newScale);

        }

/** * 是否在 WebView 内加载页面 */

@Override

publicbooleanshouldOverrideUrlLoading(WebView view, String url){

            view.loadUrl(url);

returnsuper.shouldOverrideUrlLoading(view, url);

        }

/** * WebView 开始加载页面时回调,一次Frame加载对应一次回调 */

@Override

publicvoidonPageStarted(WebView view, String url, Bitmap favicon){

super.onPageStarted(view, url, favicon);

        }

/** * WebView 完成加载页面时回调,一次Frame加载对应一次回调 */

@Override

publicvoidonPageFinished(WebView view, String url){

super.onPageFinished(view, url);

        }

/*** WebView 加载页面资源时会回调,每一个资源产生的一次网络加载,除非本地有当前 url 对应有缓存,否则就会加载。 */

@Override

publicvoidonLoadResource(WebView view, String url){

super.onLoadResource(view, url);

        }

/** * WebView 可以拦截某一次的 request 来返回我们自己加载的数据,这个方法在后面缓存会有很大作用。*/

@Override

publicWebResourceResponseshouldInterceptRequest(WebView view, WebResourceRequest request){

returnsuper.shouldInterceptRequest(view, request);

        }

/** * WebView 访问 url 出错 */

@Override

publicvoidonReceivedError(WebView view, WebResourceRequest request, WebResourceError error){

super.onReceivedError(view, request, error);

        }

/*** WebView ssl 访问证书出错,handler.cancel()取消加载,handler.proceed()对然错误也继续加载*/

@Override

publicvoidonReceivedSslError(WebView view, SslErrorHandler handler, SslError error){

super.onReceivedSslError(view, handler, error);

        }

    }

        三、与JS交互

        1、Android调用js方法:2种方式

    js方法:

functioncallJS(){ 

       alert("Android调用了JS的callJS方法");

 }

        (1)第一种方法:loadUrl

wvWebview.loadUrl("javascript:callJS()");

        (2)第二种方法:evaluateJavascript

wvWebview.evaluateJavascript("javascript:callJS()",newValueCallback() {

@Override

publicvoidonReceiveValue(String value){

//此处为 js 返回的结果

                }

            });

        因为该方法的执行不会使页面刷新,而第一种方法(loadUrl )的执行则会。Android 4.4 后才可使用

        所以建议:两种方法混合使用,即Android 4.4以下使用方法1,Android 4.4以上方法2

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

wvWebview.evaluateJavascript("javascript:callJS()",newValueCallback() {

@Override

publicvoidonReceiveValue(String value){

//此处为 js 返回的结果

                }

            });

}else{//Android 4.4 前使用该方法

wvWebview.loadUrl("javascript:callJS()");

        }

        2、js调用Android方法:3种方式

        (1)第一种方法:addJavascriptInterface

        优点:使用简单

        缺点:存在严重的漏洞问题

// js调用方式

    function callAndroid(){

        test.hello("js调用了android中的hello方法");

    }

//通过WebView设置Android类与JS代码的映射

wvWebview.addJavascriptInterface(new AndroidtoJs(), "test");

// 定义JS需要调用的方法

public class AndroidtoJs extends Object {

        // 被JS调用的方法必须加入@JavascriptInterface注解

        @JavascriptInterface

        public void hello(String msg) {

            System.out.println("JS调用了Android的hello方法");

        }

}

        (2)第二种方法:通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url

//js调用

    function callAndroid(){

        document.location="js://webview?arg1=1&arg2=222";

    }

// andorid

// 在Android通过WebViewClient复写shouldOverrideUrlLoading ()

public class MyWebViewClient extends WebViewClient {

         /**

         * 是否在 WebView 内加载页面

         */

    @Override

    public boolean shouldOverrideUrlLoading(WebView view, String url) {

            view.loadUrl(url);

            // 步骤2:根据协议的参数,判断是否是所需要的url

            // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)

            //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)

            Uri uri = Uri.parse(url);

            // 如果url的协议 = 预先约定的 js 协议

            // 就解析往下解析参数

            if (uri.getScheme().equals("js")) {

                // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议

                // 所以拦截url,下面JS开始调用Android需要的方法

                if (uri.getAuthority().equals("webview")) {

                    // 步骤3:

                    // 执行JS所需要调用的逻辑

                    System.out.println("js调用了Android的方法");

                    // 可以在协议上带有参数并传递到Android上

                    HashMap params = new HashMap<>();

                    Set collection = uri.getQueryParameterNames();

                }

                return true;

            }

            return super.shouldOverrideUrlLoading(view, url);

        }

}

        (3)第三种方法:通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息

//js调用

    function clickprompt(){

        var result = prompt("js://demo?arg1=111&arg2=222");

        alert("demo" + result);

    }

//android定义

public class MyWebChromeClient extends WebChromeClient {

    @Override

    public boolean onJsPrompt(WebView view, String url, String message, String             defaultValue, JsPromptResult result) {

            // 根据协议的参数,判断是否是所需要的url(原理同方式2)

            // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)

            //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)

            Uri uri = Uri.parse(message);

            // 如果url的协议 = 预先约定的 js 协议

            // 就解析往下解析参数

            if (uri.getScheme().equals("js")) {

                // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议

                // 所以拦截url,下面JS开始调用Android需要的方法

                if (uri.getAuthority().equals("webview")) {

                    // 执行JS所需要调用的逻辑

                    System.out.println("js调用了Android的方法");

                    // 可以在协议上带有参数并传递到Android上

                    HashMap params = new HashMap<>();

                    Set collection = uri.getQueryParameterNames();

                    //参数result:代表消息框的返回值(输入值)

                    result.confirm("js调用了Android的方法成功啦");

                }

                return true;

            }

            return super.onJsPrompt(view, url, message, defaultValue, result);

        }

}



作者:斌林诚上
链接:https://www.jianshu.com/p/3dc06c3dfb7d


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP