Android 和网页端混合开发小计

WebView 详解

基本用法

  • 加载网页
    //加载网页链接
    mWebView.loadUrl("http://www.itheima.com");
    //加载本地assets目录下的网页
    mWebView.loadUrl("file:///android_asset/demo.html");
  • 加载控制
    webView.reload(); //刷新页面(当前页面的所有资源都会重新加载)
    webView.stopLoading(); //停止加载
  • 控件高度距离
    //获取当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离。
    webView.getScrollY();
    //获取WebView控件的高度。
    webView.getHeight();webView.getBottom();
    //获取HTML的高度(原始高度,不包括缩放后的高度)
    webView.getContentHeight();
  • WebView加载上一页和下一页
    mWebView.goBack();//跳到上个页面
    mWebView.goForward();//跳到下个页面
    mWebView.canGoBack();//是否可以跳到上一页(如果返回false,说明已经是第一页)
    mWebView.canGoForward();//是否可以跳到下一页(如果返回false,说明已经是最后一页)
  • WebView基本设置
    WebSettings settings = mWebView.getSettings();
    settings.setBuiltInZoomControls(true);// 显示缩放按钮(wap网页不支持)
    settings.setUseWideViewPort(true);// 支持双击缩放(wap网页不支持)
    settings.setJavaScriptEnabled(true);// 支持js功能

生命周期

@Override
protected void onResume() {
    super.onResume();
    //恢复webview的状态(不靠谱)
    webView.resumeTimers();
    //激活webView的状态,能正常加载网页
    webView.onResume();
}

@Override
protected void onPause() {
    super.onPause();
    //当页面被失去焦点被切换到后台不可见状态,需要执行onPause
    //通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
    webView.onPause();

    //当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
    //它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。(不靠谱)
    webView.pauseTimers();
}

//在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
//但是注意:webview调用destory时,webview仍绑定在Activity上
//这是由于自定义webview构建时传入了该Activity的context对象
//因此需要先从父容器中移除webview,然后再销毁webview:
ViewGroup parent = findViewById(R.id.container);
parent.removeView(webView);
webView.destroy();

WebViewClient 与 WebChromeClient

  • WebViewClient

    mWebView.setWebViewClient(new WebViewClient() {
        // 开始加载网页
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            System.out.println("开始加载网页了");
        }
    
        // 网页加载结束
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            System.out.println("网页加载结束");
        }
    
        // 所有链接跳转会走此方法
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            System.out.println("跳转链接:" + url);
            view.loadUrl(url);// 在跳转链接时强制在当前webview中加载
    
            //此方法还有其他应用场景, 比如写一个超链接<a href="tel:110">联系我们</a>, 当点击该超链接时,可以在此方法中获取链接地址tel:110, 解析该地址,获取电话号码, 然后跳转到本地打电话页面, 而不是加载网页, 从而实现了webView和本地代码的交互
    
            return true;
        }
    });

    onPageStarted()onPageFinished():页面加载时和页面加载完毕时调用。
    shouldOverrideKeyEvent():重写此方法才能处理浏览器中的按键事件。
    shouldInterceptRequest():页面每一次请求资源之前都会调用这个方法(非UI线程调用)。
    onLoadResource():页面加载资源时调用,每加载一个资源(比如图片)就调用一次。
    onReceivedError():加载页面的服务器出现错误(比如404)时回调。
    onReceivedSslError():重写此方法可以让webview处理https请求。
    doUpdateVisitedHistory():更新历史记录。
    onFormResubmission():应用程序重新请求网页数据。
    onReceivedHttpAuthRequest():获取返回信息授权请求。
    onScaleChanged():WebView发生缩放改变时调用。
    onUnhandledKeyEvent():Key事件未被加载时调用。

  • WebChromeClient

    辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等

    mWebView.setWebChromeClient(new WebChromeClient() {
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
            // 进度发生变化
            System.out.println("进度:" + newProgress);
        }
    
        @Override
        public void onReceivedTitle(WebView view, String title) {
            super.onReceivedTitle(view, title);
            // 网页标题
            System.out.println("网页标题:" + title);
        }
    });

    onReceivedTitle():获得网页的标题时回调。
    onReceivedIcon():获得网页的图标时回调。
    onCreateWindow():打开新窗口时回调。
    onCloseWindow():关闭窗口时回调。

高级用法

缓存

  • 缓存设置
WebSettings settings = mWebView.getSettings();
//只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//只加载缓存
settings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
//根据cache-control决定是否从网络上取数据
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
//不加载缓存
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);   
  • 缓存清楚
//最简便的方式:
mWebView.clearCache(true);

