在 WebView 中建構網頁應用程式

使用 WebView 提供網頁應用程式 或網頁做為用戶端應用程式的一部分WebView 類別是 Android View 類別的擴充功能 網頁會在活動版面配置中顯示。此網址不包括 功能,例如導覽控製或 網址列根據預設,所有的 WebView 都會顯示網頁。

WebView 可協助您在應用程式中提供可能需要的資訊 例如使用者協議或使用手冊在 Android 應用程式中, 您就能建立 Activity,其中包含一個 WebView,然後用它來顯示由線上代管的文件。

WebView 也能為應用程式提供資料給需要 才能擷取資料,例如電子郵件。在這種情況下, 您會發現,在 Android 應用程式中建構 WebView 更輕鬆 而不是執行網路要求 剖析資料並在 Android 版面配置中算繪資料。您可以運用不同的 先為 Android 裝置量身打造專屬網頁,再導入 WebView,可載入網頁的 Android 應用程式。

這份文件說明如何開始使用 WebView,以及如何進行繫結 從網頁使用 JavaScript 到 Android 應用程式的用戶端程式碼;如何 處理網頁導覽,以及如何在使用 WebView 時管理視窗。

在舊版 Android 上使用 WebView

為了安全地在您的應用程式中使用較新的 WebView 功能 執行時,請將 AndroidX Webkit 程式庫。這是靜態的 您可以在應用程式中加入程式庫,android.webkit使用非支援的 API 適用於早期平台版本

請按照下列步驟將這個檔案新增至 build.gradle 檔案:

Kotlin

dependencies {
    implementation("androidx.webkit:webkit:1.8.0")
}

Groovy

dependencies {
    implementation ("androidx.webkit:webkit:1.8.0")
}

探索WebView 示例

在應用程式中新增 WebView

若要在應用程式中新增 WebView,可以在<WebView> 活動版面配置,或將整個Activity視窗設為 WebView onCreate()

在活動版面配置中新增 WebView

如要在版面配置中加入 WebView 至應用程式,請將下列程式碼加進 活動的版面配置 XML 檔案:

<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
/>

如要在 WebView 中載入網頁,請使用 loadUrl(),你好: 如以下範例所示:

Kotlin

val myWebView: WebView = findViewById(R.id.webview)
myWebView.loadUrl("http://www.example.com")

Java

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");

在 onCreate() 中新增 WebView

如要改為在活動的 onCreate() 方法中將 WebView 新增至應用程式,請使用 類似以下的邏輯:

Kotlin

val myWebView = WebView(activityContext)
setContentView(myWebView)

Java

WebView myWebView = new WebView(activityContext);
setContentView(myWebView);

接著載入頁面:

Kotlin

myWebView.loadUrl("http://www.example.com")

Java

myWebView.loadUrl("https://www.example.com");

或從 HTML 字串載入網址:

Kotlin

// 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")

Java

// 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。您也可以使用 這個子類別會攔截網址載入
  • 透過修改方法來啟用 JavaScript WebSettings
  • 使用 JavaScript 存取您已插入的 Android 架構物件 放入 WebView 中。

在 WebView 中使用 JavaScript

如要透過 WebView 載入的網頁使用 JavaScript,您必須 為 WebView 啟用 JavaScript。啟用 JavaScript 後 在應用程式程式碼和 JavaScript 程式碼之間建立介面。

啟用 JavaScript

根據預設,WebView 會停用 JavaScript。您可以透過 「WebSettings」已連接至「WebView」。使用以下方式擷取 WebSettingsgetSettings(),然後啟用 JavaScript 值為 setJavaScriptEnabled()

請參閱以下範例:

Kotlin

val myWebView: WebView = findViewById(R.id.webview)
myWebView.settings.javaScriptEnabled = true

Java

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 應用程式中加入下列類別:

Kotlin

/** 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()
    }
}

Java

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 類別可讓網頁建立 Toast 訊息 (使用 showToast()) 方法。

您可以使用以下項目,將此類別繫結至在 WebView 中執行的 JavaScript: addJavascriptInterface(),如以下範例所示:

Kotlin

val webView: WebView = findViewById(R.id.webview)
webView.addJavascriptInterface(WebAppInterface(this), "Android")

Java

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

如要開啟使用者輕觸的連結,請提供 WebViewWebViewClient 使用 setWebViewClient()。 使用者輕觸的所有連結,都會在 WebView 中載入。如需進一步掌控 當有人點選的連結載入時,請建立自己的 WebViewClient 來覆寫 shouldOverrideUrlLoading() 方法。以下範例假設 MyWebViewClient 是內部類別 (共 Activity 個)。

Kotlin

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
    }
}

Java

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 的例項:

Kotlin

val myWebView: WebView = findViewById(R.id.webview)
myWebView.webViewClient = MyWebViewClient()

Java

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() 方法中處理這個網址,例如 :

Kotlin

// 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
    }
}

Java

// 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 主要用於啟動意圖 特定網址的情況實作時,請務必針對網址傳回 false WebView 控制代碼。但這不限於啟動意圖。你可以 在上述程式碼中,以任何自訂行為取代啟動意圖 樣本。

WebView 覆寫網址載入時,會自動累積 瀏覽記錄。瀏覽上一個或下一個畫面 goBack()goForward()

舉例來說,下列是 Activity 如何使用裝置的背面 按鈕前往上一頁:

Kotlin

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)
}

Java

@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 以上版本,您可以簡化先前的 更多程式碼片段:

Kotlin

onBackPressedDispatcher.addCallback {
    // Check whether there's history.
    if (myWebView.canGoBack()) {
        myWebView.goBack()
    }
}

Java

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() 但不會覆寫 onCreateWindow() 方法 (setSupportMultipleWindows() 相依)。這個邏輯可避免 載入網頁,並在連結中使用 target="_blank"