Android Webview相关实践汇总

WebView是Android系统中的原生控件,其主要功能与前端页面进行响应交互,快捷省时地实现如期的功能,相当于增强版的内置浏览器。

WebView能做些什么?主要是提供了一个加载H5的控件~可根据需求来配置相关功能。基本使用如下:

布局文件中添加:

   <WebView
        android:id="@+id/id_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

相关权限设置:

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

java文件中调用:

WebView itWebview = findviewbyId(R.id.id_webview);
itWebview.loadUrl("https://m.baidu.com");

这样就加载一个网络连接了,加载本地连接如下:


//打开本包内asset目录下的test.html文件

wView.loadUrl(" file:///android_asset/test.html ");   

//打开本地sd卡内的index.html文件

wView.loadUrl("content://com.android.htmlfileprovider/sdcard/index.html");

//打开指定URL的html文件

wView.loadUrl(" http://m.baidu.com"); 

以上是简单的使用。想要完全掌握使用webview,还得深入去了解webview的相关组成。WebView这个控件又包含四大部分:WebSettings、WebViewClient、WebChromeClient、JavascriptInterface。通过四个类,我们可以为WebView设置基础功能和监听,下面会逐一介绍四个类的方法。除了这四部分,WebView还有自己的API,先来介绍WebView的API。

      // 加载url:
      webView.loadUrl(url)

      // 往请求头header增加参数
      val hashMap: HashMap<String, String> = HashMap()
      hashMap["name"] = "zhangsan"
      webView.loadUrl(url, hashMap)

      // 加载 HTML 页面的一小段内容
      webView.loadData("", "text/html", "utf-8")
      webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null)

      // 后退、前进:
      webView.canGoBack() //是否可以后退
      webView.goBack() //后退一页面
      webView.canGoForward() //是否可以前进
      webView.goForward() //前进一页面
      webView.goBackOrForward(-1) //后退或前进多少步,正前负退

      //清除缓存数据:
      // 清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
      webView.clearCache(true)
      // 清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
      webView.clearHistory()
      // 这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据。
      webView.clearFormData()

      //WebView的状态
      webView.onResume() // 可见状态
      webView.onPause() // 页面失去焦点变成不可见状态
      webView.pauseTimers() // 页面失去焦点变成不可见状态,对整个应用的webview起作用
      webView.resumeTimers() //恢复pauseTimers时的动作
      webView.destroy() //销毁
  • WebSettings 用于webview的相关设置、配置项,如缓存、自适应屏幕、缩放、js支持等,如下:
        WebSettings webSettings = itWebview.getSettings();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
        webSettings.setJavaScriptEnabled(true);
// 若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
// 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可

//设置自适应屏幕,两者合用
        webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
        webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

//缩放操作
        webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
        webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
        webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

//其他细节操作
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); //关闭webview中缓存
        webSettings.setAllowFileAccess(true); //设置可以访问文件
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
        webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
        webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

WebViewClient  :处理各种通知和事件,如页面开始,页面加载结束,error,重定向等,其中用的最多的是shouldOverrideUrlLoading、onPageStarted、onPageFinished

      itWebview.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
               //在网页上的所有加载都经过这个方法
               //比如在本地WebView加载H5,而不是浏览器
                return super.shouldOverrideUrlLoading(view, url);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return super.shouldOverrideUrlLoading(view, request);
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
            }

            @Override
            public void onLoadResource(WebView view, String url) {
 // 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
                super.onLoadResource(view, url);
            }

            @Nullable
            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
  // 拦截替换网络请求数据
                return super.shouldInterceptRequest(view, request);
            }

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
// (报告错误信息,当加载出错的时候会回调此方法)
                super.onReceivedError(view, request, error);
            }

            @Override
            public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
 //重写此方法才能够处理在浏览器中的按键事件。
                return super.shouldOverrideKeyEvent(view, event);
            }

            @Override
            public void onScaleChanged(WebView view, float oldScale, float newScale) {
 // (WebView缩放大小发生改变时调用)
                super.onScaleChanged(view, oldScale, newScale);
            }
        });

在android 7.0系统以上 已经摒弃了shouldOverrideUrlLoading(WebView view, String url)此方法,所以,如果要拦截URL,我们需要做兼容性处理,重写shouldOverrideUrlLoading(WebView view, WebResourceRequest request)方法,获取得到的可正常使用的URL。shouldOverrideUrlLoading(WebView view, WebResourceRequest request)是可以通过request.getUrl()获取到WebView需要加载的地址,然后通过shouldOverrideUrlLoading(WebView view, String url)此方法显示加载。

@Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                view.loadUrl(request.getUrl().toString());
            } else {
                view.loadUrl(request.toString());
            }
            return true;
        }

一般 会用该接口实现 shouldOverrideUrlLoading,用于处理拦截url和内部加载

        itWebview.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
//           后续的条子只在本webview中进行,不会跳转到外部的浏览器 
      //H5调起微信app支付方法二(可使用)
                if (url.startsWith("weixin://wap/pay?")) {
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_VIEW);
                    intent.setData(Uri.parse(url));
                    startActivity(intent);

                    return true;
                }
                if(url.startsWith("alipays:") || url.startsWith("alipay")) {
                    try {
                        startActivity(new Intent("android.intent.action.VIEW", Uri.parse(url)));
                    } catch (Exception e) {
                        new AlertDialog.Builder(WebActivity.this)
                                .setMessage("未检测到支付宝客户端,请安装后重试。")
                                .setPositiveButton("立即安装", new DialogInterface.OnClickListener() {

                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        Uri alipayUrl = Uri.parse("https://d.alipay.com");
                                        startActivity(new Intent("android.intent.action.VIEW", alipayUrl));
                                    }
                                }).setNegativeButton("取消", null).show();
                    }
                    return true;
                }
                if (!(url.startsWith("http") || url.startsWith("https"))) {
                    return true;
                }
                view.loadUrl(url);
                return false;
            }
            
        });

