Android 11 पर कस्टम टैब इस्तेमाल करना

Android 11 में कुछ ऐसे बदलाव किए गए हैं जिनमें बताया गया है कि ऐप्लिकेशन, उपयोगकर्ता के डिवाइस पर इंस्टॉल किए गए अन्य ऐप्लिकेशन से कैसे इंटरैक्ट कर सकते हैं. इन बदलावों के बारे में ज़्यादा जानने के लिए, Android से जुड़े दस्तावेज़ पढ़ें.

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

सबसे आसान मामले में, कस्टम टैब को एक लाइन में लॉन्च किया जा सकता है, जैसे कि:

new CustomTabsIntent.Builder().build()
        .launchUrl(this, Uri.parse("https://www.example.com"));

इस तरीके का इस्तेमाल करके ऐप्लिकेशन लॉन्च करने या यूज़र इंटरफ़ेस (यूआई) कस्टमाइज़ेशन जैसे टूलबार का रंग बदलना, ऐक्शन बटन जोड़ना जैसे ऐप्लिकेशन को ऐप्लिकेशन में कोई भी बदलाव करने की ज़रूरत नहीं होती.

निजी ऐप्लिकेशन को प्राथमिकता देना

हालांकि, अगर आपने सबसे सही तरीके अपनाए हैं, तो आपको कुछ बदलाव करने पड़ सकते हैं.

पहला सबसे सही तरीका यह है कि अगर ऐप्लिकेशन को इंस्टॉल करने की क्षमता वाला कोई ऐप्लिकेशन इंस्टॉल किया गया है, तो कस्टम टैब के बजाय, ऐप्लिकेशन को इंटेंट हैंडल करने के लिए किसी नेटिव ऐप्लिकेशन को प्राथमिकता देनी चाहिए.

Android 11 और इसके बाद के वर्शन वाले डिवाइसों पर

Android 11 में एक नया इंटेंट फ़्लैग, FLAG_ACTIVITY_REQUIRE_NON_BROWSER लाया गया है. इस तरीके का इस्तेमाल करके, कोई नेटिव ऐप्लिकेशन खोलने का सुझाव दिया जाता है. ऐसा इसलिए, क्योंकि इसके लिए ऐप्लिकेशन को किसी पैकेज मैनेजर क्वेरी के बारे में जानकारी देने की ज़रूरत नहीं होती.

static boolean launchNativeApi30(Context context, Uri uri) {
    Intent nativeAppIntent = new Intent(Intent.ACTION_VIEW, uri)
            .addCategory(Intent.CATEGORY_BROWSABLE)
            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                    Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER);
    try {
        context.startActivity(nativeAppIntent);
        return true;
    } catch (ActivityNotFoundException ex) {
        return false;
    }
}

इस समस्या को हल करने के लिए, इंटेंट को लॉन्च करें. साथ ही, FLAG_ACTIVITY_REQUIRE_NON_BROWSER का इस्तेमाल करके, Android को लॉन्च करते समय ब्राउज़र से बचने के लिए कहें.

अगर कोई ऐसा नेटिव ऐप्लिकेशन नहीं मिलता है जो इस इंटेंट को मैनेज कर सकता है, तो ActivityNotFoundException को इस्तेमाल किया जाएगा.

Android 11 से पहले के वर्शन

ऐप्लिकेशन, Android 11 या एपीआई लेवल 30 को टारगेट कर सकता है, लेकिन Android के पिछले वर्शन FLAG_ACTIVITY_REQUIRE_NON_BROWSER फ़्लैग को समझ नहीं पाएंगे. इसलिए, हमें इन मामलों में पैकेज मैनेजर से क्वेरी करने की ज़रूरत होगी:

private static boolean launchNativeBeforeApi30(Context context, Uri uri) {
    PackageManager pm = context.getPackageManager();

    // Get all Apps that resolve a generic url
    Intent browserActivityIntent = new Intent()
            .setAction(Intent.ACTION_VIEW)
            .addCategory(Intent.CATEGORY_BROWSABLE)
            .setData(Uri.fromParts("http", "", null));
    Set<String> genericResolvedList = extractPackageNames(
            pm.queryIntentActivities(browserActivityIntent, 0));

    // Get all apps that resolve the specific Url
    Intent specializedActivityIntent = new Intent(Intent.ACTION_VIEW, uri)
            .addCategory(Intent.CATEGORY_BROWSABLE);
    Set<String> resolvedSpecializedList = extractPackageNames(
            pm.queryIntentActivities(specializedActivityIntent, 0));

    // Keep only the Urls that resolve the specific, but not the generic
    // urls.
    resolvedSpecializedList.removeAll(genericResolvedList);

    // If the list is empty, no native app handlers were found.
    if (resolvedSpecializedList.isEmpty()) {
        return false;
    }

    // We found native handlers. Launch the Intent.
    specializedActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(specializedActivityIntent);
    return true;
}

