Web-Apps in WebView erstellen

Verwenden Sie WebView, um eine Webanwendung oder eine Webseite als Teil einer Clientanwendung bereitzustellen. Die WebView-Klasse ist eine Erweiterung der View-Klasse von Android, mit der Sie Webseiten als Teil Ihres Aktivitätslayouts anzeigen können. Er enthält keine Funktionen eines vollständig entwickelten Webbrowsers, z. B. Navigationssteuerungen oder eine Adressleiste. Standardmäßig zeigt WebView nur eine Webseite an.

WebView kann Ihnen dabei helfen, Informationen in Ihrer App anzugeben, die Sie möglicherweise aktualisieren müssen, z. B. eine Endnutzervereinbarung oder eine Bedienungsanleitung. In deiner Android-App kannst du ein Activity erstellen, das eine WebView enthält, und dann damit dein online gehostetes Dokument anzeigen.

WebView kann auch hilfreich sein, wenn Ihre Anwendung dem Nutzer Daten zur Verfügung stellt, die zum Abrufen von Daten wie E-Mails eine Internetverbindung benötigen. In diesem Fall ist es möglicherweise einfacher, in Ihrer Android-App eine WebView zu erstellen, die eine Webseite mit allen Nutzerdaten anzeigt, anstatt eine Netzwerkanfrage auszuführen, die Daten zu parsen und sie in einem Android-Layout zu rendern. Stattdessen können Sie eine für Android-Geräte optimierte Webseite entwerfen und dann eine WebView in Ihrer Android-App implementieren, über die die Webseite geladen wird.

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

WebView in älteren Android-Versionen verwenden

Wenn Sie neuere WebView-Funktionen auf dem Gerät sicher verwenden möchten, auf dem Ihre App ausgeführt wird, 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 ältere Plattformversionen nicht verfügbar sind.

Fügen Sie sie Ihrer build.gradle-Datei folgendermaßen 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 WebView auf GitHub.

WebView zur App hinzufügen

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

WebView in das Aktivitätslayout einfügen

Um Ihrer App im Layout eine WebView hinzuzufügen, fügen Sie der Layout-XML-Datei 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");

Sie können die URL auch über einen HTML-String laden:

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, Ihre WebView anzupassen:

  • Vollbildunterstützung mit WebChromeClient aktivieren. Diese Klasse wird auch aufgerufen, wenn ein WebView die Berechtigung zum Ändern der Benutzeroberfläche der Host-App benötigt, z. B. zum Erstellen oder Schließen von Fenstern oder zum Senden von JavaScript-Dialogfeldern an den Nutzer. Weitere Informationen zur Fehlerbehebung in diesem Kontext finden Sie unter Fehlerbehebung für Webanwendungen.
  • Ereignisse verarbeiten, die sich auf das Rendern von Inhalten auswirken, z. B. Fehler beim Senden von Formularen oder bei der Navigation mit WebViewClient Sie können diese Unterklasse auch verwenden, um das Laden von URLs abzufangen.
  • JavaScript aktivieren, indem WebSettings geändert wird
  • JavaScript verwenden, um auf Android-Framework-Objekte zuzugreifen, die Sie in eine WebView eingefügt haben

JavaScript in WebView verwenden

Wenn die Webseite, die Sie in Ihrem WebView laden möchten, JavaScript verwendet, 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 einer WebView standardmäßig deaktiviert. Sie können die Funktion über die WebSettings aktivieren, die mit Ihrem WebView verknüpft ist. Rufen Sie WebSettings mit getSettings() ab und aktivieren Sie dann JavaScript mit setJavaScriptEnabled().

Hier ein Beispiel:

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 können Sie auf eine Vielzahl anderer Einstellungen zugreifen, 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 entwickelt wurde, können Sie einen benutzerdefinierten User-Agent-String mit setUserAgentString() 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 entwickelt wurde, können Sie Schnittstellen zwischen Ihrem JavaScript-Code und clientseitigem 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 verknüpfen möchten, rufen Sie addJavascriptInterface() auf und übergeben Sie eine Klasseninstanz, die mit Ihrem JavaScript verknüpft werden soll, und einen Schnittstellennamen, den Ihr JavaScript aufrufen kann, um auf die Klasse zuzugreifen.

Sie können beispielsweise die folgende Klasse in Ihre Android-App aufnehmen:

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 kann die Webseite mithilfe der Methode showToast() der Klasse WebAppInterface eine Toast-Nachricht erstellen.

Sie können diese Klasse mit addJavascriptInterface() an das JavaScript binden, das in Ihrer WebView 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, die im WebView ausgeführt wird. Ihre Webanwendung hat jetzt Zugriff auf die Klasse WebAppInterface. Im Folgenden finden Sie beispielsweise einige HTML- und JavaScript-Code-Snippets, mit denen eine Toast-Nachricht mit der neuen Benutzeroberfläche 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-Benutzeroberfläche muss nicht über JavaScript initialisiert werden. Die WebView stellt es automatisch für Ihre Webseite zur Verfügung. Wenn ein Nutzer auf die Schaltfläche tippt, verwendet die Funktion showAndroidToast() also die Android-Oberfläche, um die Methode WebAppInterface.showToast() aufzurufen.

