Web-Apps in WebView erstellen

Mit WebView können Sie eine Webanwendung oder eine Webseite als Teil einer Clientanwendung bereitstellen. Die WebView-Klasse ist eine Erweiterung der Android-Klasse View, mit der du Webseiten als Teil deines Aktivitätslayouts anzeigen kannst. Sie umfasst nicht die Funktionen eines vollständig entwickelten Webbrowsers, z. B. Navigationssteuerelemente oder eine Adressleiste. WebView zeigt standardmäßig nur eine Webseite an.

Mit WebView können Sie Informationen in Ihrer Anwendung bereitstellen, die Sie möglicherweise aktualisieren müssen, z. B. eine Endnutzervereinbarung oder ein Nutzerhandbuch. 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 vielleicht einfacher, eine WebView in deiner Android-App zu erstellen, die eine Webseite mit allen Nutzerdaten anzeigt, anstatt eine Netzwerkanfrage durchzuführen, die Daten dann zu analysieren und in einem Android-Layout zu rendern. Stattdessen kannst du eine Webseite entwerfen, die auf Android-Geräte zugeschnitten ist, und dann eine WebView in deiner Android-App implementieren, mit der die Webseite geladen wird.

In diesem Dokument werden die ersten Schritte mit WebView beschrieben. Außerdem wird beschrieben, wie Sie JavaScript von Ihrer Webseite an clientseitigen Code in der Android-App binden, die Seitennavigation verwenden und Fenster bei Verwendung von WebView verwalten.

WebView in älteren Android-Versionen verwenden

Füge die AndroidX Webkit-Bibliothek hinzu, um aktuellere WebView-Funktionen auf dem Gerät, auf dem deine App ausgeführt wird, sicher zu nutzen. 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 ihn so zu Ihrer build.gradle-Datei hinzu:

Kotlin

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

Cool

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

Weitere Informationen finden Sie im Beispiel WebView auf GitHub.

WebView zur App hinzufügen

Wenn du deiner App ein WebView-Objekt hinzufügen möchtest, kannst du das <WebView>-Element in das Aktivitätslayout aufnehmen oder das gesamte Activity-Fenster als WebView in onCreate() festlegen.

WebView zum Aktivitätslayout hinzufügen

Um Ihrer App im Layout ein 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"
/>

Verwenden Sie zum Laden einer Webseite im WebView 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 eine WebView hinzufügen möchten, verwenden Sie eine Logik wie diese:

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 erhalten möchten, fordern Sie in Ihrer Manifestdatei die Berechtigung INTERNET an, wie im folgenden Beispiel gezeigt:

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

Sie haben folgende Möglichkeiten, Ihr 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 abgeleitete Klasse auch verwenden, um das Laden von URLs abzufangen.
  • Aktivieren Sie JavaScript durch Ändern von WebSettings.
  • Mit JavaScript auf Android-Framework-Objekte zugreifen, die in eine WebView eingefügt wurden

JavaScript in WebView verwenden

Wenn die Webseite, die du in deinem WebView laden möchtest, JavaScript verwendet, musst du JavaScript für dein 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 sie über das WebSettings aktivieren, das an WebView angehängt 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);

WebSettings bietet 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 WebView in Ihrer Android-App entwickelt wurde, 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 du eine Webanwendung entwickelst, die speziell für WebView in deiner Android-App entwickelt wurde, kannst du Schnittstellen zwischen dem JavaScript-Code und dem clientseitigen Android-Code erstellen. Beispielsweise kann über den JavaScript-Code eine Methode in deinem Android-Code aufgerufen werden, um ein Dialog anzuzeigen, anstatt die alert()-Funktion von JavaScript zu verwenden.

Um eine neue Schnittstelle zwischen dem JavaScript- und Android-Code zu binden, rufen Sie addJavascriptInterface() auf. Übergeben Sie dabei eine Klasseninstanz zur Bindung an den JavaScript-Code sowie einen Schnittstellennamen, den das 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 ermöglicht die Klasse WebAppInterface der Webseite, mithilfe der Methode showToast() eine Nachricht vom Typ Toast zu 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 mit dem Namen Android für JavaScript erstellt, das in WebView ausgeführt wird. Jetzt hat Ihre Webanwendung Zugriff auf die Klasse WebAppInterface. Mit dem folgenden HTML- und JavaScript-Code wird beispielsweise über die neue Benutzeroberfläche eine Toast-Nachricht erstellt, 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. Das WebView stellt sie automatisch für deine 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 verwalten

Wenn der Nutzer in Ihrem 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 Ihre WebView überschreiben, sodass Links innerhalb Ihres WebView geöffnet werden. Anschließend kannst du zulassen, dass der Nutzer durch den von WebView verwalteten Webseitenverlauf vorwärts und rückwärts navigiert.

Um Links zu öffnen, auf die der Nutzer getippt hat, musst du mithilfe von setWebViewClient() eine WebViewClient für dein WebView angeben. Alle Links, auf die der Nutzer tippt, werden in WebView geladen. Wenn Sie genauer steuern möchten, wo ein angeklickter Link geladen wird, können Sie eine eigene WebViewClient erstellen, mit der die Methode shouldOverrideUrlLoading() überschrieben wird. 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 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. Stimmen sie überein, gibt die Methode "false" zurück und überschreibt das Laden der URL nicht. Der WebView kann die URL dann wie gewohnt laden. Wenn der URL-Host nicht übereinstimmt, wird ein Intent erstellt, um die standardmäßige Activity für die Verarbeitung von URLs zu starten, die zum Standardwebbrowser des Nutzers aufgelöst wird.

Benutzerdefinierte URLs verarbeiten

WebView wendet Einschränkungen beim Anfordern von Ressourcen und Auflösen von Links an, 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.

Beispielsweise kann WebView die Methode shouldOverrideUrlLoading() für Links wie diese nicht aufrufen:

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

Ungültige URLs, wie im vorherigen Beispiel gezeigt, werden in WebView nicht einheitlich verarbeitet. 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>

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 zum Starten von Intents für bestimmte URLs gedacht. Wenn du sie implementierst, musst du false für URLs zurückgeben, die von den Handles WebView verwendet 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 im Verlauf vor- und zurückspringen.

Das folgende Beispiel zeigt, wie dein Activity die Schaltfläche „Zurück“ des Geräts verwenden kann, 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 „true“ zurück, wenn ein Webseitenverlauf für den Nutzer vorhanden ist. Ebenso können Sie mit canGoForward() prüfen, ob ein Weiterleitungsverlauf vorhanden ist. 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 Eingabemethodeneditor (IME) 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 du das Standardverhalten deiner Aktivität ändern möchtest, kannst du in deinem Manifest anpassen, wie orientation-Änderungen verarbeitet 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. Du kannst dein WebChromeClient so anpassen, dass es dein eigenes Verhalten beim Öffnen mehrerer Fenster bietet.

Um die Sicherheit Ihrer Anwendung zu gewährleisten, sollten Sie verhindern, dass Pop-ups und neue Fenster geöffnet werden. 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.