यहां इस्तेमाल किया गया तरीका, पैकेज मैनेजर से उन ऐप्लिकेशन के लिए क्वेरी करना है जो सामान्य http इंटेंट के साथ काम करते हैं. ये ऐप्लिकेशन ब्राउज़र हो सकते हैं.

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

अब, पहली सूची में मिलने वाले सभी ब्राउज़र को दूसरी सूची से हटा दें, और हमें सिर्फ़ खास ऐप्लिकेशन ही मिलेंगे.

अगर सूची खाली है, तो हम जानते हैं कि कोई नेटिव हैंडलर नहीं है और यह 'गलत' दिखाता है. ऐसा न होने पर, हम नेटिव हैंडलर के लिए इंटेंट लॉन्च कर देते हैं.

यह रही पूरी जानकारी

हमें यह पक्का करना होगा कि हर मौके के लिए, सही तरीका इस्तेमाल किया जाए:

static void launchUri(Context context, Uri uri) {
    boolean launched = Build.VERSION.SDK_INT >= 30 ?
            launchNativeApi30(context, uri) :
            launchNativeBeforeApi30(context, uri);

    if (!launched) {
        new CustomTabsIntent.Builder()
                .build()
                .launchUrl(context, uri);
    }
}

Build.VERSION.SDK_INT वह जानकारी उपलब्ध कराता है जिसकी हमें ज़रूरत है. अगर यह 30 के बराबर या उससे बड़ा है, तो Android को FLAG_ACTIVITY_REQUIRE_NON_BROWSER के बारे में पता है. इसलिए, हम इस नए तरीके में nativa ऐप्लिकेशन लॉन्च करने की कोशिश कर सकते हैं. अगर ऐसा नहीं है, तो हम पुराने तरीके से कैंपेन लॉन्च करने की कोशिश करते हैं.

अगर खास ऐप्लिकेशन लॉन्च नहीं हो पाता है, तो हम कस्टम टैब लॉन्च कर देते हैं.

इस सबसे सही तरीके में कुछ बॉयलरप्लेट शामिल हैं. हम लाइब्रेरी में जटिलता को इकट्ठा करके इसे आसान बनाने पर काम कर रहे हैं. android-Browser-helper सहायता लाइब्रेरी के अपडेट पाने के लिए, हमारे साथ बने रहें.

ऐसे ब्राउज़र का पता लगाना जो कस्टम टैब के साथ काम करते हैं

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

एपीआई लेवल 30 को टारगेट करते समय, डेवलपर को अपने Android मेनिफ़ेस्ट में क्वेरी सेक्शन जोड़ना होगा. इसमें कस्टम टैब की सुविधा वाले ब्राउज़र से मेल खाने वाले इंटेंट-फ़िल्टर का एलान करना होगा.

<queries>
    <intent>
        <action android:name=
            "android.support.customtabs.action.CustomTabsService" />
    </intent>
</queries>

मार्कअप तय होने के बाद, कस्टम टैब के साथ काम करने वाले ब्राउज़र के लिए क्वेरी करने के लिए इस्तेमाल किया जाने वाला मौजूदा कोड उम्मीद के मुताबिक काम करेगा.

अक्सर पूछे जाने वाले सवाल

सवाल: एक कोड जो उन ऐप्लिकेशन के लिए कस्टम टैब की सेवा देने वाली कंपनी की क्वेरी खोजता है जो https:// इंटेंट को हैंडल कर सकते हैं. हालांकि, क्वेरी फ़िल्टर सिर्फ़ android.support.customtabs.action.CustomTabsService क्वेरी के बारे में बताता है. क्या https:// इंटेंट के लिए क्वेरी का एलान नहीं किया जाना चाहिए?

जवाब: क्वेरी फ़िल्टर का एलान करते समय, यह किसी क्वेरी के जवाबों को PackageManager पर फ़िल्टर करेगा, न कि क्वेरी को. कस्टम टैब के साथ काम करने वाले ब्राउज़र, CustomTabsService को मैनेज करने का एलान करते हैं, इसलिए उन्हें फ़िल्टर नहीं किया जाएगा. जिन ब्राउज़र में कस्टम टैब काम नहीं करते उन्हें फ़िल्टर कर दिया जाएगा.

नतीजा

Android 11 के साथ काम करने के लिए, मौजूदा कस्टम टैब इंटिग्रेशन में बदलाव करने के लिए ये सभी बदलाव करने ज़रूरी हैं. किसी Android ऐप्लिकेशन में कस्टम टैब को इंटिग्रेट करने के बारे में ज़्यादा जानने के लिए, लागू करने की गाइड देखें. इसके बाद, फ़र्स्ट-क्लास इंटिग्रेशन बनाने के बारे में जानने के लिए, सबसे सही तरीके देखें.

अगर आपका कोई सवाल, सुझाव, शिकायत या राय है, तो हमें बताएं!