Web-Apps in WebView erstellen

Mit WebView können Sie eine Webanwendung oder eine Webseite als Teil einer Clientanwendung bereitstellen. Die Klasse WebView ist eine Erweiterung der Android-Klasse View, mit der Sie Webseiten als Teil Ihres Aktivitätslayouts anzeigen können. Sie enthält nicht die Funktionen eines vollständig entwickelten Webbrowsers, z. B. Navigationselemente oder eine Adressleiste. Standardmäßig wird mit WebView lediglich eine Webseite angezeigt.

Mit WebView können Sie Informationen in Ihrer App bereitstellen, die Sie möglicherweise aktualisieren müssen, z. B. eine Endnutzervereinbarung oder eine Bedienungsanleitung. In Ihrer Android-App können Sie ein Activity erstellen, das ein WebView enthält, und es dann verwenden, um Ihr online gehostetes Dokument anzuzeigen.

WebView kann auch hilfreich sein, wenn Ihre App dem Nutzer Daten zur Verfügung stellt, für die eine Internetverbindung zum Abrufen von Daten erforderlich ist, z. B. E-Mails. In diesem Fall ist es möglicherweise einfacher, in Ihrer Android-App eine WebView zu erstellen, in der eine Webseite mit allen Nutzerdaten angezeigt wird, als eine Netzwerkanfrage auszuführen, die Daten zu parsen und sie in einem Android-Layout zu rendern. Stattdessen können Sie eine Webseite entwerfen, die für Android-Geräte optimiert ist, und dann ein WebView in Ihre Android-App einfügen, das die Webseite lädt.

In diesem Dokument wird beschrieben, wie Sie mit WebView beginnen, wie Sie JavaScript von Ihrer Webseite an clientseitigen Code in Ihrer Android-App binden, wie Sie die Seitennavigation verarbeiten und wie Sie Fenster verwalten, wenn Sie WebView verwenden.

WebView in älteren Android-Versionen verwenden

Wenn Sie neuere WebView-Funktionen auf dem Gerät, auf dem Ihre App ausgeführt wird, sicher verwenden möchten, fügen Sie die AndroidX Webkit-Bibliothek hinzu. Dies ist eine statische Bibliothek, die Sie Ihrer Anwendung hinzufügen können, um android.webkit-APIs zu verwenden, die für frühere Plattformversionen nicht verfügbar sind.

Fügen Sie sie Ihrer build.gradle-Datei so hinzu:

Kotlin

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

Groovy

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

Weitere Informationen finden Sie im Beispiel für WebView auf GitHub.

WebView in Ihre App einfügen

Wenn Sie Ihrer App ein WebView hinzufügen möchten, können Sie das <WebView>-Element in das Layout Ihrer Aktivität einfügen oder das gesamte Activity-Fenster in onCreate() als WebView festlegen.

WebView im Aktivitätslayout hinzufügen

Wenn Sie dem Layout Ihrer App ein WebView hinzufügen möchten, fügen Sie der XML-Datei des Layouts Ihrer Aktivität den folgenden Code hinzu:

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

Wenn Sie eine Webseite in der WebView laden möchten, verwenden Sie loadUrl(), wie im folgenden Beispiel gezeigt:

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

WebView in onCreate() hinzufügen

Wenn Sie Ihrer App stattdessen in der onCreate()-Methode einer Aktivität ein WebView hinzufügen möchten, verwenden Sie eine ähnliche Logik wie die folgende:

Kotlin

val myWebView = WebView(activityContext)
setContentView(myWebView)

Java

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

Laden Sie dann die Seite:

Kotlin

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

Java

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

Oder laden Sie die URL aus einem HTML-String:

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

Ihre App muss Zugriff auf das Internet haben. Wenn Sie Internetzugriff benötigen, fordern Sie die Berechtigung INTERNET in Ihrer Manifestdatei an, wie im folgenden Beispiel gezeigt:

<manifest ... >
    <uses-permission android:name="android.permission.INTERNET" />
    ...
</manifest>

Sie haben folgende Möglichkeiten, um Ihre WebView anzupassen:

  • Aktivieren der Vollbildunterstützung mit WebChromeClient. Diese Klasse wird auch aufgerufen, wenn ein WebView die Berechtigung benötigt, die Benutzeroberfläche der Host-App zu ändern, z. B. zum Erstellen oder Schließen von Fenstern oder zum Senden von JavaScript-Dialogfeldern an den Nutzer. Weitere Informationen zum Debuggen in diesem Kontext finden Sie unter Web-Apps debuggen.
  • Verarbeiten von Ereignissen, die sich auf das Rendern von Inhalten auswirken, z. B. Fehler bei Formulareinsendungen oder Navigation mit WebViewClient. Sie können diese Unterklasse auch verwenden, um das Laden von URLs abzufangen.
  • JavaScript aktivieren, indem Sie WebSettings ändern.
  • Mit JavaScript auf Android-Framework-Objekte zugreifen, die Sie in ein WebView eingefügt haben.

