Android 原生 WebView 與 JavaScript 交互

如今的純原生的 APP 不多見了,幾乎都是原生中嵌者網頁的 hybird APP,或者直接使用 React Native 開發。原生 App 中嵌者網頁原生與網頁中 JavaScript 的交互幾乎沒法避免,畢竟在本身的應用中嵌入網頁不僅是想讓應用當個瀏覽器用。
Android 原生中加載網頁的控件是 WebView,所以要想原生與 JavaScript 交互也同樣必須經過 WebView 來實現。javascript

相關類和主要方法

WebView

低版本和高版本的 Android 系統中 WebView 採用不一樣的內核, Android 4.4 以後直接使用了 Chrome 的內核。
經常使用方法:html

//根據 url 去加載一個網頁
webView.loadUrl(String url);

//根據 HTML 數據顯示出內容,其中 loadData() 方法的 data 中不能出現英文的 %,#,\,? 四個字符,不然可能會報錯
webView.loadData(String data,String mimeType,String encoding);
webView.loadDataWithBaseUrl(String baseUrl,String mimeType,String encoding,String historyUrl);

// webView 處於激活狀態,能正常加載和響應網頁
webView.onResume();

// webView 處於暫停狀態,當頁面失去焦點切換到後臺時調用
// 處於 pause 狀態的 WebView 會中止動畫和計算,可是不會中止 JavaScript 的執行
webView.onPause();

//暫停全部 WebView 的 layout、parsing、JavaScriptTimers 以下降 CPU 消耗(全局有效)
webView.pauseTimers();

// 恢復 pauseTimers 的暫停狀態
webView.resumeTimers();

// 銷燬一個 WebView 時要先將 WebView 和當前界面解綁再銷燬
parentLayout.removeView(webView);
webView.destroy();

// 判斷網頁是否能夠後退(能夠實現監聽,當網頁能夠後退事點擊返回鍵和返回按鈕不退出瀏覽界面)
webView.canGoBack();

//後退網頁
webView.goBack();

// 判斷網頁是否能夠前進
webView.canGoForward();

//前進網頁
webView.goForward();

//以當前頁爲起點前進後退 steps 個頁面(正數前進,負數後退)
webView.goBackOrForward(int steps);複製代碼

WebSetting

WebSetting 是爲 WebView 提供配置和管理的一個抽象類,它經過 webView.getSettings() 方法獲取實例。
經常使用方法:前端

// 設置 webView 是否支持 JavaScript 的調用(應用中涉及原生與 JS 交互的必須設置爲 true)
webSettings.setJavaScriptEnabled(true);

// 設置是否容許 JS 開啓新窗口(function window.open())
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

// 設置 webView 是否支持插件
webSettings.setPluginsEnable(true);

// 設置編碼方式

// 設置是否自適應屏幕,(通常圖片和網頁縮放同時使用)
webSettings.setUseWideViewPort(true); //將圖片調整到適合 webView 的大小
webSettings.setLoadWithOverviewMode(true); //縮放至屏幕的大小(顯示未作移動端兼容的 PC 網頁)

// 設置是否支持縮放,默認爲支持
webSettings.setSupportZoom(true);
// 設置內置的縮放控件
webSettings.setBuiltInZoomControls(true);
// 隱藏原生的縮放控件
webSettings.setDisplayZoomControls(true);複製代碼

WebViewClient

WebViewClient 主要用來幫助 WebView 處理請求的各類狀態事件。
經常使用方法:java

// 頁面開始加載的時候回調
onPageStarted(WebView view, String url, Bitmap favicon);
// 頁面加載結束時回調
onPageFinished(WebView view, String url);
// 將要加載資源時回調,每次資源的加載都會調用
onLoadResource(WebView view, String url);
// 加載的頁面 404 時將會回調
onReceivedError(WebView view, WebResourceRequest request, WebResourceError error);複製代碼

webView 默認狀況下是不會加載 https 請求的,頁面將顯示空白,若是加載 https 頁面須要進行以下設置:git

webView.setWebViewClient(new WebViewClient() {    
        @Override    
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {    
            handler.proceed();    //表示等待證書響應
        // handler.cancel(); //表示掛起鏈接,爲默認方式
        // handler.handleMessage(null); //可作其餘處理
        }    
    });複製代碼

