वेबव्यू ऑब्जेक्ट मैनेज करें

Android, कई एपीआई उपलब्ध कराता है. इनकी मदद से, आपके ऐप्लिकेशन में वेब कॉन्टेंट दिखाने वाले WebView ऑब्जेक्ट मैनेज किए जा सकते हैं.

इस पेज पर, इन एपीआई का इस्तेमाल करके, WebView ऑब्जेक्ट को ज़्यादा असरदार तरीके से मैनेज करने का तरीका बताया गया है. इससे, आपके ऐप्लिकेशन की परफ़ॉर्मेंस और सुरक्षा बेहतर होती है.

वर्शन एपीआई

Android 7.0 (एपीआई लेवल 24) से, उपयोगकर्ता WebView ऑब्जेक्ट में वेब कॉन्टेंट दिखाने के लिए, अलग-अलग पैकेज चुन सकते हैं. Jetpack Webkit लाइब्रेरी में, getCurrentWebViewPackage() तरीका शामिल है. इसकी मदद से, आपके ऐप्लिकेशन में वेब कॉन्टेंट दिखाने वाले पैकेज से जुड़ी जानकारी फ़ेच की जा सकती है. यह तरीका, उन गड़बड़ियों का विश्लेषण करने में मददगार होता है जो सिर्फ़ तब होती हैं, जब आपका ऐप्लिकेशन, WebView के किसी खास पैकेज के लागू करने के तरीके का इस्तेमाल करके वेब कॉन्टेंट दिखाता है.

इस तरीके का इस्तेमाल करने के लिए, यहां दिए गए कोड स्निपेट में दिखाया गया लॉजिक जोड़ें:

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 सुरक्षित ब्राउज़िंग सेवा

आपके उपयोगकर्ताओं को सुरक्षित ब्राउज़िंग अनुभव देने के लिए, WebView ऑब्जेक्ट, Google सुरक्षित ब्राउज़िंग का इस्तेमाल करके यूआरएल की पुष्टि करते हैं. इससे, आपके ऐप्लिकेशन में उपयोगकर्ताओं को चेतावनी दिखाई जा सकती है. यह चेतावनी तब दिखती है, जब वे किसी ऐसी वेबसाइट पर जाने की कोशिश करते हैं जो सुरक्षित नहीं है.

EnableSafeBrowsing की डिफ़ॉल्ट वैल्यू 'सही' होती है. हालांकि, कुछ मामलों में आपको सुरक्षित ब्राउज़िंग की सुविधा, सिर्फ़ कुछ शर्तों के साथ चालू करनी पड़ सकती है या इसे बंद करना पड़ सकता है. Android 8.0 (एपीआई लेवल 26) और इसके बाद के वर्शन में, setSafeBrowsingEnabled() का इस्तेमाल करके, किसी एक WebView ऑब्जेक्ट के लिए सुरक्षित ब्राउज़िंग की सुविधा को टॉगल किया जा सकता है.

अगर आपको सभी WebView ऑब्जेक्ट के लिए, सुरक्षित ब्राउज़िंग की जांच से ऑप्ट आउट करना है, तो अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में, यह <meta-data> एलिमेंट जोड़ें:

<manifest>
    <application>
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="false" />
        ...
    </application>
</manifest>

प्रोग्राम के ज़रिए कार्रवाइयां तय करना

जब WebView का कोई इंस्टेंस, किसी ऐसे पेज को लोड करने की कोशिश करता है जिसे Google ने खतरे के तौर पर क्लासिफ़ाई किया है, तो WebView डिफ़ॉल्ट रूप से एक इंटरस्टीशियल दिखाता है. इसमें उपयोगकर्ताओं को खतरे के बारे में चेतावनी दी जाती है. इस स्क्रीन पर, उपयोगकर्ताओं के पास यह विकल्प होता है कि वे यूआरएल को लोड करें या किसी सुरक्षित पिछले पेज पर वापस जाएं.

