使用 WebView
將網頁應用程式或網頁當做用戶端應用程式的一部分提供。WebView
類別是 Android 的 View
類別延伸項目,可讓您在活動版面配置中顯示網頁。但不包含完整網路瀏覽器的功能,例如導覽控制項或網址列。根據預設,所有的 WebView
都會顯示網頁。
WebView
可協助您在應用程式中提供可能需要更新的資訊,例如使用者協議或使用者指南。您可以在 Android 應用程式中建立包含 WebView
的 Activity
,然後使用該檔案顯示線上代管的文件。
當應用程式向使用者提供需要透過網路連線擷取資料 (例如電子郵件) 的資料時,WebView
也能提供協助。在這種情況下,您可能會發現,在 Android 應用程式中建構 WebView
會比較容易,因為您可以直接顯示含有所有使用者資料的網頁,而不需要執行網路要求,然後剖析資料並在 Android 版面配置中算繪。您可以改為設計專為 Android 裝置打造的網頁,然後在 Android 應用程式中導入 WebView
,以便載入網頁。
這份文件說明如何開始使用 WebView
,以及如何進行繫結
從網頁使用 JavaScript 到 Android 應用程式的用戶端程式碼;如何
處理網頁導覽,以及如何在使用 WebView
時管理視窗。
在舊版 Android 上使用 WebView
為了安全地在您的應用程式中使用較新的 WebView
功能
執行時,請將 AndroidX
Webkit 程式庫。這是靜態的
您可以在應用程式中加入程式庫,android.webkit
使用非支援的 API
適用於早期平台版本
請按照下列步驟將這個檔案新增至 build.gradle
檔案:
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
探索WebView
示例
。
在應用程式中新增 WebView
如要在應用程式中新增 WebView
,您可以在活動版面配置中加入 <WebView>
元素,或是在 onCreate()
中將整個 Activity
視窗設為 WebView
。
在活動版面配置中新增 WebView
如要在版面配置中加入 WebView
至應用程式,請將下列程式碼加進
活動的版面配置 XML 檔案:
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
如要在 WebView
中載入網頁,請使用
loadUrl()
,你好:
如以下範例所示:
val myWebView: WebView = findViewById(R.id.webview) myWebView.loadUrl("http://www.example.com")
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.example.com");
在 onCreate() 中新增 WebView
如要改為在活動的 onCreate()
方法中將 WebView
新增至應用程式,請使用
類似以下的邏輯:
val myWebView = WebView(activityContext) setContentView(myWebView)
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
然後載入頁面:
myWebView.loadUrl("http://www.example.com")
myWebView.loadUrl("https://www.example.com");
或者,您也可以從 HTML 字串載入網址:
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. val unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; val encodedHtml = Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING) myWebView.loadData(encodedHtml, "text/html", "base64")
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. String unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING); myWebView.loadData(encodedHtml, "text/html", "base64");
您的應用程式必須能夠存取網際網路。如要存取網際網路,請在資訊清單檔案中要求 INTERNET
權限,如以下範例所示:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
您可以執行以下操作來自訂 WebView
:
- 使用以下應用程式啟用全螢幕支援功能
WebChromeClient
。本課程 當WebView
需要權限來變更主應用程式的 UI 時,也會呼叫此方法。 例如建立或關閉視窗,或將 JavaScript 對話方塊傳送至 內容。如要進一步瞭解在這個情況下如何偵錯,請參閱「偵錯網頁應用程式」。 - 處理影響內容轉譯的事件,例如表單錯誤
透過 YAML 檔案
WebViewClient
。您也可以使用這個子類別來攔截網址載入作業。 - 修改
WebSettings
啟用 JavaScript。 - 使用 JavaScript 存取您已插入的 Android 架構物件
放入
WebView
中。
在 WebView 中使用 JavaScript
如要透過 WebView
載入的網頁使用 JavaScript,您必須
為 WebView
啟用 JavaScript。啟用 JavaScript 後
在應用程式程式碼和 JavaScript 程式碼之間建立介面。
啟用 JavaScript
根據預設,WebView
會停用 JavaScript。您可以透過附加至 WebView
的 WebSettings
啟用這項功能。使用以下方式擷取 WebSettings
:
getSettings()
,然後啟用
JavaScript 值為
setJavaScriptEnabled()
。
請參閱以下範例:
val myWebView: WebView = findViewById(R.id.webview) myWebView.settings.javaScriptEnabled = true
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings
可讓您存取其他各種設定
很實用例如,假設您要開發
專為 Android 應用程式中的 WebView
所設計,因此您可以定義自訂
使用者代理程式字串
setUserAgentString()
,
接著查詢您網頁中的自訂使用者代理程式,驗證用戶端
也就是 Android 應用程式
將 JavaScript 程式碼繫結至 Android 程式碼
開發專為 WebView
設計的網頁應用程式時
在 Android 應用程式中,您可以建立 JavaScript 程式碼和
用戶端 Android 程式碼舉例來說,JavaScript 程式碼可以呼叫 Android 程式碼中的某個方法,以便顯示 Dialog
,而非使用 JavaScript 的 alert()
函數。
如要在 JavaScript 和 Android 程式碼之間繫結新版介面,請呼叫
addJavascriptInterface()
,
傳送類別實例,以便繫結至您的 JavaScript 和介面名稱
讓 JavaScript 可以呼叫來存取類別。
舉例來說,您可以在 Android 應用程式中加入下列類別:
/** Instantiate the interface and set the context. */ class WebAppInterface(private val mContext: Context) { /** Show a toast from the web page. */ @JavascriptInterface fun showToast(toast: String) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show() } }
public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context. */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page. */ @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }
在本例中,WebAppInterface
類別會讓網頁使用 showToast()
方法建立 Toast
訊息。
您可以使用 addJavascriptInterface()
將此類別繫結至在 WebView
中執行的 JavaScript,如以下範例所示:
val webView: WebView = findViewById(R.id.webview) webView.addJavascriptInterface(WebAppInterface(this), "Android")
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
這會建立名為 Android
的介面,供在
WebView
。此時,您的網頁應用程式可存取 WebAppInterface
類別。例如,以下這個 HTML 和 JavaScript
在使用者輕觸按鈕時,透過新版介面建立浮動式訊息:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
您不需要透過 JavaScript 初始化 Android
介面。WebView
會自動將這個資訊提供給您的網頁。所以當使用者
輕觸按鈕,showAndroidToast()
函式會使用 Android
介面
呼叫 WebAppInterface.showToast()
方法。
處理網頁導覽
當使用者輕觸 WebView
中的網頁連結時,根據預設,Android
啟動會處理網址的應用程式。通常會開啟預設的網路瀏覽器,
載入到達網頁網址。不過,您可以為 WebView
覆寫這項行為,讓連結在 WebView
中開啟。接著,您即可讓使用者
來瀏覽 網頁記錄。
來自您的WebView
。
如要開啟使用者輕觸的連結,請提供 WebView
的 WebViewClient
使用
setWebViewClient()
。
使用者點選的所有連結都會在您的 WebView
中載入。如要進一步控管點選連結的載入位置,請自行建立 WebViewClient
來覆寫 shouldOverrideUrlLoading()
方法。以下範例假設 MyWebViewClient
是內部類別
(共 Activity
個)。
private class MyWebViewClient : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { if (Uri.parse(url).host == "www.example.com") { // This is your website, so don't override. Let your WebView load // the page. return false } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { startActivity(this) } return true } }
private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if ("www.example.com".equals(request.getUrl().getHost())) { // This is your website, so don't override. Let your WebView load the // page. return false; } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); startActivity(intent); return true; } }
然後為 WebView
建立這個新 WebViewClient
的例項:
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = MyWebViewClient()
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
現在,當使用者輕觸連結時,系統會呼叫
shouldOverrideUrlLoading()
方法,可檢查網址主機是否相符
特定網域,如上述範例所定義。如果相符,
此方法傳回 false,且不會覆寫網址載入作業。讓 WebView
照常載入網址。如果網址主機不相符,系統會建立 Intent
來啟動預設 Activity
,以便處理網址,並將其解析為使用者的預設網頁瀏覽器。
處理自訂網址
WebView
會在要求資源和解析使用自訂網址配置的連結時,套用限制。舉例來說,假設您實作的回呼包括
shouldOverrideUrlLoading()
或
shouldInterceptRequest()
、
則 WebView
只會針對有效的網址叫用這些網址。
舉例來說,WebView
可能不會為以下連結呼叫 shouldOverrideUrlLoading()
方法:
<a href="showProfile">Show Profile</a>
無效的網址 (如上例所示) 在 WebView
中會以不一致的方式處理,因此建議改用格式正確的網址。您可以為貴機構控管的網域使用自訂配置或 HTTPS 網址。
如上述範例所示,與其在連結中使用簡易字串,您可以 使用自訂配置,例如:
<a href="example-app:showProfile">Show Profile</a>
接著,您可以在 shouldOverrideUrlLoading()
方法中處理這個網址,例如
:
// The URL scheme must be non-hierarchical, meaning no trailing slashes. const val APP_SCHEME = "example-app:" override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { return if (url?.startsWith(APP_SCHEME) == true) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length), "UTF-8") respondToData(urlData) true } else { false } }
// The URL scheme must be non-hierarchical, meaning no trailing slashes. private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8"); respondToData(urlData); return true; } return false; }
shouldOverrideUrlLoading()
API 主要用於啟動特定網址的意圖。實作時,請務必針對 WebView
處理的網址傳回 false
。但這不限於啟動意圖。您可以在上述程式碼範例中,將啟動意圖替換為任何自訂行為。
瀏覽網頁記錄
當 WebView
覆寫網址載入時,會自動累積
瀏覽記錄。瀏覽上一個或下一個畫面
goBack()
和
goForward()
。
舉例來說,下列是 Activity
如何使用裝置的背面
按鈕前往上一頁:
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { // Check whether the key event is the Back button and if there's history. if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) { myWebView.goBack() return true } // If it isn't the Back button or there isn't web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event) }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check whether the key event is the Back button and if there's history. if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { myWebView.goBack(); return true; } // If it isn't the Back button or there's no web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event); }
如果應用程式使用 AndroidX AppCompat
1.6.0 以上版本,您可以進一步簡化上述程式碼片段:
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack() } }
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack(); } }
canGoBack()
方法
如果使用者造訪網頁記錄,則會傳回 true。同樣地
可以使用 canGoForward()
:
並檢查記錄是否有前瞻性記錄如果您沒有執行這項檢查
在使用者瀏覽記錄結束時,goBack()
和 goForward()
就會執行
什麼都不做。
處理裝置設定變更
在執行階段期間,當裝置設定發生變更時,就會發生活動狀態變更,例如使用者旋轉裝置或關閉輸入法編輯器 (IME) 時。這些變更會導致 WebView
物件的活動遭到刪除,
要建立新的活動,這樣會同時建立新的 WebView
物件,用來載入
刪除物件的網址如要修改活動的預設行為,你可以
變更其處理資訊清單中 orientation
變更的方式。瞭解詳情
如果想瞭解如何在執行階段處理設定變更,請參閱「處理設定」
變更。
管理視窗
根據預設,系統會忽略開啟新視窗的要求。無論他們是否接受
是由 JavaScript 或連結中的目標屬性開啟。您可以自訂
WebChromeClient
,按照自訂開啟多個項目的行為。
視窗。
為進一步確保應用程式的安全性,建議您防止應用程式出現彈出式視窗和新視窗
正在打開實作這項行為最安全的方式,是將 "true"
傳遞至 setSupportMultipleWindows()
,但不要覆寫 setSupportMultipleWindows()
所依賴的 onCreateWindow()
方法。這項邏輯會防止任何在連結中使用 target="_blank"
的網頁載入。