Tworzenie aplikacji internetowych w komponencie WebView

Użyj WebView do dostarczania aplikacji internetowej lub stronę internetową jako część aplikacji klienckiej. Klasa WebView jest rozszerzeniem klasy View w Androidzie, która umożliwia wyświetlanie stron internetowych w ramach układu aktywności. Nie zawiera ona funkcji funkcje w pełni opracowanej przeglądarki, takie jak elementy sterujące nawigacji czy pasku adresu. Domyślnie WebView wyświetla tylko stronę internetową.

WebView może Ci pomóc udostępniać w aplikacji informacje, których możesz potrzebować np. umowę użytkownika lub przewodnik użytkownika. W aplikacji na Androida możesz utworzyć obiekt Activity zawierający WebView, a następnie użyj go, aby wyświetlić dokument, który jest przechowywany online.

WebView może się też przydać, gdy Twoja aplikacja udostępnia dane użytkownikowi, który wymaga podania danych połączenie z internetem w celu pobrania danych, np. e-maili. W takim przypadku łatwiej może być utworzyć w aplikacji na Androida element WebView, który wyświetla stronę internetową ze wszystkimi danymi użytkownika, zamiast wysyłać żądanie sieciowe, a następnie analizować dane i renderować je w układzie Androida. Zamiast tego możesz zaprojektować stronę internetową dostosowaną do urządzeń z Androidem, a potem wdrożyć w aplikacji na Androida element WebView, który wczytuje tę stronę.

W tym dokumencie znajdziesz informacje o tym, jak zacząć korzystać z WebView, jak powiązać kod JavaScript ze strony internetowej z kodem po stronie klienta w aplikacji na Androida, jak obsługiwać nawigację po stronach oraz jak zarządzać oknami podczas korzystania z WebView.

Korzystanie z komponentu WebView we wcześniejszych wersjach Androida

Aby bezpiecznie korzystać z najnowszych funkcji WebView na urządzeniu, na którym jest Twoja aplikacja dodaj aplikację AndroidX z biblioteki Webkit. Jest to statyczna biblioteka, którą możesz dodać do aplikacji, aby korzystać z interfejsów API android.webkit, które nie są dostępne w starszych wersjach platformy.

Dodaj go do pliku build.gradle w ten sposób:

Kotlin

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

Odlotowe

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

Aby dowiedzieć się więcej, zapoznaj się z przykładem WebView w GitHub.

Dodawanie komponentu WebView do aplikacji

Aby dodać WebView do swojej aplikacji, możesz umieścić element <WebView> w swojej aplikacji układ aktywności lub ustaw całe okno Activity jako WebView onCreate()

Dodawanie komponentu WebView w układzie aktywności

Aby dodać WebView do swojej aplikacji w układzie, dodaj ten kod do pliku XML układu aktywności:

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

Aby wczytać stronę internetową w komponencie WebView, użyj elementu loadUrl(), jak w tym przykładzie:

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

Dodawanie WebView w metodzie onCreate()

Aby zamiast tego dodać WebView do aplikacji w metodzie onCreate() aktywności, użyj w podobny sposób:

Kotlin

val myWebView = WebView(activityContext)
setContentView(myWebView)

Java

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

Następnie otwórz stronę:

Kotlin

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

Java

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

Możesz też wczytać adres URL z ciągu 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");

Aplikacja musi mieć dostęp do internetu. Aby uzyskać dostęp do internetu, w pliku manifestu poproś o przyznanie uprawnienia INTERNET, jak w tym przykładzie:

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

Aby dostosować WebView, wykonaj jedną z tych czynności:

  • Włączanie obsługi pełnego ekranu za pomocąWebChromeClient. Te zajęcia jest również wywoływane, gdy usługa WebView potrzebuje uprawnień do modyfikowania interfejsu użytkownika aplikacji hosta. na przykład przez tworzenie lub zamykanie okien czy wysyłanie okien dialogowych JavaScript do użytkownika. Więcej informacji o debugowaniu w tym kontekście znajdziesz w artykule Debugowanie sieci
  • Postępowanie w przypadku zdarzeń, które mają wpływ na renderowanie treści, takich jak błędy w formularzu. lub nawigacji za pomocą WebViewClient Możesz też użyć tę podklasę do przechwytywania wczytywania adresu URL.
  • Włączanie języka JavaScript przez wprowadzenie zmian WebSettings
  • Używanie JavaScriptu do uzyskiwania dostępu do obiektów platformy Androida, które zostały wstrzyknięte do WebView.