JavaScript in WebView verwenden

Wenn auf der Webseite, die Sie in Ihrem WebView laden möchten, JavaScript verwendet wird, müssen Sie JavaScript für Ihr WebView aktivieren. Nachdem Sie JavaScript aktiviert haben, können Sie Schnittstellen zwischen Ihrem App-Code und Ihrem JavaScript-Code erstellen.

JavaScript aktivieren

JavaScript ist in einem WebView standardmäßig deaktiviert. Sie können die Funktion über die WebSettings aktivieren, die mit Ihrem WebView verbunden ist. Rufen Sie WebSettings mit getSettings() ab und aktivieren Sie dann JavaScript mit setJavaScriptEnabled().

Sehen Sie sich folgendes Beispiel an:

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

Über WebSettings haben Sie Zugriff auf eine Vielzahl weiterer Einstellungen, die für Sie nützlich sein könnten. Wenn Sie beispielsweise eine Webanwendung entwickeln, die speziell für die WebView in Ihrer Android-App konzipiert ist, können Sie mit setUserAgentString() einen benutzerdefinierten User-Agent-String definieren und dann den benutzerdefinierten User-Agent auf Ihrer Webseite abfragen, um zu prüfen, ob der Client, der Ihre Webseite anfordert, Ihre Android-App ist.

JavaScript-Code an Android-Code binden

Wenn Sie eine Webanwendung entwickeln, die speziell für die WebView in Ihrer Android-App konzipiert ist, können Sie Schnittstellen zwischen Ihrem JavaScript-Code und dem clientseitigen Android-Code erstellen. Ihr JavaScript-Code kann beispielsweise eine Methode in Ihrem Android-Code aufrufen, um ein Dialog anzuzeigen, anstatt die alert()-Funktion von JavaScript zu verwenden.

Wenn Sie eine neue Schnittstelle zwischen Ihrem JavaScript- und Android-Code binden möchten, rufen Sie addJavascriptInterface() auf und übergeben Sie eine Klasseninstanz, die an Ihr JavaScript gebunden werden soll, sowie einen Schnittstellennamen, über den Ihr JavaScript auf die Klasse zugreifen kann.

Sie können beispielsweise die folgende Klasse in Ihre Android-App einfügen:

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

In diesem Beispiel wird mit der Klasse WebAppInterface über die Methode showToast() eine Toast-Nachricht auf der Webseite erstellt.

Sie können diese Klasse mit dem JavaScript verknüpfen, das in Ihrem WebView mit addJavascriptInterface() ausgeführt wird, wie im folgenden Beispiel gezeigt:

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

Dadurch wird eine Schnittstelle namens Android für JavaScript erstellt, das im WebView ausgeführt wird. An diesem Punkt hat Ihre Webanwendung Zugriff auf die Klasse WebAppInterface. Hier sehen Sie beispielsweise HTML- und JavaScript-Code, mit dem über die neue Schnittstelle eine Toast-Benachrichtigung erstellt wird, wenn der Nutzer auf eine Schaltfläche tippt:

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>

Die Android-Schnittstelle muss nicht über JavaScript initialisiert werden. Durch das WebView wird es automatisch auf Ihrer Webseite verfügbar. Wenn ein Nutzer also auf die Schaltfläche tippt, ruft die Funktion showAndroidToast() über die Schnittstelle Android die Methode WebAppInterface.showToast() auf.

Seitennavigation verarbeiten

Wenn der Nutzer in Ihrer WebView auf einen Link auf einer Webseite tippt, startet Android standardmäßig eine App, die URLs verarbeitet. Normalerweise wird der Standardwebbrowser geöffnet und die Ziel-URL geladen. Sie können dieses Verhalten jedoch für Ihr WebView überschreiben, sodass Links in Ihrem WebView geöffnet werden. Der Nutzer kann dann vorwärts und rückwärts durch den von Ihrem WebView verwalteten Verlauf seiner Webseiten navigieren.

Wenn Sie Links öffnen möchten, auf die der Nutzer tippt, geben Sie ein WebViewClient für Ihr WebView an, indem Sie setWebViewClient() verwenden. Alle Links, auf die der Nutzer tippt, werden in Ihrer WebView geladen. Wenn Sie mehr Kontrolle darüber haben möchten, wo ein angeklickter Link geladen wird, können Sie eine eigene WebViewClient erstellen, die die Methode shouldOverrideUrlLoading() überschreibt. Im folgenden Beispiel wird davon ausgegangen, dass MyWebViewClient eine innere Klasse von Activity ist.

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

Erstellen Sie dann eine Instanz dieses neuen WebViewClient für das WebView:

Kotlin

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

Java

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new MyWebViewClient());