Seitennavigation steuern

Wenn der Nutzer auf einer Webseite in Ihrer WebView auf einen Link 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 Ihre WebView überschreiben, sodass Links innerhalb Ihres WebView geöffnet werden. Sie können den Nutzer dann durch den von Ihrer WebView verwalteten Webseitenverlauf vor- und zurückgehen lassen.

Wenn Sie Links öffnen möchten, auf die Nutzer getippt haben, geben Sie eine WebViewClient für Ihre WebView an und verwenden Sie dazu setWebViewClient(). Alle Links, auf die der Nutzer tippt, werden in Ihrem WebView geladen. Wenn Sie mehr Kontrolle darüber haben möchten, wo ein angeklickter Link geladen wird, erstellen Sie eine eigene WebViewClient, 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 dieser neuen WebViewClient für die 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 die Übereinstimmung vorliegt, gibt die Methode „false“ zurück und überschreibt das Laden der URL nicht. So kann die WebView die URL wie gewohnt laden. Wenn der URL-Host nicht übereinstimmt, wird eine Intent erstellt, um den StandardActivity für die Verarbeitung von URLs zu starten, der zum Standardwebbrowser des Nutzers führt.

Benutzerdefinierte URLs verarbeiten

WebView ergreift Einschränkungen beim Anfordern von Ressourcen und beim Auflösen von Links, die ein benutzerdefiniertes URL-Schema verwenden. Wenn Sie beispielsweise Callbacks wie shouldOverrideUrlLoading() oder shouldInterceptRequest() implementieren, werden sie von WebView nur für gültige URLs aufgerufen.

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

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

Ungültige URLs wie die im vorherigen Beispiel werden in WebView nicht einheitlich behandelt. Wir empfehlen daher, stattdessen eine korrekt formatierte 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 wie im vorherigen Beispiel einen einfachen String in einem Link zu verwenden, können Sie ein benutzerdefiniertes Schema wie das folgende verwenden:

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

Du kannst diese URL dann in deiner 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 zum Starten von Intents für bestimmte URLs gedacht. Achten Sie bei der Implementierung darauf, false für URLs zurückzugeben, die von WebView verarbeitet werden. Sie sind jedoch nicht auf das Starten von Intents beschränkt. Sie können Start-Intents durch ein benutzerdefiniertes Verhalten in den vorherigen Codebeispielen ersetzen.

Wenn WebView das Laden von URLs überschreibt, wird automatisch ein Verlauf der besuchten Webseiten erfasst. Mit goBack() und goForward() können Sie rückwärts und vorwärts durch den Verlauf scrollen.

Im folgenden Beispiel wird beispielsweise gezeigt, wie Sie mit Activity die Rückwärtstaste des Geräts verwenden können, um zurückzugehen:

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 deine App AndroidX AppCompat 1.6.0 oder höher verwendet, kannst du 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 „wahr“ zurück, wenn es einen Webseitenverlauf für den Nutzer gibt, den er aufrufen kann. Ebenso können Sie mit canGoForward() prüfen, ob es einen Vorwärtsverlauf gibt. Wenn Sie diese Prüfung nicht ausführen, passiert bei goBack() und goForward() nichts, nachdem der Nutzer das Ende des Verlaufs erreicht hat.

Änderungen an der Gerätekonfiguration verarbeiten

Während der Laufzeit ändert sich der Aktivitätsstatus, wenn sich die Konfiguration eines Geräts ändert, z. B. wenn Nutzer das Gerät drehen oder einen Eingabemethoden-Editor schließen. Diese Änderungen führen dazu, dass die Aktivität eines WebView-Objekts gelöscht und eine neue Aktivität erstellt wird. Dadurch wird auch ein neues WebView-Objekt erstellt, das die URL des zerstörten Objekts lädt. Wenn Sie das Standardverhalten Ihrer Aktivität ändern möchten, können Sie festlegen, wie orientation-Änderungen in Ihrem Manifest behandelt werden. Weitere Informationen zum Umgang mit Konfigurationsänderungen während der Laufzeit finden Sie unter Konfigurationsänderungen verarbeiten.

Fenster verwalten

Anfragen zum Öffnen neuer Fenster werden standardmäßig ignoriert. Dies gilt unabhängig davon, ob sie mit JavaScript oder über das Zielattribut in einem Link geöffnet werden. Sie können WebChromeClient so anpassen, dass beim Öffnen mehrerer Fenster ein bestimmtes Verhalten festgelegt wird.

Um Ihre App sicherer zu machen, sollten Sie das Öffnen von Pop-ups und neuen Fenstern verhindern. Die sicherste Methode zur Implementierung dieses Verhaltens besteht darin, "true" an setSupportMultipleWindows() zu übergeben, aber nicht die Methode onCreateWindow() zu überschreiben, von der setSupportMultipleWindows() abhängt. Diese Logik verhindert, dass Seiten, die target="_blank" in ihren Links verwenden, geladen werden.