अगर आपका ऐप्लिकेशन, Android 8.1 (एपीआई लेवल 27) या इसके बाद के वर्शन को टारगेट करता है, तो प्रोग्राम के ज़रिए यह तय किया जा सकता है कि आपका ऐप्लिकेशन, खतरे के तौर पर क्लासिफ़ाई किए गए यूआरएल पर किस तरह से काम करे. इसके लिए, ये तरीके अपनाए जा सकते हैं:

  • यह कंट्रोल किया जा सकता है कि आपका ऐप्लिकेशन, खतरे के तौर पर क्लासिफ़ाई किए गए यूआरएल की जानकारी, सुरक्षित ब्राउज़िंग को रिपोर्ट करे या नहीं.
  • आपका ऐप्लिकेशन, खतरे के तौर पर क्लासिफ़ाई किए गए हर यूआरएल पर, कोई खास कार्रवाई अपने-आप कर सकता है. जैसे, सुरक्षित पेज पर वापस जाना.

यहां दिए गए कोड स्निपेट में बताया गया है कि WebView के इंस्टेंस को यह निर्देश कैसे दिया जाए कि खतरे के तौर पर क्लासिफ़ाई किए गए यूआरएल पर जाने के बाद, वे हमेशा सुरक्षित पेज पर वापस जाएं:

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 जियोलोकेशन एपीआई

Android 6.0 (एपीआई लेवल 23) और इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, जियोलोकेशन एपीआई सिर्फ़ सुरक्षित ऑरिजिन पर काम करता है. जैसे, HTTPS. गैर-सुरक्षित ऑरिजिन पर, जियोलोकेशन एपीआई के लिए किए गए किसी भी अनुरोध को, उससे जुड़े onGeolocationPermissionsShowPrompt() तरीके को लागू किए बिना ही, अपने-आप अस्वीकार कर दिया जाता है.

मेट्रिक कलेक्शन से ऑप्ट आउट करना

WebView के पास, Google पर अनाम तौर पर डाइग्नोस्टिक डेटा अपलोड करने की सुविधा होती है. हालांकि, यह सुविधा सिर्फ़ तब काम करती है, जब उपयोगकर्ता अपनी सहमति देता है. डेटा, हर ऐप्लिकेशन के हिसाब से इकट्ठा किया जाता है. यह डेटा, WebView को इंस्टैंशिएट करने वाले हर ऐप्लिकेशन के लिए इकट्ठा किया जाता है. इस सुविधा से ऑप्ट आउट करने के लिए, मेनिफ़ेस्ट के <application> एलिमेंट में यह टैग बनाएं:

<manifest>
    <application>
    ...
    <meta-data android:name="android.webkit.WebView.MetricsOptOut"
               android:value="true" />
    </application>
</manifest>

किसी ऐप्लिकेशन से डेटा सिर्फ़ तब अपलोड किया जाता है, जब उपयोगकर्ता सहमति देता है और ऐप्लिकेशन ऑप्ट आउट नहीं करता. डाइग्नोस्टिक डेटा की रिपोर्टिंग से ऑप्ट आउट करने के बारे में ज़्यादा जानने के लिए, WebView की रिपोर्टिंग में उपयोगकर्ता की निजता देखें.

टर्मिनेशन हैंडलिंग एपीआई

टर्मिनेशन हैंडलिंग एपीआई, उन मामलों को मैनेज करता है जिनमें WebView ऑब्जेक्ट के लिए रेंडरर प्रोसेस बंद हो जाती है. ऐसा तब होता है, जब सिस्टम ज़रूरी मेमोरी वापस पाने के लिए रेंडरर को बंद कर देता है या रेंडरर प्रोसेस क्रैश हो जाती है. इस एपीआई का इस्तेमाल करके, आपका ऐप्लिकेशन काम करना जारी रख सकता है. भले ही, रेंडरर प्रोसेस बंद हो गई हो.

अगर किसी वेब पेज को लोड करते समय रेंडरर क्रैश हो जाता है, तो उसी पेज को फिर से लोड करने की कोशिश करने पर, नया WebView ऑब्जेक्ट भी उसी तरह से रेंडरिंग क्रैश का सामना कर सकता है.

यहां दिए गए कोड स्निपेट में बताया गया है कि किसी 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;
    }
}

रेंडरर इंपोर्टेंस एपीआई

