如今的純原生的 APP 不多見了,幾乎都是原生中嵌者網頁的 hybird APP,或者直接使用 React Native 開發。原生 App 中嵌者網頁原生與網頁中 JavaScript 的交互幾乎沒法避免,畢竟在本身的應用中嵌入網頁不僅是想讓應用當個瀏覽器用。
Android 原生中加載網頁的控件是 WebView,所以要想原生與 JavaScript 交互也同樣必須經過 WebView 來實現。javascript
低版本和高版本的 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 是爲 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 主要用來幫助 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); //可作其餘處理
}
});複製代碼
輔助 WebView 處理 JavaScript 對話框,加載進度,網頁圖標等。
經常使用方法:github
// 加載進度回調
onProgressChanged(WebView view, int newProgress);
// 獲取到網頁 Title 回調
onReceivedTitle(WebView view, String title);
// 獲取到網頁圖標回調
onReceivedIcon(WebView view, Bitmap icon);複製代碼
經過前面的瞭解,WebView 及他的輔助類的一些基本方法咱們是知道了,接下來就看一下一下怎麼使用 WebView 以及怎樣經過 WebView 讓 Android 源生代碼與 JavaScript 代碼進行交互。web
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);
}複製代碼
在熊貓眼 PandaEye 中由於使用的知乎日報和網易新聞的 API 因此下發的 HTML body 數據須要咱們本身加個 HTML 的殼,而後再源生加載咱們須要的 JavaScrpit 代碼來實現咱們的功能。
加載 JS 能夠直接 webView.load() 加載完整的 JS 代碼也能夠在本身加的 head 節點引入 JS 文件而後 webView 直接 load 其中的方法, PandaEye 中使用的是第二種方法:
在拼裝 HTML 時在 head 中引入放在 asset 文件夾中的 js 文件瀏覽器
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 代碼替換掉便可。
WebView 中 JavaScript 代碼的調試直接使用 AndroidStudio 是沒辦法的,那麼咱們怎樣調試 HTML 頁面呢?答案是用 Chrome 瀏覽器來調試:
詳細使用代碼請移步 PandaEye 查看