استفاده از تب های سفارشی با اندروید 11

اندروید 11 تغییراتی را در نحوه تعامل برنامه ها با سایر برنامه هایی که کاربر بر روی دستگاه نصب کرده است، ارائه کرد. می‌توانید درباره آن تغییرات در اسناد Android بیشتر بخوانید.

هنگامی که یک برنامه Android با استفاده از تب های سفارشی سطح SDK 30 یا بالاتر را هدف قرار می دهد، ممکن است تغییراتی لازم باشد. این مقاله تغییراتی را که ممکن است برای آن برنامه ها مورد نیاز باشد بررسی می کند.

در ساده ترین حالت، Custom Tabs را می توان با یک لاینر مانند زیر راه اندازی کرد:

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

برنامه‌هایی که برنامه‌ها را با استفاده از این رویکرد راه‌اندازی می‌کنند، یا حتی سفارشی‌سازی‌های رابط کاربری را اضافه می‌کنند، مانند تغییر رنگ نوار ابزار ، افزودن دکمه عمل، نیازی به انجام هیچ تغییری در برنامه ندارند.

ترجیح دادن برنامه های بومی

اما، اگر از بهترین شیوه ها پیروی کنید، ممکن است تغییراتی لازم باشد.

اولین بهترین روش مرتبط این است که اگر برنامه‌ای که قادر به مدیریت آن نصب شده باشد، برنامه‌ها باید یک برنامه بومی را برای مدیریت هدف به جای یک Tab Custom ترجیح دهند .

در اندروید 11 و بالاتر

Android 11 یک پرچم جدید 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 بخواهید هنگام راه اندازی از مرورگرها اجتناب کند.

اگر یک برنامه بومی که قادر به مدیریت این Intent است یافت نشد، یک ActivityNotFoundException پرتاب می شود.

قبل از اندروید 11

حتی اگر برنامه ممکن است Android 11 یا API سطح 30 را هدف قرار دهد، نسخه‌های قبلی Android پرچم FLAG_ACTIVITY_REQUIRE_NON_BROWSER را متوجه نمی‌شوند، بنابراین در این موارد باید به جستجوی Package Manager متوسل شویم:

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

روشی که در اینجا استفاده می‌شود، پرس و جو از Package Manager برای برنامه‌هایی است که از یک http عمومی پشتیبانی می‌کنند. این برنامه ها احتمالاً مرورگرهایی هستند.

سپس، برای برنامه‌هایی که آیتم‌ها را برای URL خاصی که می‌خواهیم راه‌اندازی کنیم، پرس و جو کنید. این کار هم مرورگرها و هم تنظیمات برنامه های بومی را برای مدیریت آن URL برمی گرداند.

اکنون، تمام مرورگرهای موجود در لیست اول را از لیست دوم حذف کنید و ما فقط با برنامه های بومی باقی خواهیم ماند.

اگر لیست خالی باشد، می دانیم که هیچ کنترل کننده بومی وجود ندارد و false برگردانده می شود. در غیر این صورت، intent را برای هندلر بومی راه اندازی می کنیم.

همه را کنار هم گذاشتن

ما باید از استفاده از روش مناسب برای هر مناسبت اطمینان حاصل کنیم:

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 را با رویکرد جدید راه اندازی کنیم. در غیر این صورت، سعی می کنیم با رویکرد قدیمی راه اندازی کنیم.

اگر راه‌اندازی یک برنامه بومی با شکست مواجه شد، یک Tabs سفارشی راه‌اندازی می‌کنیم.

برخی از دیگ بخار در این بهترین عمل دخیل هستند. ما در حال کار روی ساده‌تر کردن این کار با کپسوله کردن پیچیدگی در یک کتابخانه هستیم. منتظر به‌روزرسانی‌های کتابخانه پشتیبانی Android-Browser-Helper باشید.

شناسایی مرورگرهایی که از تب های سفارشی پشتیبانی می کنند

یکی دیگر از الگوهای رایج استفاده از PackageManager برای تشخیص اینکه کدام مرورگرها از تب های سفارشی روی دستگاه پشتیبانی می کنند است. موارد استفاده رایج برای این کار، تنظیم بسته در Intent برای جلوگیری از گفتگوی ابهام‌زدایی برنامه یا انتخاب مرورگر برای اتصال هنگام اتصال به سرویس Tabs سفارشی است.

هنگام هدف قرار دادن API سطح 30، توسعه دهندگان باید یک بخش پرس و جو را به Manifest Android خود اضافه کنند و یک فیلتر هدف را اعلام کنند که با مرورگرهای دارای پشتیبانی Tabs سفارشی مطابقت دارد.

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

با وجود نشانه گذاری، کد موجود مورد استفاده برای پرس و جو برای مرورگرهایی که از Tabs سفارشی پشتیبانی می کنند، همانطور که انتظار می رود کار خواهد کرد.

سوالات متداول

س: کدی که به دنبال درخواست های ارائه دهندگان Tabs سفارشی برای برنامه هایی است که می توانند intent های https:// را مدیریت کنند، اما فیلتر query فقط یک جستار android.support.customtabs.action.CustomTabsService را اعلام می کند. آیا نباید یک پرس و جو برای اهداف https:// اعلام شود؟

پاسخ: هنگام اعلان فیلتر پرس و جو، پاسخ های یک پرس و جو را به PackageManager فیلتر می کند، نه خود پرس و جو را. از آنجایی که مرورگرهایی که از تب های سفارشی پشتیبانی می کنند، مدیریت CustomTabsService را اعلام می کنند، فیلتر نخواهند شد. مرورگرهایی که از برگه های سفارشی پشتیبانی نمی کنند، فیلتر می شوند.

نتیجه گیری

اینها همه تغییراتی هستند که برای تطبیق یک ادغام Custom Tabs برای کار با Android 11 لازم است. برای کسب اطلاعات بیشتر در مورد ادغام Custom Tabs در یک برنامه Android، با راهنمای پیاده سازی شروع کنید و سپس بهترین روش ها را برای یادگیری در مورد ساختن یک برنامه کلاس اول بررسی کنید. ادغام

اگر سوال یا بازخوردی دارید به ما اطلاع دهید!