WebView অবজেক্ট পরিচালনা করুন

আপনার অ্যাপে ওয়েব কন্টেন্ট প্রদর্শনকারী WebView অবজেক্টগুলো পরিচালনা করতে সাহায্য করার জন্য অ্যান্ড্রয়েড বেশ কিছু এপিআই প্রদান করে।

এই পৃষ্ঠায় বর্ণনা করা হয়েছে কীভাবে এই API-গুলো ব্যবহার করে WebView অবজেক্টগুলোর সাথে আরও কার্যকরভাবে কাজ করা যায়, যা আপনার অ্যাপের স্থিতিশীলতা এবং নিরাপত্তা উন্নত করবে।

সংস্করণ এপিআই

অ্যান্ড্রয়েড ৭.০ (এপিআই লেভেল ২৪) থেকে, ব্যবহারকারীরা একটি WebView অবজেক্টে ওয়েব কন্টেন্ট প্রদর্শনের জন্য বিভিন্ন প্যাকেজের মধ্যে থেকে বেছে নিতে পারেন। Jetpack Webkit লাইব্রেরিতে getCurrentWebViewPackage() মেথডটি রয়েছে, যা আপনার অ্যাপে ওয়েব কন্টেন্ট প্রদর্শনকারী প্যাকেজ সম্পর্কিত তথ্য সংগ্রহ করে। এই মেথডটি সেইসব ত্রুটি বিশ্লেষণ করার জন্য উপযোগী, যা শুধুমাত্র তখনই ঘটে যখন আপনার অ্যাপ কোনো নির্দিষ্ট প্যাকেজের WebView ইমপ্লিমেন্টেশন ব্যবহার করে ওয়েব কন্টেন্ট প্রদর্শন করার চেষ্টা করে।

এই পদ্ধতিটি ব্যবহার করতে, নিম্নলিখিত কোড স্নিপেটে দেখানো লজিকটি যোগ করুন:

কোটলিন

val webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext)
Log.d("MY_APP_TAG", "WebView version: ${webViewPackageInfo.versionName}")

জাভা

PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(appContext);
Log.d("MY_APP_TAG", "WebView version: " + webViewPackageInfo.versionName);

গুগল নিরাপদ ব্রাউজিং পরিষেবা

আপনার ব্যবহারকারীদের একটি নিরাপদ ব্রাউজিং অভিজ্ঞতা প্রদান করতে, WebView অবজেক্টগুলো Google Safe Browsing ব্যবহার করে URL যাচাই করে, যার ফলে ব্যবহারকারীরা কোনো সম্ভাব্য অনিরাপদ ওয়েবসাইটে যাওয়ার চেষ্টা করলে আপনার অ্যাপকে একটি সতর্কবার্তা দেখানো যায়।

যদিও EnableSafeBrowsing এর ডিফল্ট মান true, এমন কিছু পরিস্থিতি আসতে পারে যখন আপনি শর্তসাপেক্ষে সেফ ব্রাউজিং চালু বা বন্ধ করতে চাইতে পারেন। Android 8.0 (API লেভেল 26) এবং এর পরবর্তী সংস্করণগুলো একটি স্বতন্ত্র WebView অবজেক্টের জন্য সেফ ব্রাউজিং টগল করতে setSafeBrowsingEnabled() ব্যবহার সমর্থন করে।

আপনি যদি চান সমস্ত WebView অবজেক্ট সেফ ব্রাউজিং চেক থেকে অব্যাহতি পাক, তাহলে আপনার অ্যাপের ম্যানিফেস্ট ফাইলে নিম্নলিখিত <meta-data> এলিমেন্টটি যোগ করুন:

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

প্রোগ্রাম্যাটিক কার্যক্রম সংজ্ঞায়িত করুন

যখন WebView এর কোনো ইনস্ট্যান্স গুগল কর্তৃক পরিচিত হুমকি হিসেবে শ্রেণীবদ্ধ কোনো পৃষ্ঠা লোড করার চেষ্টা করে, তখন WebView ডিফল্টরূপে একটি ইন্টারস্টিশিয়াল প্রদর্শন করে যা ব্যবহারকারীদের সেই পরিচিত হুমকি সম্পর্কে সতর্ক করে। এই স্ক্রিনটি ব্যবহারকারীদেরকে ইউআরএলটি লোড করার অথবা পূর্ববর্তী কোনো নিরাপদ পৃষ্ঠায় ফিরে যাওয়ার বিকল্প দেয়।

