Web-Apps in WebView erstellen

Verwenden Sie WebView, um eine Webanwendung oder eine Webseite als Teil einer Clientanwendung bereitzustellen. Die Klasse WebView ist eine Erweiterung der Android-Klasse View, mit der du Webseiten als Teil deines Aktivitätslayouts anzeigen kannst. Er umfasst nicht die Funktionen eines vollständig entwickelten Webbrowsers wie Navigationssteuerelemente oder eine Adressleiste. Standardmäßig wird in WebView lediglich eine Webseite angezeigt.

Mit WebView können Sie in Ihrer Anwendung Informationen zur Verfügung stellen, die Sie möglicherweise aktualisieren müssen, z. B. eine Endnutzervereinbarung oder ein Nutzerhandbuch. Innerhalb deiner Android-App kannst du ein Activity erstellen, das eine WebView enthält, und dann dieses zum Anzeigen deines online gehosteten Dokuments verwenden.

WebView kann auch hilfreich sein, wenn Ihre Anwendung dem Nutzer Daten bereitstellt, für die eine Internetverbindung zum Abrufen von Daten wie E-Mails erforderlich ist. In diesem Fall könnte es einfacher sein, ein WebView in deiner Android-App zu erstellen, das 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 speziell für Android-Geräte entwerfen und dann in deiner Android-App ein WebView implementieren, das die Webseite lädt.

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

Mit WebView unter älteren Android-Versionen arbeiten

Fügen Sie die AndroidX Webkit-Bibliothek hinzu, um die aktuellen WebView-Funktionen auf dem Gerät, auf dem Ihre 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 ältere Plattformversionen nicht verfügbar sind.

So fügen Sie ihn der Datei build.gradle hinzu:

Kotlin

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

Groovig

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 eine WebView hinzufügen möchtest, kannst du das <WebView>-Element in dein Aktivitätslayout einbinden oder das gesamte Activity-Fenster als WebView in onCreate() festlegen.

WebView im Aktivitätslayout hinzufügen

Wenn Sie Ihrer App im Layout ein WebView-Element hinzufügen möchten, fügen Sie den folgenden Code in die Layout-XML-Datei Ihrer Aktivität ein:

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

Zum Laden einer Webseite im WebView 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

Um Ihrer App stattdessen in der onCreate()-Methode einer Aktivität ein WebView hinzuzufügen, 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. Um Internetzugriff zu erhalten, fordern Sie in der Manifestdatei die Berechtigung INTERNET an, wie im folgenden Beispiel gezeigt:

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

Sie können Ihre WebView anpassen, indem Sie einen der folgenden Schritte ausführen:

  • 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. beim Erstellen oder Schließen von Fenstern oder zum Senden von JavaScript-Dialogfeldern an den Nutzer. Weitere Informationen zum Debugging in diesem Kontext finden Sie unter Fehler bei Webanwendungen beheben.
  • Ereignisse verarbeiten, die sich auf das Rendering von Inhalten auswirken, z. B. Fehler beim Einreichen von Formularen oder der Navigation mit WebViewClient. Sie können diese Unterklasse auch verwenden, um das Laden von URLs abzufangen.
  • Aktivieren Sie JavaScript, indem Sie WebSettings ändern.
  • Auf Android-Framework-Objekte zugreifen, die du in ein WebView-Objekt eingeschleust hast mit JavaScript

JavaScript in WebView verwenden

Wenn die Webseite, die du in WebView laden möchtest, JavaScript verwendet, musst du JavaScript für dein WebView aktivieren. Nachdem du JavaScript aktiviert hast, kannst du Schnittstellen zwischen deinem App-Code und deinem JavaScript-Code erstellen.

JavaScript aktivieren

JavaScript ist in einem WebView standardmäßig deaktiviert. Sie können sie über das WebSettings aktivieren, das an Ihre 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);

Mit WebSettings haben Sie Zugriff auf eine Reihe weiterer nützlicher Einstellungen. Wenn du beispielsweise eine Webanwendung entwickelst, die speziell für WebView in deiner Android-App entwickelt wurde, kannst du mit setUserAgentString() einen benutzerdefinierten User-Agent-String definieren und dann den benutzerdefinierten User-Agent auf deiner Webseite abfragen, um zu prüfen, ob es sich bei dem Client, der die Webseite anfordert, um deine Android-App handelt.

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 deinem JavaScript-Code und clientseitigem Android-Code erstellen. Beispielsweise kann dein JavaScript-Code eine Methode in deinem Android-Code aufrufen, um ein Dialog anzuzeigen, anstatt die Funktion alert() von JavaScript zu verwenden.

