Użyj WebView, aby dostarczać aplikację internetową lub stronę internetową jako część aplikacji klienckiej. Klasa WebView jest rozszerzeniem klasy View na Androidzie
, które umożliwia wyświetlanie stron internetowych jako części układu aktywności. Nie zawiera ona funkcji w pełni rozwiniętej przeglądarki internetowej, takich jak elementy sterujące nawigacją czy pasek adresu. Domyślnie WebView wyświetla tylko stronę internetową.
WebView może pomóc Ci w udostępnianiu w aplikacji informacji, które mogą wymagać aktualizacji, np. umowy z użytkownikiem lub przewodnika. W aplikacji na Androida,
możesz utworzyć Activity, która zawiera
WebView, a następnie użyć jej do wyświetlania dokumentu hostowanego online.
WebView może też pomóc, gdy aplikacja udostępnia użytkownikowi dane, które wymagają połączenia z internetem, np. e-maile. W takim przypadku może się okazać, że łatwiej jest utworzyć w aplikacji na Androida WebView, która wyświetla stronę internetową ze wszystkimi danymi użytkownika, niż 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 następnie zaimplementować w aplikacji na Androida WebView, która wczytuje tę stronę.
Z tego dokumentu dowiesz się, jak zacząć korzystać z WebView, jak powiązać JavaScript ze strony internetowej z kodem po stronie klienta w aplikacji na Androida, jak obsługiwać nawigację po stronie i jak zarządzać oknami podczas korzystania z WebView.
Praca z WebView w starszych wersjach Androida
Aby bezpiecznie korzystać z nowszych funkcji WebView na urządzeniu, na którym działa Twoja aplikacja
, dodaj bibliotekę AndroidX Webkit. Jest to biblioteka statyczna, 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 ją do pliku build.gradle w ten sposób:
Kotlin
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
Dynamiczny
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
Więcej informacji znajdziesz w przykładzie WebView na GitHubie.
Dodawanie WebView do aplikacji
Aby dodać WebView do aplikacji, możesz umieścić element <WebView> w swoim
układzie aktywności lub ustawić całe okno Activity jako WebView w
onCreate().
Dodawanie WebView w układzie aktywności
Aby dodać WebView do 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_hei>ght="match_parent" /
Aby wczytać stronę internetową w WebView, użyj loadUrl(), jak pokazano 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 onCreate()
Aby dodać WebView do aplikacji w metodzie onCreate() aktywności, użyj logiki podobnej do tej:
Kotlin
val myWebView = WebView(activityContext) setContentView(myWebView)
Java
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
Następnie wczytaj 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 = &<quot><;htm>lbody'%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 = &<quot><;htm>lbody'%23' is the percent <code ><for ‘>#‘ /body/html"; String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING); myWebView.loadData(encodedHtml, "text/html", "base64");
Twoja aplikacja musi mieć dostęp do internetu. Aby uzyskać dostęp do internetu, poproś o uprawnienie
INTERNET w pliku manifestu, jak pokazano w tym
przykładzie:
<manifest ... > <uses-permission android:name="android.permission.INTERN>ET" </ ...> /manifest
WebView możesz dostosować, wykonując dowolną z tych czynności:
- Włączanie obsługi pełnego ekranu za pomocą
WebChromeClient. Ta klasa jest też wywoływana, gdyWebViewpotrzebuje uprawnień do zmiany interfejsu aplikacji hosta, np. do tworzenia lub zamykania okien albo wysyłania do użytkownika okien dialogowych JavaScript. Więcej informacji o debugowaniu w tym kontekście znajdziesz w artykule Debugowanie aplikacji internetowych. - Obsługa zdarzeń, które mają wpływ na renderowanie treści, np. błędów podczas przesyłania formularzy
lub nawigacji za pomocą
WebViewClient. Możesz też użyć tej podklasy do przechwytywania wczytywania adresów URL. - Włączanie JavaScriptu przez modyfikowanie
WebSettings. - Używanie JavaScriptu do uzyskiwania dostępu do obiektów frameworka Androida, które zostały wstrzyknięte do
WebView.
Używanie JavaScriptu w WebView
Jeśli strona internetowa, którą chcesz wczytać w WebView, używa JavaScriptu, musisz włączyć JavaScript w WebView. Gdy włączysz JavaScript, możesz tworzyć interfejsy między kodem aplikacji a kodem JavaScript.
Włączanie JavaScriptu
JavaScript jest domyślnie wyłączony w WebView. Możesz go włączyć za pomocą WebSettings dołączonego do WebView. Pobierz WebSettings za pomocą
getSettings(), a następnie włącz JavaScript za pomocą
setJavaScriptEnabled().
Przyjrzyj się temu przykładowi:
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ą przeznaczoną
specjalnie do WebView w aplikacji na Androida, możesz zdefiniować niestandardowy
ciąg znaków agenta użytkownika za pomocą setUserAgentString(), a następnie wysłać zapytanie o niestandardowego agenta
użytkownika na stronie internetowej, aby sprawdzić, czy klient wysyłający żądanie do strony internetowej to
Twoja aplikacja na Androida.
Wiązanie kodu JavaScript z kodem Androida
Podczas tworzenia aplikacji internetowej przeznaczonej specjalnie do WebView w aplikacji na Androida możesz tworzyć interfejsy między kodem JavaScript a kodem Androida po stronie klienta. Na przykład kod JavaScript może wywoływać metodę w
kodzie Androida, aby wyświetlić Dialog, zamiast używać funkcji
alert() JavaScript.
Aby powiązać nowy interfejs między kodem JavaScript a kodem Androida, wywołaj
addJavascriptInterface(), przekazując do niego instancję klasy do powiązania z
JavaScriptem oraz nazwę interfejsu, za pomocą której JavaScript może wywoływać
klasę.
Więcej informacji o komunikacji między JavaScriptem a kodem natywnym, w tym o nowocześniejszych i bezpieczniejszych interfejsach API, znajdziesz w artykule Dostęp do natywnych interfejsów API za pomocą JSBridge.
W aplikacji na Androida możesz na przykład umieścić tę klasę:
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 utworzenie
Toast wiadomości za pomocą metody showToast().
Możesz powiązać tę klasę z JavaScriptem działającym w WebView za pomocą 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 działającego w WebView. W tym momencie aplikacja internetowa ma dostęp do klasy WebAppInterface. Oto na przykład kod HTML i JavaScript, który tworzy wiadomość toastową za pomocą nowego interfejsu, gdy użytkownik kliknie przycisk:
<input type="button" value="Say hello" onClick="showAndroidT>oa<st('Hello Android!')&>quot; / script type="text/javascript" function showAndroidToast(t<oast) {> Android.showToast(toast); } /script
Nie musisz inicjować interfejsu Android z JavaScriptu. WebView automatycznie udostępnia go stronie internetowej. Gdy użytkownik
kliknie przycisk, funkcja showAndroidToast() użyje interfejsu Android do wywołania metody WebAppInterface.showToast().
Obsługa nawigacji na stronie
Gdy użytkownik kliknie link na stronie internetowej w WebView, Android domyślnie uruchamia aplikację, która obsługuje adresy URL. Zwykle otwiera się domyślna przeglądarka internetowa i wczytuje docelowy adres URL. Możesz jednak zastąpić to działanie w WebView, aby linki otwierały się w WebView. Następnie możesz pozwolić użytkownikowi na poruszanie się wstecz i do przodu w historii stron internetowych, która jest utrzymywana przez WebView.
Aby otwierać linki klikane przez użytkownika, podaj WebViewClient dla WebView
za pomocą setWebViewClient(). Wszystkie linki klikane przez użytkownika będą wczytywane w WebView. Jeśli chcesz mieć większą kontrolę nad tym, gdzie wczytuje się kliknięty link, utwórz własny
WebViewClient który zastępuje shouldOverrideUrlLoading()
metodę. W tym przykładzie zakłada się, że MyWebViewClient jest klasą wewnętrzną 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ę tego nowego WebViewClient dla 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 sprawdzi, czy host adresu URL pasuje do określonej domeny, jak zdefiniowano w poprzednim przykładzie. Jeśli pasuje, metoda zwraca wartość false i nie zastępuje wczytywania adresu URL. Umożliwia to WebView wczytanie adresu URL jak zwykle.
Jeśli host adresu URL nie pasuje, tworzony jest Intent, aby uruchomić
domyślny Activity do obsługi adresów URL, który jest rozwiązywany do domyślnej przeglądarki internetowej użytkownika.
Obsługa niestandardowych adresów URL
WebView stosuje ograniczenia podczas wysyłania żądań zasobów i rozwiązywania linków, które używają niestandardowego schematu URI adresu URL. Jeśli na przykład zaimplementujesz wywołania zwrotne, takie jak
shouldOverrideUrlLoading() lub shouldInterceptRequest(), to
WebView wywoła je tylko w przypadku prawidłowych adresów URL.
Na przykład WebView może nie wywołać metody shouldOverrideUrlLoading() w przypadku linków takich jak ten:
<a href="showPro>file"Sh<ow> Profile/a
Nieprawidłowe adresy URL, takie jak ten pokazany w poprzednim przykładzie, są obsługiwane w WebView w sposób niespójny, dlatego zalecamy używanie prawidłowo sformatowanego adresu URL.
Możesz użyć schematu niestandardowego lub adresu URL HTTPS dla domeny, którą kontroluje Twoja organizacja.
Zamiast używać w linku prostego ciągu znaków, jak w poprzednim przykładzie, możesz użyć schematu niestandardowego, takiego jak ten:
<a href="example-app:showPro>file"Sh<ow> 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() jest przeznaczony głównie do uruchamiania intencji dla określonych adresów URL. Podczas jego implementowania pamiętaj, aby zwracać wartość false w przypadku adresów URL obsługiwanych przez WebView. Nie musisz jednak ograniczać się do uruchamiania intencji. W poprzednich przykładach kodu możesz zastąpić uruchamianie intencji dowolnym niestandardowym działaniem.
Nawigacja po historii stron internetowych
Gdy WebView zastępuje wczytywanie adresów URL, automatycznie gromadzi historię odwiedzonych stron internetowych. Możesz poruszać się wstecz i do przodu w
historii za pomocą goBack() i goForward().
Na przykład ten kod pokazuje, jak Activity może używać przycisku Wstecz na urządzeniu do nawigacji 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_B&&ACK 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_BA&&CK) 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 Twoja aplikacja używa AndroidX AppCompat w wersji 1.6.0 lub nowszej, możesz jeszcze bardziej uprościć poprzedni fragment kodu:
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 może przejść do strony internetowej w historii. Podobnie możesz użyć canGoForward(), aby sprawdzić, czy
istnieje historia do przodu. Jeśli nie wykonasz tego sprawdzenia, po dotarciu przez użytkownika do końca historii metody goBack() i goForward() nie będą wykonywać żadnych działań.
Obsługa zmian konfiguracji urządzenia
Podczas działania aplikacji zmiany stanu działania występują, gdy zmienia się konfiguracja urządzenia, np. gdy użytkownicy obracają urządzenie lub zamykają edytor IME. Te zmiany powodują zniszczenie aktywności obiektu WebView i utworzenie nowej aktywności, która tworzy też nowy obiekt WebView wczytujący adres URL zniszczonego obiektu. Aby zmodyfikować domyślne działanie aktywności, możesz zmienić sposób obsługi zmian orientation w manifeście. Więcej informacji o obsłudze zmian konfiguracji w czasie działania znajdziesz w artykule Obsługa zmian konfiguracji.
Zarządzanie oknami
Domyślnie żądania otwarcia nowych okien są ignorowane. Dotyczy to zarówno okien otwieranych przez JavaScript, jak i przez atrybut target w linku. Możesz dostosować WebChromeClient, aby zapewnić własne działanie podczas otwierania wielu okien.
Aby zwiększyć bezpieczeństwo aplikacji, najlepiej uniemożliwić otwieranie wyskakujących okienek i nowych okien. Najbezpieczniejszym sposobem na zaimplementowanie tego działania jest przekazanie wartości "true" do
setSupportMultipleWindows() bez zastępowania metody
onCreateWindow(), od której zależy setSupportMultipleWindows().
Ta logika uniemożliwia wczytywanie stron, które używają w linkach target="_blank" od
wczytywania.