ndfweb.cn

AndroidStudio之WebView詳解


2023-06-20 17:22:21 (1683)



簡介:

WebView是一個基於webkit引擎、展現web頁麵的控件。

Android的Webview在低版本和高版本采用了不同的webkit版本內核,4.4後直接使用了Chrome。


作用:

1、 顯示和渲染Web頁麵

2、 直接使用html文件(網絡上或本地assets中)作布局

3、 可和JavaScript交互調用


使用介紹:

一般來說Webview可單獨使用,可聯合其子類一起使用:

1、 Webview自身的常見方法;

2、 Webview的最常用的子類(WebSettings類、WebViewClient類、WebChromeClient類)

3、 Android和Js的交互


WebView常用方法:

1. WebView的狀態

協同安卓生命周期,做激活銷毀等


//激活WebView為活躍狀態,能正常執行網頁的響應

webView.onResume() ;

//當頁麵被失去焦點被切換到後台不可見狀態,需要執行onPause

//通過onPause動作通知內核暫停所有的動作,比如DOM的解析、plugin的執行、JavaScript執行。

webView.onPause();

//當應用程序(存在webview)被切換到後台時,這個方法不僅僅針對當前的webview而是全局的全應用程序的webview

//它會暫停所有webview的layout,parsing,javascripttimer。降低CPU功耗。

webView.pauseTimers()

//恢複pauseTimers狀態

webView.resumeTimers();

//銷毀Webview

//在關閉了Activity時,如果Webview的音樂或視頻,還在播放。就必須銷毀Webview

//但是注意:webview調用destory時,webview仍綁定在Activity上

//這是由於自定義webview構建時傳入了該Activity的context對象

//因此需要先從父容器中移除webview,然後再銷毀webview:

rootLayout.removeView(webView); 

webView.destroy();


根據場景做一些清除緩存數據


//清除網頁訪問留下的緩存

//由於內核緩存是全局的因此這個方法不僅僅針對webview而是針對整個應用程序.

Webview.clearCache(true);

//清除當前webview訪問的曆史記錄

//隻會webview訪問曆史記錄裏的所有記錄除了當前訪問記錄

Webview.clearHistory();

//這個api僅僅清除自動完成填充的表單數據,並不會清除WebView存儲到本地的數據

Webview.clearFormData();


2.WebView的行為

前進與後退


//是否可以後退

Webview.canGoBack() 

//後退網頁

Webview.goBack()

//是否可以前進                     

Webview.canGoForward()

//前進網頁

Webview.goForward()


//以當前的index為起始點前進或者後退到曆史記錄中指定的steps

//如果steps為負數則為後退,正數則為前進

Webview.goBackOrForward(intsteps) 


Back鍵控製網頁後退


問題:在不做任何處理前提下 ,瀏覽網頁時點擊係統的“Back”鍵,整個 Browser 會調用 finish()而結束自身

目標:點擊返回後,是網頁回退而不是退出瀏覽器

解決方案:在當前Activity中處理並消費掉該 Back 事件

public boolean onKeyDown(int keyCode, KeyEvent event) {

    if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) { 

        mWebView.goBack();

        return true;

    }

    return super.onKeyDown(keyCode, event);

}

1

2

3

4

5

6

7

3.WebView常用類