//另外一种方式:
//删除缓存文件夹
File file = CacheManager.getCacheFileBaseDir(); 

if (file != null && file.exists() && file.isDirectory()) { 
  for (File item : file.listFiles()) { 
    item.delete(); 
  } 
  file.delete(); 
} 
//删除缓存数据库
context.deleteDatabase("webview.db"); 
context.deleteDatabase("webviewCache.db");

//清除当前webview访问的历史记录
//只会webview访问历史记录里的所有记录除了当前访问记录
Webview.clearHistory();
//这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
Webview.clearFormData();
  • Cookie设置
    CookieSyncManager.createInstance(this);
    CookieManager cookieManager = CookieManager.getInstance();
    cookieManager.setAcceptCookie(true);

    String cookie = "name=xxx;age=18";
    cookieManager.setCookie(URL, cookie);
    CookieSyncManager.getInstance().sync();
  • 获取Cookie

      CookieManager cookieManager = CookieManager.getInstance();
      String cookie = cookieManager.getCookie(URL);
  • 清除Cookie

      CookieSyncManager.createInstance(context);  
      CookieManager cookieManager = CookieManager.getInstance(); 
    //这个两个在 API level 21 被抛弃
    cookieManager.removeSessionCookie();
    cookieManager.removeAllCookie();
    //Api 21 新增
    //移除所有过期 cookie
    cookieManager.removeSessionCookies();
    //移除所有的 cookie
    cookieManager.removeAllCookies();
    //回调
    CookieManager.getInstance().removeAllCookies(new ValueCallback<Boolean>() {
            @Override
            public void onReceiveValue(Boolean value) {
                // 清除结果
            }
        });
    
    
CookieSyncManager.getInstance().sync();  
#### 高级设置

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

    webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局

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

    webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);  //提高渲染的优先级

    webSettings.setStandardFontFamily("");//设置 WebView 的字体,默认字体为 "sans-serif"
    webSettings.setDefaultFontSize(20);//设置 WebView 字体的大小,默认大小为 16
    webSettings.setMinimumFontSize(12);//设置 WebView 支持的最小字体大小,默认为 8
        webSettings.setVerticalScrollBarEnabled(false); //vertical bar 不显示
        webSettings.setHorizontalScrollBarEnabled(false); // horizontal bar 不显示

    // 5.1以上默认禁止了https和http混用,以下方式是开启
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    }


        //其他
    webSettings.setAllowFileAccess(true); //设置可以访问文件
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
    webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
    webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
    webSettings.setGeolocationEnabled(true);//允许网页执行定位操作

        //分段加载HTML文件
        if (VERSION.SDK_INT >= 21) {
        WebView.enableSlowWholeDocumentDraw();
    }

JavaScript 和 Native 交互

DSBridge-Android

用于JavaScript and native applications 相互调用

  1. 依赖引用

    dependencies {
     //compile 'com.github.wendux:DSBridge-Android:3.0-SNAPSHOT'
     //support the x5 browser core of Tencent
     //compile 'com.github.wendux:DSBridge-Android:x5-3.0-SNAPSHOT'
    }
  2. JavaScript 调用原生

    • 原生提供调用方法

      public class JsApi{
          //for synchronous invocation
            //【err】易错点: msg 这个参数必须是Object否则JavaScript会不识别方法
          @JavascriptInterface
          public String testSyn(Object msg)  {
              return msg + "[syn call]";
          }
      
          //for asynchronous invocation
          @JavascriptInterface
          public void testAsyn(Object msg, CompletionHandler handler) {
              handler.complete(msg+" [ asyn call]");
          }
      }
    • 加入DWebView生效

      import wendu.dsbridge.DWebView
      ...
      DWebView dwebView= (DWebView) findViewById(R.id.dwebview);
      dwebView.addJavascriptObject(new JsApi(), null);
    • JavaScript 项目demo js-call-native.html(需要配置科学上网)

      //cdn
      //<script src="https://unpkg.com/dsbridge@3.1.3/dist/dsbridge.js"> </script>
      //npm
      //npm install dsbridge@3.1.3
      var dsBridge=require("dsbridge")
      //Call synchronously 
      var str=dsBridge.call("testSyn","testSyn");
      
      //Call asynchronously
      dsBridge.call("testAsyn","testAsyn", function (v) {
        alert(v);
      })
      
      //Register javascript API for Native
       dsBridge.register('addValue',function(l,r){
           return l+r;
       })

常用的第三方库

cordova

Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头、麦克风等。

mui

  • mui是最接近原生App体验的前端框架

参考博文

实践案例

参考