Wenn der Nutzer jetzt auf einen Link tippt, ruft das System die Methode shouldOverrideUrlLoading() auf, die prüft, ob der URL-Host mit einer bestimmten Domain übereinstimmt, wie im vorherigen Beispiel definiert. Wenn sie übereinstimmt, gibt die Methode „false“ zurück und überschreibt das Laden der URL nicht. Dadurch kann WebView die URL wie gewohnt laden. Wenn der URL-Host nicht übereinstimmt, wird ein Intent erstellt, um die Standard-Activity zum Verarbeiten von URLs zu starten, die zum Standardwebbrowser des Nutzers aufgelöst wird.

Benutzerdefinierte Alias-URLs

WebView wendet Einschränkungen an, wenn Ressourcen angefordert und Links aufgelöst werden, die ein benutzerdefiniertes URL-Schema verwenden. Wenn Sie beispielsweise Callbacks wie shouldOverrideUrlLoading() oder shouldInterceptRequest() implementieren, ruft WebView sie nur für gültige URLs auf.

WebView ruft Ihre shouldOverrideUrlLoading()-Methode möglicherweise nicht für Links wie diesen auf:

<a href="showProfile">Show Profile</a>

Ungültige URLs wie im vorherigen Beispiel werden in WebView inkonsistent verarbeitet. Wir empfehlen daher, stattdessen eine wohlgeformte URL zu verwenden. Sie können ein benutzerdefiniertes Schema oder eine HTTPS-URL für eine Domain verwenden, die von Ihrer Organisation verwaltet wird.

Anstatt einen einfachen String in einem Link zu verwenden, wie im vorherigen Beispiel, können Sie ein benutzerdefiniertes Schema wie das folgende verwenden:

<a href="example-app:showProfile">Show Profile</a>

Sie können diese URL dann in Ihrer shouldOverrideUrlLoading()-Methode so verarbeiten:

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

Die shouldOverrideUrlLoading() API ist in erster Linie für das Starten von Intents für bestimmte URLs vorgesehen. Achten Sie bei der Implementierung darauf, dass für URLs, die von WebView verarbeitet werden, false zurückgegeben wird. Sie sind jedoch nicht auf das Starten von Intents beschränkt. Sie können Launching-Intents in den oben genannten Codebeispielen durch ein beliebiges benutzerdefiniertes Verhalten ersetzen.

Wenn Ihr WebView das Laden von URLs überschreibt, wird automatisch ein Verlauf der besuchten Webseiten erstellt. Mit goBack() und goForward() können Sie in der Chronik vor- und zurückgehen.

Im Folgenden sehen Sie ein Beispiel dafür, wie Ihre Activity die Zurück-Taste des Geräts verwenden kann, um rückwärts zu navigieren:

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

Wenn Ihre App AndroidX AppCompat 1.6.0 oder höher verwendet, können Sie das vorherige Snippet noch weiter vereinfachen:

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

Die Methode canGoBack() gibt „true“ zurück, wenn der Nutzer einen Webseitenverlauf hat, den er aufrufen kann. Entsprechend können Sie canGoForward() verwenden, um zu prüfen, ob ein Vorwärtsverlauf vorhanden ist. Wenn Sie diese Prüfung nicht durchführen, passiert nach dem Erreichen des Endes des Verlaufs durch den Nutzer nichts.goBack()goForward()

Umgang mit Änderungen der Gerätekonfiguration

Zur Laufzeit treten Änderungen des Aktivitätsstatus auf, wenn sich die Konfiguration eines Geräts ändert, z. B. wenn Nutzer das Gerät drehen oder einen IME (Input Method Editor) schließen. Durch diese Änderungen wird die Aktivität eines WebView-Objekts beendet und eine neue Aktivität erstellt. Dadurch wird auch ein neues WebView-Objekt erstellt, in das die URL des beendeten Objekts geladen wird. Wenn Sie das Standardverhalten Ihrer Aktivität ändern möchten, können Sie in Ihrem Manifest festlegen, wie orientation-Änderungen verarbeitet werden. Weitere Informationen zum Verarbeiten von Konfigurationsänderungen während der Laufzeit finden Sie unter Konfigurationsänderungen verarbeiten.

Fenster verwalten

Standardmäßig werden Anfragen zum Öffnen neuer Fenster ignoriert. Das gilt unabhängig davon, ob sie über JavaScript oder über das Attribut „target“ in einem Link geöffnet werden. Sie können WebChromeClient anpassen, um ein eigenes Verhalten für das Öffnen mehrerer Fenster zu definieren.

Um Ihre App sicherer zu machen, sollten Sie verhindern, dass Pop-ups und neue Fenster geöffnet werden. Die sicherste Methode, dieses Verhalten zu implementieren, besteht darin, "true" an setSupportMultipleWindows() zu übergeben, aber die Methode onCreateWindow()>, von der setSupportMultipleWindows() abhängt, nicht zu überschreiben. Diese Logik verhindert, dass Seiten geladen werden, in deren Links target="_blank" verwendet wird.