一` WebSettings類

1.作用:對WebView進行配置和管理

2.配置步驟 & 常見方法:


步驟一:添加訪問網絡權限(AndroidManifest.xml)

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

1

步驟二:配置步驟2:生成一個WebView組件(有兩種方式)

//方式1:直接在在Activity中生成

WebView webView = new WebView(this)

//方法2:在Activity的layout文件裏添加webview控件:

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

1

2

3

4

配置步驟3:進行配置-利用WebSettings子類(常見方法 看情況使用)

//聲明WebSettings子類

WebSettings webSettings = webView.getSettings();

//如果訪問的頁麵中要與Javascript交互,則webview必須設置支持Javascript

webSettings.setJavaScriptEnabled(true);  

//支持插件

webSettings.setPluginsEnabled(true); 

//設置自適應屏幕,兩者合用

webSettings.setUseWideViewPort(true); //將圖片調整到適合webview的大小 

webSettings.setLoadWithOverviewMode(true); // 縮放至屏幕的大小

//縮放操作

webSettings.setSupportZoom(true); //支持縮放,默認為true。是下麵那個的前提。

webSettings.setBuiltInZoomControls(true); //設置內置的縮放控件。若為false,則該WebView不可縮放

webSettings.setDisplayZoomControls(false); //隱藏原生的縮放控件

//其他細節操作

webSettings.setAllowFileAccess(true); //設置可以訪問文件 

webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通過JS打開新窗口 

webSettings.setLoadsImagesAutomatically(true); //支持自動加載圖片

webSettings.setDefaultTextEncodingName("utf-8");//設置編碼格式

webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);//設置混合內容模式(需要判斷版本號)

webSettings.setTextZoom(100);//設置文字大小 100為正常 120為120%

//結合使用(離線加載)

webSettings.getSettings().setDomStorageEnabled(true);//啟用Dom存儲

if (NetStatusUtil.isConnected(getApplicationContext())) {

    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根據cache-control決定是否從網絡上取數據。

} else {

    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//沒網,則從本地獲取,即離線加載

}

webSettings.setDomStorageEnabled(true); // 開啟 DOM storage API 功能

webSettings.setDatabaseEnabled(true);   //開啟 database storage API 功能

webSettings.setAppCacheEnabled(true);//開啟 Application Caches 功能

String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;

webSettings.setAppCachePath(cacheDirPath); //設置  Application Caches 緩存目錄

 //優先使用緩存: 

webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 

     //緩存模式如下:

    //LOAD_CACHE_ONLY: 不使用網絡,隻讀取本地緩存數據

    //LOAD_DEFAULT: (默認)根據cache-control決定是否從網絡上取數據。

    //LOAD_NO_CACHE: 不使用緩存,隻從網絡獲取數據.

    //LOAD_CACHE_ELSE_NETWORK,隻要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。

//不使用緩存: 

webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);


二` WebViewClient類

1.作用:處理各種通知 & 請求事件

2. 常見方法:


方法一:shouldOverrideUrlLoading()

作用:打開網頁時不調用係統瀏覽器, 而是在本WebView中顯示;在網頁上的所有加載都經過這個方法,這個函數我們可以做很多操作。

//步驟1. 定義Webview組件

Webview webview = (WebView) findViewById(R.id.webView1);

//步驟2.websettings的各種配置

WebSettings webSettings = webView.getSettings();//webSettings.setxxx();

//步驟3. 選擇加載方式

  //方式1. 加載一個網頁:

  webView.loadUrl("http://www.google.com/");

  //方式2:加載apk包中的html頁麵

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

  //方式3:加載手機本地的html頁麵

   webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");

//步驟4. 複寫shouldOverrideUrlLoading()方法,使得打開網頁時不調用係統瀏覽器, 而是在本WebView中顯示

    webView.setWebViewClient(new WebViewClient(){

      @Override

      public boolean shouldOverrideUrlLoading(WebView view, String url) {

          view.loadUrl(url);

      return true;

      }

  });


方法二:onPageStarted()

作用:開始載入頁麵調用的,我們可以設定一個loading的頁麵,告訴用戶程序在等待網絡響應。

webView.setWebViewClient(new WebViewClient(){

      @Override

      public void  onPageStarted(WebView view, String url, Bitmap favicon) {

         //設定加載開始的操作

      }

  });

1

2

3

4

5

6

方法三:onPageFinished()

作用:在頁麵加載結束時調用。我們可以關閉loading 條,切換程序動作。

webView.setWebViewClient(new WebViewClient(){

      @Override

      public void onPageFinished(WebView view, String url) {

         //設定加載結束的操作

      }

  });

