استخدام علامات التبويب المخصَّصة في Android 11

أجرى نظام التشغيل Android 11 تغييرات على كيفية تفاعل التطبيقات مع التطبيقات الأخرى التي ثبّتها المستخدم على الجهاز. يمكنك الاطّلاع على مزيد من المعلومات حول هذه التغييرات في مستندات Android.

عندما يستهدف تطبيق Android الذي يستخدم علامات التبويب المخصّصة المستوى 30 من حزمة تطوير البرامج (SDK) أو إصدارًا أحدث، قد تكون بعض التغييرات ضرورية. وتتناول هذه المقالة التغييرات التي قد تكون مطلوبة لهذه التطبيقات.

في أبسط الحالات، يمكن تشغيل علامات التبويب المخصّصة باستخدام سطر واحد على النحو التالي:

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

بالنسبة إلى التطبيقات التي تطلِق تطبيقات أخرى باستخدام هذا النهج، أو حتى تلك التي تضيف تخصيصات لواجهة المستخدم، مثل تغيير لون شريط الأدوات أو إضافة زر إجراء، لن تحتاج إلى إجراء أي تغييرات في التطبيق.

تفضيل التطبيقات المتوافقة

ولكن إذا اتّبعت أفضل الممارسات، قد تكون هناك حاجة لإجراء بعض التغييرات.

إنّ أفضل ممارسة ذات صلة هي أن تفضّل التطبيقات استخدام تطبيق أصلي للتعامل مع intent بدلاً من علامة تبويب مخصّصة إذا كان هناك تطبيق قادر على التعامل معه مثبّتًا.

على نظام التشغيل Android 11 والإصدارات الأحدث

يقدّم الإصدار 11 من Android علامة Intent جديدة، وهي 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;
    }
}

الحلّ هو محاولة تشغيل Intent واستخدام 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 عام. من المرجّح أن تكون هذه التطبيقات متصفحات.

بعد ذلك، نبحث عن التطبيقات التي تتعامل مع العناصر لعنوان URL المحدّد الذي نريد تشغيله. سيؤدي ذلك إلى عرض إعدادات المتصفّحات والتطبيقات المتوافقة مع نظام التشغيل لمعالجة عنوان URL هذا.

الآن، أزِل جميع المتصفّحات المتوفّرة في القائمة الأولى من القائمة الثانية، وسيتبقّى لدينا فقط التطبيقات المضمّنة.

إذا كانت القائمة فارغة، نعرف أنّه ما مِن معالجات أصلية، لذا نعرض خطأ. بخلاف ذلك، سنطلق القصد للمعالج الأصلي.

خلاصة ما سبق ذكره

يجب التأكّد من استخدام الطريقة المناسبة لكلّ حالة:

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 ويمكننا محاولة إطلاق تطبيق أصلي باستخدام النهج الجديد. وفي حال عدم نجاح ذلك، سنحاول الإطلاق باستخدام النهج القديم.

إذا تعذّر تشغيل تطبيق أصلي، سنشغّل علامات تبويب مخصّصة.

هناك بعض العبارات الجاهزة المضمّنة في هذه أفضل الممارسات. نحن نعمل على تبسيط هذه العملية من خلال تجميع العناصر المعقدة في مكتبة. يمكنك متابعة آخر الأخبار حول مكتبة الدعم android-browser-helper.

رصد المتصفّحات التي تتيح استخدام ميزة "علامات التبويب المخصّصة"

من الأنماط الشائعة الأخرى استخدام PackageManager لرصد المتصفّحات التي تتيح استخدام علامات التبويب المخصّصة على الجهاز. تشمل حالات الاستخدام الشائعة لهذا الإجراء ضبط الحزمة في Intent لتجنُّب مربّع الحوار لإزالة الالتباس بشأن التطبيق أو اختيار المتصفّح الذي يتم الاتصال به عند الاتصال بخدمة علامات التبويب المخصّصة.

عند استهداف مستوى واجهة برمجة التطبيقات 30، على المطوّرين إضافة قسم طلبات بحث إلى ملف بيان Android ، مع توضيح فلتر أهداف يتطابق مع المتصفّحات المتوافقة مع علامات التبويب المخصّصة.

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

بعد تطبيق الترميز، سيعمل الرمز الحالي المستخدَم للبحث عن المتصفّحات التي تتيح استخدام علامات التبويب المخصّصة على النحو المتوقّع.

الأسئلة الشائعة

س: يقدّم الرمز الذي يبحث عن علامات التبويب المخصّصة طلبات بحث للتطبيقات التي يمكنها معالجة https:// طلبات البحث، ولكنّ فلتر طلبات البحث يُعلن فقط عن طلب بحث android.support.customtabs.action.CustomTabsService. هل يجب عدم الإفصاح عن طلب بحث عن https:// intents؟

ج: عند الإعلان عن فلتر طلب بحث، سيتم فلترة الردود على طلب البحث المرسَل إلى PackageManager، وليس طلب البحث نفسه. وبما أنّ المتصفحات المتوافقة مع علامات التبويب المخصّصة تعلن عن معالجة CustomTabsService، لن يتم استبعادها. سيتمّ ترشيح المتصفحات التي لا تتيح استخدام ميزة "علامات التبويب المخصّصة".

الخاتمة

هذه هي جميع التغييرات المطلوبة لتعديل عملية دمج Tabs مخصّصة حالية كي تعمل مع Android 11. للاطّلاع على مزيد من المعلومات عن دمج علامات التبويب المخصّصة في تطبيق Android، ابدأ بقراءة دليل التنفيذ، ثم اطّلِع على أفضل الممارسات للتعرّف على كيفية إنشاء عملية دمج فائقة الجودة.

يُرجى إعلامنا إذا كانت لديك أي أسئلة أو ملاحظات.