You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅通过Scheme判断应用是否安装的可行性及实现方案(兼容含Host参数的Intent-Filter场景)

仅通过Scheme判断应用是否安装的可行性及实现方案(兼容含Host参数的Intent-Filter场景)

首先,先明确你遇到的问题根源:当某个应用的Intent-Filter同时指定了scheme和host参数时,系统的Intent匹配规则会要求Uri必须同时包含这两个属性才能匹配成功。所以你用appscheme1://这种仅带scheme的Uri去查询,是不符合第一个应用的Intent-Filter条件的,自然会返回找不到Activity的结果。

那有没有办法只通过scheme来检测应用是否安装呢?当然有,我们可以直接遍历设备上所有已安装应用的Intent-Filter,主动检查是否存在包含目标scheme的配置,不管它有没有绑定host参数。

实现方案代码

下面是一个可以实现需求的工具方法,兼容带host和不带host的Intent-Filter场景:

fun isAppInstalledByScheme(targetScheme: String, packageManager: PackageManager): Boolean {
    // 获取所有已安装的应用(Android 11+ 需要在Manifest中配置queries,否则可能获取不到部分应用)
    val installedApps = packageManager.getInstalledApplications(0)
    
    for (appInfo in installedApps) {
        try {
            // 获取当前应用的所有Activity信息
            val activityInfos = packageManager.getPackageInfo(
                appInfo.packageName,
                PackageManager.GET_ACTIVITIES or PackageManager.GET_INTENT_FILTERS
            ).activities ?: continue
            
            for (activityInfo in activityInfos) {
                // 遍历当前Activity的所有Intent-Filter
                activityInfo.intentFilters?.forEach { filter ->
                    // 遍历Filter中的所有Data规则
                    filter.dataSchemes?.forEach { scheme ->
                        if (scheme.equals(targetScheme, ignoreCase = true)) {
                            // 找到匹配的scheme,直接返回true
                            return true
                        }
                    }
                }
            }
        } catch (e: PackageManager.NameNotFoundException) {
            // 应用可能在遍历过程中被卸载,忽略异常
            continue
        }
    }
    // 遍历完所有应用都没找到匹配的scheme
    return false
}

注意事项

  • Android 11+ 包可见性配置:如果你的应用目标SDK是30(Android 11)及以上,需要在AndroidManifest.xml中添加<queries>标签,来声明你需要查询的应用范围,否则可能无法获取到部分第三方应用的信息。比如如果要匹配所有应用的scheme,可以这样配置:
<manifest ...>
    <queries>
        <!-- 允许查询所有应用的Intent-Filter信息 -->
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="*" />
        </intent>
    </queries>
    ...
</manifest>
  • 性能说明:遍历所有应用的Intent-Filter会有一定的性能开销,如果需要频繁调用,建议做缓存处理,比如把检测结果缓存起来,一段时间内重复使用。
  • 大小写问题:scheme是大小写不敏感的,所以代码中用了ignoreCase = true来匹配,避免因为大小写不一致导致漏检。

为什么这个方法可行?

这个方法跳过了系统的Intent匹配逻辑,直接从PackageManager中读取每个应用的Intent-Filter配置,只要某个应用的任意一个Intent-Filter中包含目标scheme,不管它有没有绑定host、path等其他参数,都能被检测到。完美解决了你不知道目标应用是否配置了host参数的问题。

备注:内容来源于stack exchange,提问作者picKit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 10:59:16