1

2

3

4

5

6

方法四:onLoadResource()

作用: 在加載頁麵資源時會調用,每一個資源(比如圖片)的加載都會調用一次。

  webView.setWebViewClient(new WebViewClient(){

      @Override

      public boolean onLoadResource(WebView view, String url) {

         //設定加載資源的操作

      }

  });

1

2

3

4

5

6

方法五:onReceivedError()

作用:加載頁麵的服務器出現錯誤時(如404)調用。 App裏麵使用webview控件的時候遇到了諸如404這類的錯誤的時候,若也顯示瀏覽器裏麵的那種錯誤提示頁麵就顯得很醜陋了,那麼這個時候我們的app就需要加載一個本地的錯誤提示頁麵,即webview如何加載一個本地的頁麵

//步驟1:寫一個html文件(error_handle.html),用於出錯時展示給用戶看的提示頁麵

//步驟2:將該html文件放置到代碼根目錄的assets文件夾下


//步驟3:複寫WebViewClient的onRecievedError方法

//該方法傳回了錯誤碼,根據錯誤類型可以進行不同的錯誤分類處理

  webView.setWebViewClient(new WebViewClient(){

     @Override

          public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {

              super.onReceivedError(view, request, error);

              // 自定義錯誤提示頁麵

              String errorHtml = "<html><body style='background-color:#e5e5e5;text-align: center;padding-top:80px;font-size:30px;'><h1>網絡繁忙!</h1></body></html>";

              view.loadData(errorHtml, "text/html", "UTF-8");

          }

      });

1

2

3

4

5

6

7

8

9

10

11

12

13

14

方法六:onReceivedSslError()

作用:處理https請求

webView.setWebViewClient(new WebViewClient() {    

        @Override    

        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {    

            handler.proceed();    //表示等待證書響應

        // handler.cancel();      //表示掛起連接,為默認方式

        // handler.handleMessage(null);    //可做其他處理

        }    

    }); 

1

2

3

4

5

6

7

8