जब WebView ऑब्जेक्ट मल्टीप्रोसेस मोड में काम करते हैं, तो आपके पास यह तय करने की सुविधा होती है कि आपका ऐप्लिकेशन, मेमोरी खत्म होने की स्थितियों को कैसे मैनेज करे. Android 8.0 में पेश किए गए रेंडरर इंपोर्टेंस एपीआई का इस्तेमाल करके, किसी खास WebView ऑब्जेक्ट को असाइन किए गए रेंडरर के लिए, प्राथमिकता की नीति सेट की जा सकती है. खास तौर पर, हो सकता है कि आप चाहें कि आपके ऐप्लिकेशन का मुख्य हिस्सा काम करना जारी रखे. भले ही, आपके ऐप्लिकेशन के WebView ऑब्जेक्ट दिखाने वाला रेंडरर बंद हो जाए. उदाहरण के लिए, ऐसा तब किया जा सकता है, जब आपको WebView ऑब्जेक्ट को लंबे समय तक नहीं दिखाना हो. इससे, सिस्टम उस मेमोरी को वापस पा सकता है जिसका इस्तेमाल रेंडरर कर रहा था.

यहां दिए गए कोड स्निपेट में बताया गया है कि आपके ऐप्लिकेशन के WebView ऑब्जेक्ट से जुड़ी रेंडरर प्रोसेस को प्राथमिकता कैसे असाइन की जाती है:

Kotlin

val myWebView: WebView = ...
myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true)

Java

WebView myWebView;
myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);

इस स्निपेट में, रेंडरर की प्राथमिकता, ऐप्लिकेशन की डिफ़ॉल्ट प्राथमिकता के बराबर होती है या उससे जुड़ी होती है. जब उससे जुड़ा WebView ऑब्जेक्ट नहीं दिखता है, तो true आर्ग्युमेंट, रेंडरर की प्राथमिकता को RENDERER_PRIORITY_WAIVED पर ले जाता है. दूसरे शब्दों में, true आर्ग्युमेंट से पता चलता है कि आपके ऐप्लिकेशन को इस बात से कोई फ़र्क़ नहीं पड़ता कि सिस्टम, रेंडरर प्रोसेस को चालू रखता है या नहीं. दरअसल, प्राथमिकता का यह निचला लेवल, मेमोरी खत्म होने की स्थितियों में रेंडरर प्रोसेस को बंद कर सकता है.

वेब कॉन्टेंट का इस्तेमाल करते समय, अपने ऐप्लिकेशन की मेमोरी फ़ुटप्रिंट की जांच करने और उसे ऑप्टिमाइज़ करने के बारे में ज़्यादा जानने के लिए, WebView की मेमोरी मैनेज करना और उसकी जांच करना देखें. प्रोसेस के दौरान, मेमोरी कम होने की स्थितियों को सिस्टम कैसे मैनेज करता है, इसके बारे में ज़्यादा जानने के लिए, प्रोसेस और ऐप्लिकेशन का लाइफ़साइकल देखें.

स्टेट और नेविगेशन इतिहास को सुरक्षित रखना

जब सिस्टम, बैकग्राउंड में चल रहे संसाधनों को वापस पाता है या डिवाइस के कॉन्फ़िगरेशन में बदलाव होता है, तो ऐप्लिकेशन की गतिविधि और उसके WebView ऑब्जेक्ट खत्म हो सकते हैं. उपयोगकर्ता के नेविगेशन कॉन्टेक्स्ट को सुरक्षित रखने के लिए, saveState(Bundle) तरीके का इस्तेमाल करें. इससे, नेविगेशन इतिहास को Bundle में क्रम से लगाया जाता है. इसके बाद, इसे restoreState(Bundle) का इस्तेमाल करके वापस लाया जाता है.onSaveInstanceState()

Android, savedInstanceState के लिए पूरी प्रोसेस में 1 एमबी की सीमा लागू करता है. इसलिए, स्टैंडर्ड फ़्रेमवर्क एपीआई की मदद से, बड़े ब्राउज़िंग सेशन को क्रम से लगाने पर, TransactionTooLargeException हो सकता है. साइज़ की सीमाएं लागू करने या फ़ॉरवर्ड इतिहास की एंट्री को सुरक्षित तरीके से हटाने के लिए, Jetpack Webkit के WebViewCompat.saveState() तरीके का इस्तेमाल करें.

स्टेट को असरदार तरीके से मैनेज करने की रणनीतियों और सबसे सही तरीकों के बारे में ज़्यादा जानने के लिए, WebView के स्टेट को असरदार तरीके से मैनेज करना देखें.