Ⅰ 安卓WebView詳解 (三)--Webview的API及說明
android.view.ViewGroup
↳ android.widget.AbsoluteLayout
↳android.webkit.WebView
用於安卓顯示網頁內容
一、查找網頁中匹配的字元串
1、void findAllAsync ( String find) 查滾悄找網頁亂搭中匹配的字元串且高亮顯示,此方法為非同步方法,對應的結果會在 WebView.FindListener中回調
2、void findNext (boolean forward) 上下查找匹配字元串
3、void addJavascriptInterface ( Object object, String name) 將提供的Java對象注入到此WebView中
4、void autofill( SparseArray < AutofillValue > values) 自動填充該視圖中虛擬子級的內容
5、boolean canGoBack () 獲取此WebView是否具有後退歷史記錄項。
6、boolean canGoBackOrForward (int steps) 獲取頁面是大陪渣否可以前進或後退給定數量的步驟。
7、boolean canGoForward () 獲取此WebView是否具有轉發歷史記錄項。
8、void clearCache (boolean includeDiskFiles) 清除緩存
9、void clearClientCertPreferences ( Runnable onCleared) 清除響應於繼續/取消客戶端證書請求而存儲的客戶端證書首選項。
10、void clearFormData() 從當前關注的表單欄位中刪除自動完成彈出窗口(如果存在)。
11、void clearHistory () 告訴此WebView清除其內部後退/前進列表
Ⅱ Android WebView
啟用JavaScript
定義Java介面,暴露方法給JavaScript
綁定一個命名為Android的介面給WebView,
在JavaScript中肆返使用這個介面
點擊WebView中的鏈接的默認行為是啟動默認瀏覽器打開這個URL。如果想要在自己的WebView中打開:
復寫WebViewClient的shouldOverrideUrlLoading方法:
canGoBack()如果實際存在用戶要訪問的網頁歷史記錄,則該方法返回true。同樣,您可以使用純搏canGoForward()檢查是否存在轉發歷史記裂褲飢錄。如果您不執行此檢查,則一旦用戶到達歷史記錄的末尾,goBack()或goForward()什麼都不做。
WebSettings用來對WebView做各種設置, 你可以這樣獲取WebSettings:
<pre><code>
WebSettings webSettings = mWebView .getSettings();
</code></pre>
WebSettings的常見設置如下所示:
WebViewClient用來幫助WebView處理各種通知, 請求事件。我們通過繼承WebViewClient並重載它的方法可以實現不同功能的定製。主要方法:
WebChromeClient用來幫助WebView處理JS的對話框、網址圖標、網址標題和載入進度等。同樣地, 通過繼承WebChromeClient並重載它的方法也可以實現不同功能的定製, 如下所示:
Ⅲ Android 5.x 免 Root 升級系統 WebView
Android 的系統碎片化問題可以說是 Android 系統最大的硬傷了,自這個系統誕生以來十幾年過去了,依然沒能很好的解決,碎片化問題也是每個 Android 開發工程師心中的隱痛😂,每次處理系統碎片化帶來的問題時,血壓也能分分鍾飆升到 200+,為了減輕其他同仁的痛苦以及此後再遇到類似問題能少踩幾個坑,就之前的爬坑經歷做個記錄吧。
有關 WebieView 的重要性和其使用不是本文的重點,但是有幾個相關的屬性我們必須了解:
在Android4.4(API level 19)系統以前,Android使用了原生自帶的Android Webkit內核,這個內核對HTML5的支持不是很好,現在使用4.4以下機子的也不多了,就不對這個內核做過多介紹了,有興趣可以看下 這篇文章 。
從Android4.4系統開始,Chromium內核取代了Webkit內核,正式地接管了WebView的渲染工作。Chromium是一個開源的瀏覽器內核項目,基於Chromium開源項目修改實現的瀏覽器非常多,包括最著名的Chrome瀏覽器,以及一眾國內瀏覽器(360瀏覽器、QQ瀏覽器等)。其中Chromium在Android上面的實現是 Android System WebView ^1 。
從Android5.0系統開始,WebView移植成了一個獨立的apk,可以不依賴系統而獨立存在和更新,我們可以在 系統->設置->Android System WebView 看到WebView的當前版本。
從Android7.0系統開始,如果系統安裝了Chrome (version>51),那麼Chrome將會直接為應用的WebView提供渲染,WebView版本會隨著Chrome的更新而更新,用戶也可以選擇WebView的服務提供方(在開發者選項->WebView Implementation里),WebView可以脫離應用,在一個獨立的沙盒進程中渲染頁面(需要在開發者選項里打開) ^2 。
從Android8.0系統開始,默認開啟WebView多進程模式,即WebView運行在獨立的沙盒進程中 ^3 。―― 節選自 如何設計一個優雅健壯的Android WebView?(上)
WebView 的包名在 AOSP 中的值是 com.android.webview ,該值是在 AOSP 構建過程中編譯的版本,也就是說它是和系統一起被編譯出來的,由於大部分的第三方手機製造商都有自己的定製 ROM,所以包名也是不盡相同,比如 MIUI ROM 中它已經被改為 com.mi.webkit.core 。從 WebView 的版本歷史中可以看到自 Android 5.0 開始 WebView 移植成了一個獨立的 apk,可以不依賴系統而獨立存在和更新,這時候起 WebView 的包名就正式改為 com.google.android.webview 了。
所以這就是為什麼網上一堆人問為啥升級了一下系統 WebView ,App 內使用到 WebView 的地方或者是內置瀏覽器一碰就報 PackageManager$NameNotFoundException: com.google.android.webview 或者 PackageManager$NameNotFoundException: com.android.webview 之類的錯誤,這些問題在 Android 5.0 的機器上非常常見,因為你升級了 WebView 之後 TMD 包名都變了🤣,而 ROM 定製商一般在版本銜接時都很保守,所以即使系統升到了 Android 5.0 ,解決方案未必就是最新的,內置的 WebView 依然可能是硬編碼進 ROM 的,所以系統環境引用的包名可能依舊是 com.android.webview ,你升級到 com.google.android.webview 它當然不認識了😂。
通過上面一通廢話,你應該知道了,替換的坑就在如果你換上去的 WebView 包名和原內置的 WebView 包名不一致,就無法使用,所以就需要找一個包名一致的高版本 APK 了,還有一種方法是在系統目錄某個配置文件里改個什麼值,也就是包名引用,這樣你就能換成任何包名的 APK 了,這個暫時沒仔細研究,後續有結果了再更新。
APKMirror 是一個 APK 鏡像站點,在這里可以找到很多 APK 的 release 版本以及歷史版本,尤其 Google 全家桶系列的 APK 非常全,我們在這里根據需求直接搜索包名就可以了,我這里需要 com.android.webview ,檢索到如下結果,可以看到這些都是從第三方 ROM 里提取出來的。
因為 Google 官方早在 WebView 40 的時候就已經將包名換成 com.google.android.webview 了,最新的是 72.xxx ,我翻了 15 頁才找到最早改名並獨立出來的那個版本😂。
adb connect 192.168.18.235
adb shell
su
mount -o rw,remount /system
這里原目錄下的文件分別有 /webview/webview.apk 和 /webview/lib/arm/libwebviewchromium.so ,備份原目錄:
cd /system/app
mv webview/ webview-b/
mkdir -p webview/lib/arm/
這里很簡單,文件後綴 .apk 直接改成 .zip 然後解壓縮,復制出 libwebviewchromium.so 即可
先上傳文件到設備 /sdcard ,然後執行如下命令移動過去,和原路徑以及原文件名保持一致即可。
mv /sdcard/xxx.apk /system/app/webview/webview.apk
mv /sdcard/xxx.so /system/app/webview/lib/arm/libwebviewchromium.so
cd /system/app/
chmod 777 webview/*
adb reboot
如上一頓操作,其實也沒什麼難度,主要的坑就是包名一致的問題,還有一些系統目錄訪問許可權之類的問題,之前網上搜了好多,都說不 root 沒法換,或者換了會出問題,root 許可權其實就是為了訪問和寫入系統目錄,通過重新掛載就解決了,換了會崩掉的問題其實就是歷史遺留問題,從 4.x 過度到 5.0 WebView 獨立了,所以包名變了,或者是 ROM 定製方不按套路來導致換上去的 WebView 不被系統識別,只要找到合適的包就解決了。
Ⅳ 如何控制了Android的WebView歷史/後退堆棧
您的OnKeyDown應該像這些 @Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
Ⅳ android webview 有沒有獲取歷史記錄集合的方法
有的。mWebView.BackForwardList()這個是集合
mWebView.BackForwardList().getItemAtIndex(position).getUrl();position是int類型。這個是獲取url。
我最近在做安卓瀏覽器,基本不用自帶的,基本都是沒打開一個網頁存在本地資料庫,用起來方便。
Ⅵ 如何清除參觀一個Android的WebView的歷史
1.覆蓋和WebViewClient ......媽的這是隱藏的。
其實,我只好掏了一下,找到了這一點。
WebView webView = (WebView)findViewById(R.id.myWebView);
WebChromeClient myWebChromeClient = new WebChromeClient(){
@Override
public void getVisitedHistory(ValueCallback<String[]> callback) {
// called ring webview initialization, original implementation does strictly nothing
// and defaults to the native method WebViewCore.nativeProvideVisitedHistory()
String[] myUserHistory = (userId);
callback.onReceiveValue(myUserHistory);
}
};
WebViewClient myWebViewClient = new WebViewClient(){
@Override
public void doUpdateVisitedHistory(WebView view, String url,
boolean isReload) {
// called whenever there is a new link being visited
(userId);
super(view, url, isReload);
}
}
webView.setWebViewClient(myWebViewClient);
webView.setChromeClient(myWebChromeClient);
webView.getSettings().etc(whatever)...
我想我是「幾乎沒有」。下面塌鏈敏是我所管理的一部分:它做什麼,到目前為止是完全去除CSS的歷史,所以我們已經完成一半了。我不能讓瀏覽器識別URL格式我提供的「myUserHistory」,所以實際上這個代碼的唯一函數是重置的CSS歷史乾脆,但團枝一旦當web視圖被實例化它只是調用(或創建的
CodeGo.net,沒有檢查),所以對於一個真正的經驗,你就需要重新創建web視圖在每次登錄時。
我現在的問題是,我不能管理正常載入urlHistory。我的Xoom的web視圖似乎忽略我的數據。
不錯啊,我希望它為你工作。只是打電話callback.onReceiveValue(新的String []
{});在getVisitedHistory()就可以了。
編輯:
我只是把20多分鍾就喚拿到,我是委託給(mCallbackProxy=
Ⅶ 關於Android WebView的那些事
[TOC]
Webkit是一個開源瀏覽器項目,其中,對Android開發者來說,或多或少的都有些接觸。 在應用層來看,最經常使用無非這么幾個類:WebView(Android中最為復雜,也是最為簡單的一個View,繼承自AbsoluteLayout),WebViewClient、WebChromeClient(作為回調控制類)、WebSettings(進行設置項的配置)等;Webkit內部包含了網路請求、頁面渲染、Js引擎等等。在Android4.4之前的版本中,系統使用的是Webkit內核,其後,切換到Google的Chromium內核。本文主要介紹的是在Android中,如何使用Webkit進行H5頁面的展現,以及常見問題的分析手段。
下面的內容抄自網路 & 亂七八糟的地方,簡單了解一下。
<b><i>前面都是吹牛逼的信息,如何使用Webkit來更好的搬磚? 且聽如下分解</i></b>
XML布局中丟一個 <WebView> 標簽,然後再 Activity 或者 Fragment 中 findViewById ,進而 loadUrl ,一般也沒人這么簡單的用,除非寫Demo。很簡單,它就是一個Layout,提供了一個調用載入頁面的介面,不寫範例了,能看到這篇文章的都看過Google的API說明。
主要涉及到WebView和WebSettings兩個類。
例如:
其實就是WebView的父類ViewGroup和View的方法,不多說了。不過需要注意的是,不是所有的View或ViewGroup的方法對WebView都生效。
列舉幾類常用的,幾乎所有App的 WebView 都會設置的屬性:
</br>
如何處理頁面跳轉以及特殊 Scheme
這個回調可以說是最容易出問題的一個回調,表示什麼? 字面意思,讓你重寫這個URL 的loading,比如點擊html打電話的一個 <a href=「tel:110」> 標簽,作為一個有節操、有責任心的瀏覽器,你需要處理 H5常用的幾個Scheme :
除此之外,還有各個應用自定義的scheme ,舉個例子,支付寶的支付Scheme : alipay: 。 這里的返回值,就代表你有沒有能力處理這個url,沒有的話Webkit就默認處理了。
需要注意的是,這個回調的觸發的絕大多數情況是點擊頁面的 <a href="xxxx"> a標簽,在Android中 loadUrl("http://www..com") ,是不會回調的,為什麼不會回調,各位自行理解吧。
超鏈接 <a> 標簽怎麼寫: 點我
特別說下窗口常見的兩種打開方式:
針對單頁模式的WebView框架(所有的html窗口均使用同一個WebView實例),不需要關注target的。
如果作為一個成熟的瀏覽器框架的話,是需要支持Html、JavaScript使用新窗口打開頁面,需要實現如下回調:
還有一個相關設置項: WebSettings.
此時,系統將不會再回調 shouldOverrideUrlLoading 。新窗口邏輯的具體實現機制,可以參考系統browser實現邏輯。
<b> 這里有個坑 </b>
Android 4.4版本 ,如果實現了onCreateWindow,也就是說頁面 <a> 標簽是這么寫的: <a href="http://www..com" target="_blank"> ,點擊此鏈接打開的新WebView窗口,此窗口中的url點擊,是不會觸發 shouldOverrideUrlLoading 。 這是剛替換成Chrominum內核出的一個bug。本人並沒在新版本上驗證是否已經修復。
另外,根據不同的Rom,底層實現是不一樣的,有的ROM會幫你處理各種調起scheme,也就是startActivity,有的ROM點一個url,就會拋一個intent出來,讓用戶選擇系統瀏覽器進行載入。
系統默認,提供了一個介面:
有什麼安全隱患呢?
戳這里
如果不知道Js怎麼寫, 請戳我
用PC的截圖意思一下,看出區別了吧。 這里確定、取消點擊以後就得調用 JsResult、JsPromptResult 的 confirm或者cancel。
因為安全問題,大一些的App Native與Js通信都不再用 WebView.addJavascriptInterface(Object) 了,都改用JsPrompt,因為JsPrompt中有message、有JsPromptResult可以返回給Js一些信息,所以橋選中了JsPrompt,另一個備選方案是JsConsole。
大體有這么幾種方式進行傳遞
具體方案實現時,多方面考慮使用何種方式。
還有一個比較牛逼的
系統源碼中均有方法注釋,怎麼用自己看吧。
那麼問題來了
查了下,只有這兩個相關的:
WebBackForwardList BackForwardList()
void clearHistory()
系統提供的關於歷史記錄的操作並不多,因為,不支持單條刪除啊,啊啊啊!
WebViewClient中,還有一個相關callback,當系統更新歷史記錄時回調:
void doUpdateVisitedHistory(WebView view, String url, boolean isReload)
<b>相關問題分析法:歷史棧回退錯誤的定位</b>
絕大多數回退錯誤是由於介面調用、回調中邏輯執行時序錯誤。
定位方法:利用 BackForwardList , doUpdateVisitedHistory 兩個介面在 loadUrl、onPageStart、onPageFinish 以及邏輯相關的地方調用,打log,查看歷史棧,這里注意下由於loarl是非同步的,需要考慮是否加延遲等等保證調用時機的准確。
本人曾經遇到一個問題:在WebChromeClient中的 JsPrompt回調中,直接進行WebView.goBack操作,結果發現WebView確實回退到上一個頁面,但是BackFowardList當前頁面的index未更新的問題,具體見另一個篇blog。
網上有很多關於WebView內存泄露的討論,據傳,老版本的WebView在展示大量圖片的時候,即使 WebView.destory() WebView=null ,也不會銷毀。
在新版本上,實際測試結果:compileSDKVersion 23 不會泄露。
一般,我們如何銷毀WebView比較保險?
這個問題好大。。。
暫時不介紹,另起blog進行說明。
解決方案:
實現回調 void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
首先,提幾個需要注意的點:
個人歸納總結幾點:
step1 進入開發者模式,勾選「顯示布局邊界」;
step 2,回到你想查看的界面; step 3 假如內容區只有一層基本就是H5 WebView的,多個層級,就是Native。
看到左右圖的差異了吧。
還有另一種方法,RD屌絲們看這里,特別說明,這種方法不太適合瀏覽器。 (自有內核,可能會不準確)
好了,就介紹到這里,零零散散的幾年前寫的文章,第一篇blog,如有不對的地方,還懇請大家指正。