Używanie JavaScriptu w komponencie WebView

Jeśli strona internetowa, którą chcesz wczytać w interfejsie WebView, korzysta z JavaScriptu, musisz włączyć JavaScript na urządzeniu WebView. Po włączeniu JavaScript możesz tworzyć interfejsy między kodem aplikacji a kodem JavaScript.

Włącz obsługę języka JavaScript

Domyślnie JavaScript jest wyłączony w WebView. Aby ją włączyć, użyj Urządzenie WebSettings zostało podłączone do urządzenia WebView. Pobierz WebSettings za pomocą getSettings(), a potem włącz JavaScript za pomocą setJavaScriptEnabled().

Zobacz ten przykład:

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 zapewnia dostęp do wielu innych ustawień, które mogą Ci się przydać. Jeśli na przykład tworzysz aplikację internetową zaprojektowaną specjalnie dla WebView w Twojej aplikacji na Androida, możesz zdefiniować ciąg znaków klienta użytkownika z setUserAgentString() wysyła zapytanie do niestandardowego klienta użytkownika na stronie internetowej, żądania strony to aplikacja na Androida.

Wiązanie kodu JavaScript z kodem Androida

Podczas tworzenia aplikacji internetowej zaprojektowanej specjalnie pod kątem urządzeń z systemem WebView w aplikacji na Androida, możesz tworzyć interfejsy między kodem JavaScript kodu Androida po stronie klienta. Kod JavaScript może na przykład wywołać metodę w kodzie Androida, aby wyświetlić Dialog, zamiast używać funkcji alert() w JavaScript.

Aby powiązać nowy interfejs między kodem JavaScript a kodem Androida, wywołaj funkcję addJavascriptInterface(), przekazując jej instancję klasy do powiązania z JavaScriptem i nazwę interfejsu, do którego JavaScript może się odwoływać, aby uzyskać dostęp do klasy.

W aplikacji na Androida możesz na przykład użyć tej klasy:

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

W tym przykładzie klasa WebAppInterface umożliwia stronie internetowej tworzenie wiadomości Toast za pomocą metody showToast().

Możesz powiązać tę klasę z kodem JavaScript, który działa w Twoim WebView, za pomocą funkcji addJavascriptInterface(), jak pokazano w tym przykładzie:

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

Spowoduje to utworzenie interfejsu o nazwie Android dla JavaScriptu uruchomionego w WebView W tym momencie aplikacja internetowa ma dostęp do WebAppInterface zajęcia. Oto kilka kodów HTML i JavaScript, które tworzy powiadomienie z nowym interfejsem, gdy użytkownik kliknie przycisk:

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

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

Nie musisz inicjować interfejsu Android w JavaScript. WebView automatycznie udostępnia je na Twojej stronie internetowej. Gdy użytkownik klika przycisk, funkcja showAndroidToast() korzysta z interfejsu Android aby wywołać metodę WebAppInterface.showToast().

Uchwyć nawigację po stronie

Gdy użytkownik kliknie link na stronie internetowej w urządzeniu WebView, domyślnie na urządzeniu z Androidem uruchamia aplikację obsługującą adresy URL. Zwykle otwierana jest domyślna przeglądarka, wczytuje docelowy adres URL. Możesz jednak zastąpić to zachowanie w swojej aplikacji WebView, aby linki otwierały się w niej. Następnie możesz pozwolić użytkownikowi na przechodzenie w przód i w tył po historii stron internetowych przechowywanej przez WebView.

Aby otworzyć linki kliknięte przez użytkownika, podaj WebViewClient dla WebView za pomocą setWebViewClient(). Wszystkie linki, które użytkownik kliknie, wczytują się w Twoim WebView. Jeśli chcesz mieć większą kontrolę nad tam, gdzie wczytuje się kliknięty link, utwórz własny element WebViewClient, który zastąpi shouldOverrideUrlLoading() . W tym przykładzie zakładamy, że MyWebViewClient jest klasą wewnętrzną klasy 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;
  }
}

Następnie utwórz instancję nowego WebViewClient dla środowiska WebView:

Kotlin

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

Java

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

