From c5807bc2c5e8160e498a25a03523dc7ecebf255a Mon Sep 17 00:00:00 2001 From: Shinya Kumagai Date: Thu, 23 Jul 2026 21:55:04 +0900 Subject: [PATCH 1/5] queryIntentActivities: simplify flag assignment to always use MATCH_ALL --- .../android/customtabs/launcher/CustomTabsPackage.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt index ad4e4ce..54b86cf 100644 --- a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt +++ b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt @@ -40,11 +40,7 @@ internal object CustomTabsPackage { } private fun queryIntentActivities(pm: PackageManager, intent: Intent): List { - val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - PackageManager.MATCH_ALL - } else { - PackageManager.MATCH_DEFAULT_ONLY - } + val flag = PackageManager.MATCH_ALL return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { pm.queryIntentActivities( intent, From 8f2156edda26d2e7e2ba5f626d214040fcd4820c Mon Sep 17 00:00:00 2001 From: Shinya Kumagai Date: Thu, 23 Jul 2026 21:59:37 +0900 Subject: [PATCH 2/5] Change CustomTabsPackageProvider to return List instead of Set The KDoc states that non-Chrome browser packages are prioritized from the top of the list, but the implementation kept them as `Set`, which does not guarantee iteration order. This made the actual behavior depend on the concrete Set implementation rather than the API contract. --- .../android/customtabs/launcher/CustomTabsPackage.kt | 4 ++-- .../customtabs/launcher/CustomTabsPackageProvider.kt | 10 ++++++---- .../customtabs/launcher/NonChromeCustomTabsTest.kt | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt index 54b86cf..b185549 100644 --- a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt +++ b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt @@ -23,7 +23,7 @@ internal object CustomTabsPackage { PACKAGE_CHROME_LOCAL, ) - fun getNonChromeCustomTabsPackages(context: Context): Set { + fun getNonChromeCustomTabsPackages(context: Context): List { val activityIntent = Intent(ACTION_VIEW, Uri.parse("http://")) .addCategory(Intent.CATEGORY_BROWSABLE) val pm = context.packageManager @@ -36,7 +36,7 @@ internal object CustomTabsPackage { .setPackage(it) pm.resolveService(serviceIntent, 0) != null } - .toSet() + .toList() } private fun queryIntentActivities(pm: PackageManager, intent: Intent): List { diff --git a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt index 0da02e3..4f2acfd 100644 --- a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt +++ b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt @@ -16,9 +16,9 @@ fun interface CustomTabsPackageProvider { /** * Retrieves the set of browser package names that support Custom Tabs. * - * @return A [Set] of package names as [String]. + * @return A [List] of package names as [String]. */ - operator fun invoke(): Set + operator fun invoke(): List } /** @@ -30,18 +30,20 @@ fun interface CustomTabsPackageProvider { * @param packages Package list of non-Chrome browsers supporting Custom Tabs. The top of the list is used with the highest priority. */ class NonChromeCustomTabs( - private val packages: Set, + private val packages: List, ) : CustomTabsPackageProvider { constructor(context: Context) : this( CustomTabsPackage.getNonChromeCustomTabsPackages(context), ) + constructor(packages: Set) : this(packages.toList()) + init { require(packages.none { CHROME_PACKAGES.contains(it) }) { "Packages must not contain any Chrome packages." } } - override operator fun invoke(): Set = packages + override operator fun invoke(): List = packages } diff --git a/launcher/src/test/java/com/droibit/android/customtabs/launcher/NonChromeCustomTabsTest.kt b/launcher/src/test/java/com/droibit/android/customtabs/launcher/NonChromeCustomTabsTest.kt index 9ce6d1c..e0a8fdf 100644 --- a/launcher/src/test/java/com/droibit/android/customtabs/launcher/NonChromeCustomTabsTest.kt +++ b/launcher/src/test/java/com/droibit/android/customtabs/launcher/NonChromeCustomTabsTest.kt @@ -23,7 +23,7 @@ class NonChromeCustomTabsTest { @Test fun `invoke returns non-Chrome packages`() { - val packages = setOf( + val packages = listOf( "com.example.customtabs_1", "com.example.customtabs_2", ) From d665b6c74c18b7c177d210408b8269fbd3591335 Mon Sep 17 00:00:00 2001 From: Shinya Kumagai Date: Thu, 23 Jul 2026 22:03:59 +0900 Subject: [PATCH 3/5] Use LinkedHashSet for CHROME_PACKAGES to preserve priority order Replace it with linkedSetOf() so the ordered nature of the collection is explicit and the priority semantics are preserved correctly. This is an internal change and does not affect the public API. --- .../droibit/android/customtabs/launcher/CustomTabsPackage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt index b185549..ed63f40 100644 --- a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt +++ b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt @@ -16,7 +16,7 @@ internal object CustomTabsPackage { private const val PACKAGE_CHROME_LOCAL = "com.google.android.apps.chrome" // Higher priority packages are listed first. - val CHROME_PACKAGES = setOf( + val CHROME_PACKAGES = linkedSetOf( PACKAGE_CHROME_STABLE, PACKAGE_CHROME_BETA, PACKAGE_CHROME_DEV, From 93a1571dacccc2fa9604f66dbaa584bac9176a83 Mon Sep 17 00:00:00 2001 From: Shinya Kumagai Date: Thu, 23 Jul 2026 23:11:56 +0900 Subject: [PATCH 4/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../droibit/android/customtabs/launcher/CustomTabsPackage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt index ed63f40..0a05653 100644 --- a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt +++ b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackage.kt @@ -16,7 +16,7 @@ internal object CustomTabsPackage { private const val PACKAGE_CHROME_LOCAL = "com.google.android.apps.chrome" // Higher priority packages are listed first. - val CHROME_PACKAGES = linkedSetOf( + val CHROME_PACKAGES: Set = linkedSetOf( PACKAGE_CHROME_STABLE, PACKAGE_CHROME_BETA, PACKAGE_CHROME_DEV, From 6c98a34b967c4aec2f29abe6685261f6650bcf43 Mon Sep 17 00:00:00 2001 From: Shinya Kumagai Date: Thu, 23 Jul 2026 23:14:39 +0900 Subject: [PATCH 5/5] Clarify documentation to specify list instead of set for browser package names in CustomTabsPackageProvider --- .../customtabs/launcher/CustomTabsPackageProvider.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt index 4f2acfd..11dbd8e 100644 --- a/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt +++ b/launcher/src/main/java/com/droibit/android/customtabs/launcher/CustomTabsPackageProvider.kt @@ -5,7 +5,7 @@ import androidx.browser.customtabs.CustomTabsIntent import com.droibit.android.customtabs.launcher.CustomTabsPackage.CHROME_PACKAGES /** - * Interface for providing a set of browser package names that support Custom Tabs. + * Interface for providing a list of browser package names that support Custom Tabs. * * The [CustomTabsPackageProvider] interface allows you to specify alternative browsers * that can handle Custom Tabs when launching URLs using [CustomTabsIntent]. @@ -14,7 +14,7 @@ import com.droibit.android.customtabs.launcher.CustomTabsPackage.CHROME_PACKAGES */ fun interface CustomTabsPackageProvider { /** - * Retrieves the set of browser package names that support Custom Tabs. + * Retrieves the list of browser package names that support Custom Tabs. * * @return A [List] of package names as [String]. */ @@ -22,7 +22,7 @@ fun interface CustomTabsPackageProvider { } /** - * Provides a set of non-Chrome browser package names that support Custom Tabs. + * Provides a list of non-Chrome browser package names that support Custom Tabs. * * This is useful when Chrome is not installed or when you prefer to use a different browser * that supports Custom Tabs.