三` WebViewClient類

1.作用:輔助 WebView 處理 Javascript 的對話框,網站圖標,網站標題等等。

2.常見使用:


方法一:onProgressChanged()

作用:獲得網頁的加載進度並顯示。

webview.setWebChromeClient(new WebChromeClient(){

      @Override

      public void onProgressChanged(WebView view, int newProgress) {

          if (newProgress < 100) {

              String progress = newProgress + "%";

              progress.setText(progress);

            } else {

        }

    });

1

2

3

4

5

6

7

8

9

方法二:onReceivedTitle()

作用:獲取Web頁中的標題

每個網頁的頁麵都有一個標題,比如www.baidu.com這個頁麵的標題即“百度一下,你就知道”,那麼如何知道當前webview正在加載的頁麵的title並進行設置呢?

webview.setWebChromeClient(new WebChromeClient(){

    @Override

    public void onReceivedTitle(WebView view, String title) {

       titleview.setText(title);

    }

1

2

3

4

5

4.WebView與JS的交互

借張思維導圖:


Android與JS通過WebView互相調用方法,實際上是:


Android去調用JS的代碼

JS去調用Android的代碼

Android調用JS代碼的方法有2種:

(1) 通過WebView的loadUrl()

(2) 通過WebView的evaluateJavascript()

對於JS調用Android代碼的方法有3種:

(1) 通過WebView的addJavascriptInterface()進行對象映射

(2) 通過 WebViewClient 的shouldOverrideUrlLoading ()方法回調攔截 url

(3) 通過 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調攔截JS對話框alert()、confirm()、prompt() 消息

4.如何避免WebView內存泄露

不在xml中定義 Webview ,而是在需要的時候在Activity中創建,並且Context使用 getApplicationgContext()

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

       mWebView = new WebView(getApplicationContext());

       mWebView.setLayoutParams(params);

       mLayout.addView(mWebView);

1

2

3

4

在 Activity 銷毀( WebView )的時候,先讓 WebView 加載null內容,然後移除 WebView,再銷毀 WebView,最後置空。

@Override

    protected void onDestroy() {

        if (mWebView != null) {

            mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);

            mWebView.clearHistory();


            ((ViewGroup) mWebView.getParent()).removeView(mWebView);

            mWebView.destroy();

            mWebView = null;

        }

        super.onDestroy();

    }


交互

加載頁麵

//加載assets文件夾下的test.html頁麵,文件截圖如圖1*

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

//加載網頁*

mWebView.loadUrl("http://www.baidu.com");

1

2

3

4

Android調用JS方法

 WebSettings webSettings = mWebView.getSettings();

//設置為可調用js方法* 

webSettings.setJavaScriptEnabled(true);

//調用JS中無參的show方法

mWebView.loadUrl("JavaScript:show()");

//Android調用H5中帶返回值的方法()該方法隻在安卓4.4以上版本適用 

mWebView.evaluateJavascript("sum(1,2)",new ValueCallback() {        

       @Override

      public void on ReceiveValue(String value) {           

          Log.e(TAG,"onReceiveValue value=" + value);       

    }   

});

//當調用H5中帶參數的方法時,勢必要傳入一個字符串,當傳入固定字符串時,用單引號括起來即可;當傳入變量名時,需要用到轉義符

mWebView.loadUrl("javascript:alertMessage('哈哈')");

mWebView.loadUrl(  "javascript:alertMessage(\" " +content+ "\")");//String content="9880";*



JS調用Android方法

H5調用Android裏的方法,相對複雜一些,雙方具體操作如下:

Android需要做什麼呢?????

說白了就是新建一個類,裏麵寫提供給H5操作的方法,並規定別名。這裏我新建的class為JsInteration,方法為back(),規定的別名為android。先貼截圖,後貼代碼。*


在安卓4.2以上可以直接使用@JavascriptInterface注解來聲明,下麵是在一個本地Java方法


public  class  JsInteration  {

      @JavascriptInterface

      public  String  back() {

             return "hello world";   

       }

}

//定義完這個方法後再調用mWebView.addJavascriptInterface()方法:

mWebView.addJavascriptInterface(newJsInteration(),"android");


在H5中怎麼來調用呢?

調用格式為 window.別名.android中的方法名(parameter Values) ,此示例中我們用的別名為android,方法名為back()。

下圖:


代碼:


function s() {

      var result=window.android.back();

      document.getElementById("p").innerHTML=result;

}


完整代碼:

activity:

package com.e_valmont.javaandjsinteractivedemo;


import android.annotation.SuppressLint;

import android.annotation.TargetApi;

import android.os.Build;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.webkit.JavascriptInterface;

import android.webkit.ValueCallback;

import android.webkit.WebChromeClient;

import android.webkit.WebSettings;

import android.webkit.WebView;

import android.webkit.WebViewClient;

import android.widget.Toast;


public class MainActivity extends AppCompatActivity{


    private static final String TAG = "MainActivity";

    private WebView mWebView;


    @SuppressLint("JavascriptInterface")

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        mWebView = (WebView) findViewById(R.id.webview);

        mWebView.loadUrl("file:///android_asset/js_java_interaction.html");//加載本地asset下麵的js_java_interaction.html文件

        //mWebView.loadUrl("https://www.baidu.com/");//加載本地assets下麵的js_java_interaction.html文件


        WebSettings webSettings = mWebView.getSettings();

        webSettings.setJavaScriptEnabled(true);//打開js支持

        /**

         * 打開js接口給H5調用,參數1為本地類名,參數2為別名;h5用window.別名.類名裏的方法名才能調用方法裏麵的內容,例如:window.android.back();

         * */

        mWebView.addJavascriptInterface(new JsInteration(), "android");

        mWebView.setWebViewClient(new WebViewClient());

        mWebView.setWebChromeClient(new WebChromeClient());

    }


    /**

     * 自己寫一個類,裏麵是提供給H5訪問的方法

     * */

    public class JsInteration {


        @JavascriptInterface//一定要寫,不然H5調不到這個方法

        public String back() {

            return "我是java裏的方法返回值";

        }

    }


    //點擊按鈕,訪問H5裏帶返回值的方法

    @TargetApi(Build.VERSION_CODES.KITKAT)

    public void onClick(View v) {

        Log.e("TAG", "onClick: ");


//        mWebView.loadUrl("JavaScript:show()");//直接訪問H5裏不帶返回值的方法,show()為H5裏的方法



        //傳固定字符串可以直接用單引號括起來

        mWebView.loadUrl("javascript:alertMessage('哈哈')");//訪問H5裏帶參數的方法,alertMessage(message)為H5裏的方法


        //當出入變量名時,需要用轉義符隔開

        String content="9880";

        mWebView.loadUrl("javascript:alertMessage(\""   +content+   "\")"   );



        //Android調用有返回值js方法,安卓4.4以上才能用這個方法

        mWebView.evaluateJavascript("sum(1,2)", new ValueCallback<String>() {

            @Override

            public void onReceiveValue(String value) {

                Log.d(TAG, "js返回的結果為=" + value);

                Toast.makeText(MainActivity.this,"js返回的結果為=" + value,Toast.LENGTH_LONG).show();

            }

        });

    }

}



js:


<html>

    <head>

        <!--從assert中加載的中文網頁會出現亂碼,解決辦法就是給html指定編碼-->

        <meta http-equiv="content-type" content="text/html;charset=gb2312">

        <title>

        </title>



    </head>

    <body>

        這是html頁麵 <br/>

        <button onclick="s()">點擊調用本地方法</button>

        <a href="file:///android_asset/js_java_interaction.html">點擊跳轉到原生頁麵</a>

        <p id="p"></p>


        <script type="text/javascript">


            //有參有返回值的方法

            function sum(a,b) {

                <!--gygguuuiu-->

                return a+b;

            }


            //有參無返回值的方法

            function alertMessage(message) {

                alert(message);

            }


            //無參無返回值的方法

            function show(){

                //顯示hello world

                document.getElementById("p").innerHTML="hello world";

            }


            function s() {

                //調用原生的方法,android為約定的別名;back()為原生的方法

                var result=window.android.back();

                //將返回結果顯示在id為p的控件上

                document.getElementById("p").innerHTML=result;

            }

        </script>

    </body>

</html>


注意事項

(1)當自己寫html文件時,可能會出現顯示亂碼,我們需要指定格式

(2)當H5調用我們的方法時,我們需要把規定的別名傳給H5(切記一定不能錯),而且我們要在自己的方法裏執行H5想要的操作


(3)給H5調用的方法一定要加@JavascriptInterface,不然H5調不到我們的方法


(4) 調用js有參數有返回值的函數時,隻有安卓4.4以上才能用webView.evaluateJavascript方法直接拿到返回值;當版本低於4.4的時候,常用的思路是 java調用js方法,js方法執行完畢,再次調用java代碼將值返回

①.Java調用JS代碼

String call = "javascript:sumToJava(1,2)";

webView.loadUrl(call);

1

2

②.js函數處理,並將結果通過調用java方法返回

function sumToJava(number1, number2){

  window.control.onSumResult(number1 + number2)}

1

2

③.Java在回調方法中獲取js函數返回值

@JavascriptInterface

public void onSumResult(int result) {

Log.i(LOGTAG, "onSumResult result=" + result);}



本文版权:http://www.ndfweb.cn/news-928.html
  NDF俱乐部
  国际域名注册
  建站咨询
简体中文 NDF网站建设淘宝店 | ICO图标在线生成 | 外贸网站建设 | 联系我们
©2007-2025 NDF Corporation 鲁ICP备08005967号 Sitemap - RSSRSS订阅