Android udostępnia kilka interfejsów API, które ułatwiają zarządzanie
WebView
obiekty, które wyświetlają treści z internetu w aplikacji.
Na tej stronie dowiesz się, jak używać tych interfejsów API w pracy z usługą WebView
obiektów, zwiększając w ten sposób stabilność i bezpieczeństwo aplikacji.
Interfejs API wersji
Począwszy od Androida 7.0 (poziom interfejsu API 24) użytkownicy mają do wyboru kilka
różne pakiety do wyświetlania treści internetowych w obiekcie WebView
.
AndroidX.webkit
biblioteka obejmuje
getCurrentWebViewPackage()
metoda pobierania informacji o pakiecie, który wyświetla sieć
treści w aplikacji. Metoda ta przydaje się przy analizowaniu błędów występujących tylko
gdy aplikacja próbuje wyświetlić treści z internetu przy użyciu pakietu
implementacja WebView
.
Aby użyć tej metody, dodaj mechanizm logiczny widoczny w tym fragmencie kodu:
Kotlin
val webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext) Log.d("MY_APP_TAG", "WebView version: ${webViewPackageInfo.versionName}")
Java
PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext); Log.d("MY_APP_TAG", "WebView version: " + webViewPackageInfo.versionName);
Usługa Bezpieczne przeglądanie Google
Aby zwiększyć bezpieczeństwo użytkowników podczas przeglądania internetu, WebView
Obiekty weryfikuje adresy URL za pomocą
Bezpieczne przeglądanie Google,
który pozwala aplikacji wyświetlać użytkownikom ostrzeżenie przy próbie przejścia do
potencjalnie niebezpiecznej stronie.
Chociaż domyślna wartość EnableSafeBrowsing
to prawda,
To sytuacje, gdy możesz włączyć Bezpieczne przeglądanie tylko warunkowo lub
możesz ją wyłączyć. Android 8.0 (poziom interfejsu API 26) i nowsze obsługują używanie
setSafeBrowsingEnabled()
aby włączyć lub wyłączyć Bezpieczne przeglądanie dla pojedynczego obiektu WebView
.
Jeśli chcesz, aby wszystkie obiekty WebView
zrezygnowały z Bezpiecznego przeglądania
sprawdź, dodaj ten element <meta-data>
do
plik manifestu:
<manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> ... </application> </manifest>
Zdefiniuj działania zautomatyzowane
Gdy instancja WebView
próbuje wczytać stronę, która jest
sklasyfikowanych przez Google jako znane zagrożenie, domyślnie WebView
wyświetla reklamę pełnoekranową, która ostrzega użytkowników o znanym zagrożeniu. Ten ekran pokazuje
użytkownicy mogą wczytać adres URL mimo to lub wrócić do poprzedniej strony,
bezpieczeństwa.
Jeśli kierujesz aplikację na Androida 8.1 (poziom interfejsu API 27) lub nowszego, możesz zdefiniować w sposób zautomatyzowany, w jaki sposób aplikacja reaguje na znane zagrożenia: sposoby:
- Możesz określić, czy aplikacja będzie zgłaszać znane zagrożenia bezpieczeństwa Przeglądanie.
- Aplikacja może automatycznie wykonywać określone działanie, np. jako powrót do zabezpieczeń – za każdym razem, gdy napotka adres URL, sklasyfikowanych jako znane zagrożenia.
Te fragmenty kodu pokazują, jak przekazać instrukcje instancji aplikacji
WebView
, aby zawsze wrócić do zabezpieczeń po napotkaniu znanego zdarzenia
zagrożenie:
Kotlin
private lateinit var superSafeWebView: WebView private var safeBrowsingIsInitialized: Boolean = false // ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) superSafeWebView = WebView(this) superSafeWebView.webViewClient = MyWebViewClient() safeBrowsingIsInitialized = false if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) { WebViewCompat.startSafeBrowsing(this, ValueCallback<Boolean> { success -> safeBrowsingIsInitialized = true if (!success) { Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!") } }) } }
Java
private WebView superSafeWebView; private boolean safeBrowsingIsInitialized; // ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); superSafeWebView = new WebView(this); superSafeWebView.setWebViewClient(new MyWebViewClient()); safeBrowsingIsInitialized = false; if (WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING)) { WebViewCompat.startSafeBrowsing(this, new ValueCallback<Boolean>() { @Override public void onReceiveValue(Boolean success) { safeBrowsingIsInitialized = true; if (!success) { Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!"); } } }); } }
Kotlin
class MyWebViewClient : WebViewClientCompat() { // Automatically go "back to safety" when attempting to load a website that // Google identifies as a known threat. An instance of WebView calls this // method only after Safe Browsing is initialized, so there's no conditional // logic needed here. override fun onSafeBrowsingHit( view: WebView, request: WebResourceRequest, threatType: Int, callback: SafeBrowsingResponseCompat ) { // The "true" argument indicates that your app reports incidents like // this one to Safe Browsing. if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) { callback.backToSafety(true) Toast.makeText(view.context, "Unsafe web page blocked.", Toast.LENGTH_LONG).show() } } }
Java
public class MyWebViewClient extends WebViewClientCompat { // Automatically go "back to safety" when attempting to load a website that // Google identifies as a known threat. An instance of WebView calls this // method only after Safe Browsing is initialized, so there's no conditional // logic needed here. @Override public void onSafeBrowsingHit(WebView view, WebResourceRequest request, int threatType, SafeBrowsingResponseCompat callback) { // The "true" argument indicates that your app reports incidents like // this one to Safe Browsing. if (WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY)) { callback.backToSafety(true); Toast.makeText(view.getContext(), "Unsafe web page blocked.", Toast.LENGTH_LONG).show(); } } }
Interfejs API geolokalizacji w HTML5
W przypadku aplikacji kierowanych na Androida 6.0 (poziom interfejsu API 23) i nowsze wersje interfejsu API geolokalizacji
jest obsługiwany tylko w przypadku bezpiecznych źródeł, takich jak HTTPS. Wszystkie prośby skierowane do
Interfejs API geolokalizacji w przypadku niezabezpieczonych źródeł jest automatycznie odrzucany bez wywoływania
odpowiednią metodę onGeolocationPermissionsShowPrompt()
.
Zrezygnuj ze zbierania danych
WebView
może przesyłać anonimowe dane diagnostyczne do
Google, gdy użytkownik wyrazi zgodę. Dane są zbierane w odniesieniu do poszczególnych aplikacji
dla każdej aplikacji, która tworzy instancję WebView
. Możesz zrezygnować z tej opcji.
przez utworzenie w pliku manifestu następującego tagu
Element <application>
:
<manifest> <application> ... <meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" /> </application> </manifest>
Dane są przesyłane z aplikacji tylko wtedy, gdy użytkownik wyrazi zgodę oraz nie rezygnuje. Więcej informacji o rezygnowaniu z danych diagnostycznych raportowania dowiesz się z artykułu Prywatność użytkowników w komponencie WebView .
Interfejs API obsługi wypowiedzenia
Interfejs Termination Handling API obsługuje przypadki, w których mechanizm renderowania
WebView
gdy obiekt znika, ponieważ system kończy działanie mechanizmu renderowania, by odzyskać
niezbędną pamięć lub z powodu błędu procesu renderowania. Korzystając z tego interfejsu API,
Pozwól aplikacji kontynuować wykonywanie, mimo że mechanizm renderowania przestanie działać.
Jeśli mechanizm renderowania ulegnie awarii podczas wczytywania konkretnej strony internetowej,
ponowne wczytanie tej samej strony może spowodować, że nowy obiekt WebView
występują w przypadku tego samego błędu renderowania.
Poniższy fragment kodu ilustruje, jak używać tego interfejsu API w tagu
Activity
:
Kotlin
inner class MyRendererTrackingWebViewClient : WebViewClient() { private var mWebView: WebView? = null override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean { if (!detail.didCrash()) { // Renderer is killed because the system ran out of memory. The app // can recover gracefully by creating a new WebView instance in the // foreground. Log.e("MY_APP_TAG", ("System killed the WebView rendering process " + "to reclaim memory. Recreating...")) mWebView?.also { webView -> val webViewContainer: ViewGroup = findViewById(R.id.my_web_view_container) webViewContainer.removeView(webView) webView.destroy() mWebView = null } // By this point, the instance variable "mWebView" is guaranteed to // be null, so it's safe to reinitialize it. return true // The app continues executing. } // Renderer crashes because of an internal error, such as a memory // access violation. Log.e("MY_APP_TAG", "The WebView rendering process crashed!") // In this example, the app itself crashes after detecting that the // renderer crashed. If you handle the crash more gracefully and let // your app continue executing, you must destroy the current WebView // instance, specify logic for how the app continues executing, and // return "true" instead. return false } }
Java
public class MyRendererTrackingWebViewClient extends WebViewClient { private WebView mWebView; @Override public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) { if (!detail.didCrash()) { // Renderer is killed because the system ran out of memory. The app // can recover gracefully by creating a new WebView instance in the // foreground. Log.e("MY_APP_TAG", "System killed the WebView rendering process " + "to reclaim memory. Recreating..."); if (mWebView != null) { ViewGroup webViewContainer = (ViewGroup) findViewById(R.id.my_web_view_container); webViewContainer.removeView(mWebView); mWebView.destroy(); mWebView = null; } // By this point, the instance variable "mWebView" is guaranteed to // be null, so it's safe to reinitialize it. return true; // The app continues executing. } // Renderer crashes because of an internal error, such as a memory // access violation. Log.e("MY_APP_TAG", "The WebView rendering process crashed!"); // In this example, the app itself crashes after detecting that the // renderer crashed. If you handle the crash more gracefully and let // your app continue executing, you must destroy the current WebView // instance, specify logic for how the app continues executing, and // return "true" instead. return false; } }
Interfejs Renderer Importance API
Gdy obiekty WebView
działa w
w trybie wielu procesów, możesz
elastycznie reagować
typu „za mało pamięci”. Korzystając z interfejsu Renderer Importance API, omówionego w artykule
Android 8.0, aby ustawić zasadę priorytetu dla mechanizmu renderowania przypisanego do
WebView
obiekt. Szczególnie przydałaby się najważniejsza część
aby kontynuować wykonywanie, gdy mechanizm renderowania wyświetla
WebView
obiektu zostało zakończone. Możesz to zrobić na przykład, jeśli
obiekt WebView
nie będzie przez dłuższy czas wyświetlany, więc
system może odzyskać pamięć używaną przez mechanizm renderowania.
Fragment kodu poniżej pokazuje, jak przypisać priorytet do mechanizmu renderowania
proces powiązany z obiektami WebView
Twojej aplikacji:
Kotlin
val myWebView: WebView = ... myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)
Java
WebView myWebView; myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);
W tym fragmencie kodu priorytet mechanizmu renderowania jest taki sam jak – lub
– jest to domyślny priorytet aplikacji. true
zmniejsza priorytet mechanizmu renderowania do
RENDERER_PRIORITY_WAIVED
gdy powiązany obiekt WebView
nie jest już widoczny. W innym
słów, argument true
wskazuje, że aplikacja nie dba o to, czy
system utrzymuje
proces renderowania. Ten niższy priorytet
może doprowadzić do zakończenia procesu renderowania z „brakiem pamięci”
w różnych sytuacjach.
Aby dowiedzieć się więcej o tym, jak system postępuje w sytuacjach, gdy brakuje pamięci, zobacz Procesy i aplikacja cyklu życia usługi.