Wenn Sie eine neue Schnittstelle zwischen JavaScript- und Android-Code einbinden möchten, rufen Sie addJavascriptInterface() auf. Dabei übergeben Sie eine Klasseninstanz zur Bindung an Ihr JavaScript sowie einen Schnittstellennamen, den Ihr JavaScript für den Zugriff auf die Klasse aufrufen kann.

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

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, mit der Methode showToast() eine Toast-Nachricht zu erstellen.

Sie können diese Klasse mit addJavascriptInterface() an den JavaScript-Code binden, der in 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 im WebView ausgeführt wird. Jetzt hat Ihre Webanwendung Zugriff auf die Klasse WebAppInterface. Hier sehen Sie zum Beispiel HTML- und JavaScript-Code, mit dem auf der neuen Benutzeroberfläche eine Toast-Nachricht 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 von JavaScript aus initialisiert werden. WebView stellt es automatisch für deine Webseite zur Verfügung. Wenn ein Nutzer auf die Schaltfläche tippt, verwendet die showAndroidToast()-Funktion also die Android-Oberfläche, um die WebAppInterface.showToast()-Methode aufzurufen.

Seitennavigation verarbeiten

Wenn der Nutzer auf einen Link von einer Webseite in deinem WebView tippt, startet Android standardmäßig eine App, die URLs verarbeitet. Normalerweise wird der Standardwebbrowser geöffnet und lädt die Ziel-URL. Sie können dieses Verhalten jedoch für WebView überschreiben, sodass Links in WebView geöffnet werden. Anschließend können Sie dem Nutzer die Möglichkeit geben, seinen Webseitenverlauf, der über die WebView verwaltet wird, vorwärts und rückwärts zu navigieren.

Wenn du Links öffnen möchtest, auf die der Nutzer getippt hat, musst du mithilfe von setWebViewClient() eine WebViewClient für deine WebView angeben. Alle Links, die der Nutzer antippt, werden in deinem WebView geladen. Wenn Sie genauer steuern möchten, wo ein angeklickter Link geladen wird, erstellen Sie einen eigenen WebViewClient, der 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 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. Diese prüft, ob der URL-Host wie im vorherigen Beispiel definiert mit einer bestimmten Domain übereinstimmt. Bei einer Übereinstimmung gibt die Methode „false“ zurück und überschreibt das Laden der URL nicht. WebView kann die URL dann wie gewohnt laden. Wenn der URL-Host nicht übereinstimmt, wird ein Intent erstellt, um den standardmäßigen Activity zur Verarbeitung von URLs zu starten, der in den Standardwebbrowser des Nutzers aufgelöst wird.

Umgang mit benutzerdefinierten 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.

Es kann beispielsweise sein, dass WebView die shouldOverrideUrlLoading()-Methode für Links wie diesen nicht aufruft:

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

Ungültige URLs wie die im vorherigen Beispiel werden in WebView inkonsistent gehandhabt. Daher empfehlen wir, 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 kontrolliert 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 vorgesehen. Bei der Implementierung muss für URLs mit den WebView-Handles false zurückgegeben werden. Sie sind jedoch nicht auf das Starten von Intents beschränkt. Sie können das Starten von Intents durch ein beliebiges 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 Ihr Activity mithilfe der Zurück-Schaltfläche auf dem Gerät rückwärts navigieren kann:

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 für den Nutzer ein Webseitenverlauf vorhanden ist. Ebenso können Sie mit canGoForward() prüfen, ob ein Weiterleitungsverlauf vorhanden ist. Wenn Sie diese Prüfung nicht ausführen, werden goBack() und goForward() nichts ausgeführt, sobald der Nutzer das Ende des Verlaufs erreicht hat.

Änderungen an der Gerätekonfiguration verarbeiten

Während der Laufzeit werden Aktivitätsstatusänderungen vorgenommen, wenn sich die Konfiguration eines Geräts ändert, z. B. wenn Nutzer das Gerät drehen oder einen Eingabemethodeneditor schließen. Durch diese Änderungen wird die Aktivität eines WebView-Objekts gelöscht und eine neue Aktivität erstellt. Dabei wird auch ein neues WebView-Objekt erstellt, das die URL des gelöschten Objekts lädt. 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. Dies gilt unabhängig davon, ob sie über JavaScript oder über das Zielattribut in einem Link geöffnet werden. Sie können den WebChromeClient so anpassen, dass Sie ein eigenes Verhalten beim Öffnen mehrerer Fenster angeben.

Zum Schutz Ihrer App sollten Sie das Öffnen von Pop-ups und neuen Fenstern verhindern. Die sicherste Möglichkeit, dieses Verhalten zu implementieren, besteht darin, "true" an setSupportMultipleWindows() zu übergeben, ohne die Methode onCreateWindow() zu überschreiben, von der setSupportMultipleWindows() abhängt. Dadurch wird verhindert, dass Seiten geladen werden, die target="_blank" in ihren Links verwenden.