আপনি যদি অ্যান্ড্রয়েড ৮.১ (এপিআই লেভেল ২৭) বা তার পরবর্তী সংস্করণকে টার্গেট করেন, তাহলে কোনো পরিচিত হুমকির ক্ষেত্রে আপনার অ্যাপ কীভাবে প্রতিক্রিয়া জানাবে, তা নিম্নলিখিত উপায়ে প্রোগ্রাম্যাটিকভাবে নির্ধারণ করতে পারেন:

  • আপনার অ্যাপ সেফ ব্রাউজিং-কে পরিচিত হুমকি সম্পর্কে জানাবে কিনা, তা আপনি নিয়ন্ত্রণ করতে পারেন।
  • আপনার অ্যাপকে এমনভাবে তৈরি করা যায় যাতে এটি পরিচিত হুমকি হিসেবে চিহ্নিত কোনো URL-এর সম্মুখীন হলেই স্বয়ংক্রিয়ভাবে একটি নির্দিষ্ট কাজ—যেমন নিরাপদ অবস্থায় ফিরে যাওয়া—করে।

নিম্নলিখিত কোড স্নিপেটগুলো দেখায় কিভাবে আপনার অ্যাপের WebView ইনস্ট্যান্সগুলোকে কোনো পরিচিত হুমকির সম্মুখীন হওয়ার পর সর্বদা সুরক্ষাব্যবস্থায় ফিরে যাওয়ার নির্দেশ দিতে হয়:

MyWebActivity.java

কোটলিন

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!")
            }
        })
    }
}

জাভা

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

কোটলিন

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

জাভা

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

এইচটিএমএল৫ ভূ-অবস্থান এপিআই

অ্যান্ড্রয়েড ৬.০ (এপিআই লেভেল ২৩) এবং তার পরবর্তী সংস্করণকে লক্ষ্য করে তৈরি অ্যাপগুলির জন্য, জিওলোকেশন এপিআই শুধুমাত্র 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 মধ্যে এই API ব্যবহার করতে হয়:

কোটলিন

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

জাভা

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-তে প্রবর্তিত Renderer Importance API ব্যবহার করে একটি নির্দিষ্ট WebView অবজেক্টের জন্য নির্ধারিত রেন্ডারারের অগ্রাধিকার নীতি নির্ধারণ করতে পারেন। বিশেষ করে, আপনি চাইতে পারেন যে আপনার অ্যাপের WebView অবজেক্টগুলো প্রদর্শনকারী কোনো রেন্ডারার বন্ধ হয়ে গেলেও আপনার অ্যাপের মূল অংশটি যেন চলতে থাকে। উদাহরণস্বরূপ, আপনি এমনটা করতে পারেন যদি আপনি আশা করেন যে WebView অবজেক্টটি দীর্ঘ সময়ের জন্য দেখানো হবে না, যাতে সিস্টেম রেন্ডারার দ্বারা ব্যবহৃত মেমোরি পুনরুদ্ধার করতে পারে।

নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে আপনার অ্যাপের WebView অবজেক্টগুলির সাথে যুক্ত রেন্ডারার প্রসেসকে একটি অগ্রাধিকার নির্ধারণ করতে হয়:

কোটলিন

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

জাভা

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

এই নির্দিষ্ট কোড অংশে, রেন্ডারারের প্রায়োরিটি অ্যাপের ডিফল্ট প্রায়োরিটির সমান—অথবা এর সাথে আবদ্ধ। যখন সংশ্লিষ্ট WebView অবজেক্টটি আর দৃশ্যমান থাকে না, তখন ' true আর্গুমেন্টটি রেন্ডারারের প্রায়োরিটি কমিয়ে RENDERER_PRIORITY_WAIVED করে দেয়। অন্য কথায়, একটি true আর্গুমেন্ট নির্দেশ করে যে, সিস্টেম রেন্ডারার প্রসেসটিকে চালু রাখবে কি না, তা নিয়ে আপনার অ্যাপের কোনো মাথাব্যথা নেই। প্রকৃতপক্ষে, এই নিম্ন প্রায়োরিটি লেভেলের কারণে মেমোরি শেষ হয়ে যাওয়ার পরিস্থিতিতে রেন্ডারার প্রসেসটি বন্ধ হয়ে যাওয়ার সম্ভাবনাই বেশি থাকে।

সিস্টেম কীভাবে স্বল্প-মেমরি পরিস্থিতি সামাল দেয় সে সম্পর্কে আরও জানতে, প্রসেস এবং অ্যাপ লাইফসাইকেল দেখুন।