Gdy użytkownik kliknie link, system wywoła metodę shouldOverrideUrlLoading(), która sprawdza, czy host adresu URL pasuje do określonej domeny zdefiniowanej w poprzednim przykładzie. Jeśli dane będą zgodne, metoda zwraca wartość „false” (fałsz) i nie zastępuje wczytywania adresu URL. Pozwala to WebView wczytać adres URL w zwykły sposób. Jeśli host adresu URL nie pasuje, tworzony jest element Intent, który uruchamia domyślny element Activity do obsługi adresów URL. Rozwiązuje się on do domyślnej przeglądarki internetowej użytkownika.

Obsługa niestandardowych adresów URL

WebView stosuje ograniczenia podczas żądania zasobów i rozwiązywania linków, które używają niestandardowego schematu adresu URL. Na przykład: jeśli implementujesz wywołania zwrotne, takie jak shouldOverrideUrlLoading() lub shouldInterceptRequest(), a następnie WebView wywołuje je tylko dla prawidłowych adresów URL.

Na przykład funkcja WebView może nie wywoływać metody shouldOverrideUrlLoading() w przypadku linków takich jak:

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

Nieprawidłowe adresy URL, takie jak ten z poprzedniego przykładu, są obsługiwane niespójnie w polu WebView, dlatego zalecamy użycie adresu URL o prawidłowym formacie. Możesz użyć schematu niestandardowego lub adresu URL HTTPS w domenie należącej do Twojej organizacji elementów sterujących.

Zamiast prostego ciągu znaków w linku, jak w poprzednim przykładzie, możesz użyć schematu niestandardowego, takiego jak:

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

Następnie możesz obsługiwać ten adres URL w metodzie shouldOverrideUrlLoading() w ten sposób:

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

Interfejs API shouldOverrideUrlLoading() służy przede wszystkim do uruchamiania intencji w przypadku określonych adresów URL. Podczas jego wdrażania pamiętaj, aby zwracać false w przypadku adresów URL, których uchwyty to WebView. Nie musisz jednak ograniczać się do uruchamiania intencji. W powyższych przykładach kodu możesz zastąpić intencje uruchamiania dowolnym zachowaniem niestandardowym.

Gdy WebView zastąpi wczytywanie adresu URL, automatycznie będzie gromadzić historię odwiedzonych stron internetowych. Możesz przechodzić wstecz i do przodu w historię z goBack() i goForward()

Na przykład poniżej pokazujemy, jak urządzenie Activity może korzystać z Wstecz przycisk przechodzenia wstecz:

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

Jeśli używasz AndroidaX AppCompat 1.6.0 lub nowszego, możesz uprościć poprzednią wersję jeszcze więcej:

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

Metoda canGoBack() zwraca wartość true, jeśli użytkownik ma historię strony internetowej, którą chce odwiedzić. Podobnie możesz użyć canGoForward(), aby sprawdzić, czy istnieje historia do przodu. Jeśli nie sprawdzisz tego, gdy użytkownik dotrze do końca historii, goBack() i goForward() robią to nic.

Obsługa zmian konfiguracji urządzenia

Podczas działania stan aktywności zmienia się, gdy zmienia się konfiguracja urządzenia, np. gdy użytkownik obróci urządzenie lub zamknie edytor metody wprowadzania (IME). Te zmiany powodują zniszczenie aktywności obiektu WebView i utworzenie nowej aktywności, która tworzy też nowy obiekt WebView, który wczytuje adres URL usuniętego obiektu. Aby zmienić domyślne zachowanie aktywności, możesz zmienić sposób, w jaki obsługuje ona zmiany orientation w pliku manifestu. Więcej informacji na temat obsługi zmian konfiguracji w trakcie działania, przeczytaj artykuł Obsługuj konfigurację zmian.

Zarządzanie oknami

Domyślnie prośby o otwieranie nowych okien są ignorowane. Dzieje się tak niezależnie od tego, czy są otwierane przez JavaScript czy przez atrybut docelowy w linku. Możesz dostosować WebChromeClient, aby dostosować sposób otwierania wielu oknach.

Aby zwiększyć bezpieczeństwo aplikacji, najlepiej zablokuj wyskakujące okienka i nowe okna, przed otwarciem. Najbezpieczniejszym sposobem wdrożenia tego sposobu jest przekazanie funkcji "true" do setSupportMultipleWindows() ale nie zastępują onCreateWindow() , od której zależy wartość setSupportMultipleWindows(). Ta logika uniemożliwia strona, która w linkach korzysta z elementu target="_blank".