WebChromeClient

輔助 WebView 處理 JavaScript 對話框,加載進度,網頁圖標等。
經常使用方法:github

// 加載進度回調
onProgressChanged(WebView view, int newProgress);
// 獲取到網頁 Title 回調
onReceivedTitle(WebView view, String title);
// 獲取到網頁圖標回調
onReceivedIcon(WebView view, Bitmap icon);複製代碼

WebView 的使用

經過前面的瞭解,WebView 及他的輔助類的一些基本方法咱們是知道了,接下來就看一下一下怎麼使用 WebView 以及怎樣經過 WebView 讓 Android 源生代碼與 JavaScript 代碼進行交互。web

JS 調用原生方法

JS 調用源生的方法時該方法必需要加上 @JavascriptInterface 註解,咱們能夠定義一個類或者接口來單獨存放用於 JS 調用的方法,這裏我以接口爲例。接口中提供一個 getUrl(String url) 方法用於提供給 JS 調用,傳遞一個 String 類型的值給源生方法:chrome

/** * Created by PandaQ on 2017/3/22. * JS 接口方法定義 * 接口中定義方法時不用加註解,使用時才加註解 */
public interface JavaScriptFunction {
    void getUrl(String string);
}複製代碼
// 此代碼片斷爲 PandaEye 中點擊加載的 html 數據中的圖片跳轉到新的 Activity 顯示圖片的功能
webView.addJavascriptInterface(new JavaScriptFunction() {
            @Override
            @JavascriptInterface // 加上註解 getUrl() 方法才能被 JS 調用
            public void getUrl(String imageUrl) {
                LogWritter.LogStr(imageUrl);
                Intent intent = new Intent();
                intent.putExtra("imageUrls", mImageUrls);
                intent.putExtra("curImageUrl", imageUrl);
                intent.setClass(ZhihuStoryInfoActivity.this, PhotoViewActivity.class);
                startActivity(intent);
            }
        }, "JavaScriptFunction");複製代碼
// 在 HTML 中圖片的點擊事件 JS 方法中就能夠執行以下代碼來調用源生的接口方法
function(){
    window.JavaScriptFunction.getUrl(this.src);
}複製代碼

原生調用 JS

在熊貓眼 PandaEye 中由於使用的知乎日報和網易新聞的 API 因此下發的 HTML body 數據須要咱們本身加個 HTML 的殼,而後再源生加載咱們須要的 JavaScrpit 代碼來實現咱們的功能。
加載 JS 能夠直接 webView.load() 加載完整的 JS 代碼也能夠在本身加的 head 節點引入 JS 文件而後 webView 直接 load 其中的方法, PandaEye 中使用的是第二種方法:
在拼裝 HTML 時在 head 中引入放在 asset 文件夾中的 js 文件瀏覽器

enter description here
enter description here

imageClick.js 中的內容以下:ide

function initClick() {
    var objects = document.getElementsByTagName("img");
    for(var i=0;i<objects.length;i++)
    {
        objects[i].onclick= function (){
            window.JavaScriptFunction.getUrl(this.src);
        }
    }
}複製代碼

而後在 WebChromeClient 當加載進度達到 100% 後去調用 JS 文件中的 initClick() 方法,爲每一張圖片設置點擊事件:

/** * 爲全部的圖片添加點擊事件 * * @param webView 對應的 WebView */
    private void addImageClickListener(WebView webView) {
        webView.loadUrl("javascript:(initClick())()");
    }複製代碼

直接加載 JS 把 initClick() 用 JS 代碼替換掉便可。

利用 Chrome 調試 WebView

WebView 中 JavaScript 代碼的調試直接使用 AndroidStudio 是沒辦法的,那麼咱們怎樣調試 HTML 頁面呢?答案是用 Chrome 瀏覽器來調試:

  • USB 選項是打開的(AS 能調試應用就行)
  • Chrome 瀏覽器打開地址:chrome://inspect 或者 about:inspect
    打開待調試的 WebView 而後能夠看到以下界面:

InspectPage
InspectPage

點擊對應頁面的 inspect 就能夠進入調試頁面:

DebugPage
DebugPage

接下里就能夠像調試前端頁面同樣調試 WebView 中的內容了。

最後

詳細使用代碼請移步 PandaEye 查看

相關文章
相關標籤/搜索