WebChromeClient内核处理类,主要用于网站的加载进度、标题、图片文件选择、JS弹窗


        itWebview.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
// 网页加载进度
                super.onProgressChanged(view, newProgress);
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
// 网页title
                super.onReceivedTitle(view, title);
            }

            @Override
            public void onReceivedIcon(WebView view, Bitmap icon) {
// 网页图标
                super.onReceivedIcon(view, icon);
            }

            @Override
            public void onCloseWindow(WebView window) {
// 窗口关闭
                super.onCloseWindow(window);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
// JS交互确认框
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public void onPermissionRequest(PermissionRequest request) {
                super.onPermissionRequest(request);
            }

            @Override
            public void onPermissionRequestCanceled(PermissionRequest request) {
                super.onPermissionRequestCanceled(request);
            }

            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
// 调用的文件选择器
                return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
            }
        });

JavascriptInterface:       可以通过addJavascriptInterface()设置JavascriptInterface,从而使JS可以直接调用JavascriptInterface设置好的方法,比如H5想要跳转Activity、打开原生视频等都可以通知App。
webview

1. 通过JS调用Android原生代码

itWebview.addJavascriptInterface(new H5BridgeInterface(H5WebActivity.this), "H5BridgeInterface");
H5WebActivity相关代码
package cn.zeus.jondy.h5;

import android.app.DownloadManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.PersistableBundle;
import android.webkit.DownloadListener;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.URLUtil;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import cn.zeus.jondy.R;
import cn.zeus.jondy.utils.Lg;


public class H5WebActivity extends AppCompatActivity {
    private static final String TAG = H5WebActivity.class.getSimpleName();
    private static final String webUrl = "file:///android_asset/h5/test.html";
    private WebView itWebview;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Lg.d("onCreate ---");
        setContentView(R.layout.activity_web);
        itWebview = findViewById(R.id.it_webview);
        initWebview();

    }

    private void initWebview() {
        Lg.d("initWebview ---");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            itWebview.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }

        WebSettings webSettings = itWebview.getSettings();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
        webSettings.setJavaScriptEnabled(true);
// 若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
// 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可

//设置自适应屏幕,两者合用
        webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
        webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

//缩放操作
        webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
        webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
        webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
//其他细节操作
//        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); //关闭webview中缓存
        webSettings.setAllowFileAccess(true); //设置可以访问文件
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
        webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
        webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

        itWebview.loadUrl(webUrl);

        itWebview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {//使用WebView加载显示url
                view.loadUrl(url);
                //返回true
                return true;
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                Lg.e("onPageStarted :---"+url);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                Lg.e("onPageFinished :---"+url);
            }

            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                super.onReceivedError(view, errorCode, description, failingUrl);
                Lg.e("onReceivedError :---"+failingUrl);
            }

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);

            }

            @Override
            public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
                super.onReceivedHttpError(view, request, errorResponse);
                Lg.e("onReceivedError :---"+errorResponse.getStatusCode());
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                super.onReceivedSslError(view, handler, error);
                Lg.e("onReceivedError :---"+error.getUrl());
            }
        });

        itWebview.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                Lg.d("onProgressChanged :---"+newProgress);
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }

            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
        });

        itWebview.addJavascriptInterface(new H5BridgeInterface(H5WebActivity.this), "H5BridgeInterface");

        itWebview.setDownloadListener(new DownloadListener() {
            @Override
            public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
//                startDownload(url);
                Lg.d("download ,url :" + url);
                Lg.d("download ,mimetype :" + mimetype);
                Lg.d("download ,contentDisposition :" + contentDisposition);
                downloadBySystem(url, contentDisposition, mimetype);
            }
        });
    }

    private void downloadBySystem(String url, String contentDisposition, String mimeType) {
        // 指定下载地址
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        // 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库
        request.allowScanningByMediaScanner();
        // 设置通知的显示类型,下载进行时和完成后显示通知
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        // 设置通知栏的标题,如果不设置,默认使用文件名
//        request.setTitle("This is title");
        // 设置通知栏的描述
//        request.setDescription("This is description");
        // 允许在计费流量下下载
        request.setAllowedOverMetered(false);
        // 允许该记录在下载管理界面可见
        request.setVisibleInDownloadsUi(false);
        // 允许漫游时下载
        request.setAllowedOverRoaming(true);
        // 允许下载的网路类型
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
        // 设置下载文件保存的路径和文件名
        if (mimeType.equalsIgnoreCase("application/octet-stream")) {
            mimeType = "image/jpeg";
        }
        request.setMimeType(mimeType);
        String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
        Lg.d("download fileName :" + fileName);
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
//        另外可选一下方法,自定义下载路径
//        request.setDestinationUri()
//        request.setDestinationInExternalFilesDir()
        final DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        // 添加一个下载任务
        long downloadId = downloadManager.enqueue(request);
        Lg.d("download downloadId :" + downloadId);
    }


}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值