Android, uygulamanızda web içeriğini gösteren
WebViewnesneleri yönetmenize yardımcı olacak çeşitli API'ler sunar.
Bu sayfada, WebView
nesneleriyle daha etkili bir şekilde çalışmak için bu API'lerin nasıl kullanılacağı açıklanmaktadır. Bu sayede uygulamanızın kararlılığı ve güvenliği artırılır.
Version API
Android 7.0'dan (API düzeyi 24) itibaren kullanıcılar, web içeriğini bir WebView nesnesinde görüntülemek için çeşitli paketler arasından seçim yapabilir. Jetpack Webkit kitaplığı, uygulamanızda web içeriğini görüntüleyen paketle ilgili bilgileri getirmek için getCurrentWebViewPackage() yöntemini içerir. Bu yöntem, yalnızca uygulamanız belirli bir paketin WebView uygulaması kullanılarak web içeriğini görüntülemeye çalıştığında oluşan hataları analiz ederken faydalıdır.
Bu yöntemi kullanmak için aşağıdaki kod snippet'inde gösterilen mantığı ekleyin:
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);
Google Güvenli Tarama Hizmeti
Kullanıcılarınıza daha güvenli bir tarama deneyimi sunmak için WebView
nesneler, URL'leri Google Güvenli Tarama'yı kullanarak doğrular.
Bu sayede uygulamanız, kullanıcılar potansiyel olarak güvenli olmayan bir web sitesine gitmeye çalıştığında onlara uyarı gösterebilir.
EnableSafeBrowsing'nın varsayılan değeri doğru olsa da Güvenli Tarama'yı yalnızca koşullu olarak etkinleştirmek veya devre dışı bırakmak isteyebileceğiniz durumlar olabilir. Android 8.0 (API düzeyi 26) ve sonraki sürümlerde, tek bir WebView nesnesi için Güvenli Tarama'yı etkinleştirmek veya devre dışı bırakmak üzere setSafeBrowsingEnabled() kullanılabilir.
Tüm WebView nesnelerinin Güvenli Tarama kontrollerini devre dışı bırakmasını istiyorsanız uygulamanızın manifest dosyasına aşağıdaki <meta-data> öğesini ekleyin:
<manifest> <application> <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="false" /> ... </application> </manifest>
Programatik işlemleri tanımlama
WebView örneği, Google tarafından bilinen bir tehdit olarak sınıflandırılan bir sayfayı yüklemeye çalıştığında WebView, varsayılan olarak kullanıcılara bilinen tehdit hakkında uyarı veren bir ara sayfa gösterir. Bu ekran, kullanıcılara URL'yi yine de yükleme veya güvenli olan önceki bir sayfaya dönme seçeneği sunar.
Android 8.1'i (API düzeyi 27) veya sonraki sürümleri hedefliyorsanız uygulamanızın bilinen bir tehdide nasıl yanıt vereceğini aşağıdaki şekillerde programatik olarak tanımlayabilirsiniz:
- Uygulamanızın bilinen tehditleri Güvenli Tarama'ya bildirip bildirmeyeceğini kontrol edebilirsiniz.
- Uygulamanızın, bilinen tehdit olarak sınıflandırılan bir URL ile her karşılaştığında belirli bir işlemi (ör. güvenliğe geri dönme) otomatik olarak yapmasını sağlayabilirsiniz.
Aşağıdaki kod snippet'lerinde, bilinen bir tehditle karşılaştıktan sonra uygulamanızın WebView örneklerine her zaman güvenliğe geri dönme talimatının nasıl verileceği gösterilmektedir:
MyWebActivity.java
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!"); } } }); } }
MyWebViewClient.java
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(); } } }
HTML5 Geolocation API
Android 6.0 (API düzeyi 23) ve sonraki sürümleri hedefleyen uygulamalarda Geolocation API yalnızca HTTPS gibi güvenli kaynaklarda desteklenir. Güvenli olmayan kaynaklarda Geolocation API'ye yapılan tüm istekler, ilgili onGeolocationPermissionsShowPrompt() yöntemi çağrılmadan otomatik olarak reddedilir.
Metrik toplamayı devre dışı bırakma
WebView, kullanıcı izni verdiğinde Google'a anonim teşhis verileri yükleyebilir. Veriler, WebView örneği oluşturan her uygulama için uygulama bazında toplanır. Manifest dosyasının <application> öğesinde aşağıdaki etiketi oluşturarak bu özelliği devre dışı bırakabilirsiniz:
<manifest> <application> ... <meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" /> </application> </manifest>
Veriler yalnızca kullanıcı izin verirse ve uygulama kapsam dışında kalmayı tercih etmezse uygulamadan yüklenir. Teşhis verileri raporlamayı devre dışı bırakma hakkında daha fazla bilgi için WebView raporlamasında kullanıcı gizliliği başlıklı makaleyi inceleyin.
Termination Handling API
Termination Handling API, bir WebView
nesnesinin oluşturma işlemi, sistemin gerekli belleği geri kazanmak için oluşturma işlemini sonlandırması veya oluşturma işleminin kilitlenmesi nedeniyle ortadan kalktığında bu durumu ele alır. Bu API'yi kullanarak, oluşturma işlemi ortadan kalksa bile uygulamanızın yürütülmeye devam etmesini sağlayabilirsiniz.
Belirli bir web sayfası yüklenirken bir oluşturucu kilitlenirse aynı sayfayı tekrar yüklemeye çalışmak yeni bir WebView nesnesinin aynı oluşturma kilitlenme davranışını sergilemesine neden olabilir.
Aşağıdaki kod snippet'i, bu API'nin Activity içinde nasıl kullanılacağını gösterir:
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; } }
Renderer Importance API
WebView nesneleri çoklu işlem modunda çalışırken uygulamanızın bellek yetersizliği durumlarını nasıl işlediği konusunda biraz esnekliğe sahip olursunuz. Android 8.0'da kullanıma sunulan Oluşturucu Önem Derecesi API'sini kullanarak belirli bir WebView nesnesine atanan oluşturucu için bir öncelik politikası belirleyebilirsiniz. Özellikle, uygulamanızın WebView nesnelerini görüntüleyen bir oluşturucu sonlandırıldığında uygulamanızın ana bölümünün yürütülmeye devam etmesini isteyebilirsiniz. Örneğin, WebView nesnesini uzun süre göstermeyeceğinizi düşünüyorsanız bu işlemi yapabilirsiniz. Böylece sistem, oluşturucunun kullandığı belleği geri alabilir.
Aşağıdaki kod snippet'inde, uygulamanızın WebView nesneleriyle ilişkili oluşturucu işlemine nasıl öncelik atanacağı gösterilmektedir:
Kotlin
val myWebView: WebView = ... myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)
Java
WebView myWebView; myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);
Bu snippet'te, oluşturucunun önceliği uygulamanın varsayılan önceliğiyle aynıdır veya bu önceliğe bağlıdır. true bağımsız değişkeni, ilişkili WebView nesnesi artık görünür olmadığında oluşturucunun önceliğini RENDERER_PRIORITY_WAIVED olarak düşürür. Diğer bir deyişle, true bağımsız değişkeni, uygulamanızın sistemin oluşturma işlemini canlı tutmasıyla ilgilenmediğini gösterir. Hatta bu düşük öncelik düzeyi, oluşturucu sürecinin bellek yetersizliği durumlarında sonlandırılma olasılığını artırır.
Sistemin düşük bellek durumlarını nasıl ele aldığı hakkında daha fazla bilgi edinmek için İşlemler ve uygulama yaşam döngüsü başlıklı makaleyi inceleyin.