Android 5.0+起getRunningTasks()对第三方应用彻底失效,应改用UsageStatsManager或Intent跳转检测;iOS和鸿蒙无法实时检测其他App运行状态,仅能判断安装或URL Scheme注册;“防多开”需服务端风控,前端仅做体验兜底。

Android 上用 ActivityManager.getRunningTasks() 检测多开已失效
从 Android 5.0(API 21)起,getRunningTasks() 对第三方应用彻底不可用,调用后返回空列表或抛出安全异常,不是你代码写错了,是系统直接拦了。即使你声明了 GET_TASKS 权限,也拿不到任何有效结果。
实操建议:
- 别再尝试兼容旧逻辑,比如判断
task.topActivity.packageName—— 它在真机上基本永远是false - 如果必须感知“目标 App 是否前台活跃”,可改用
UsageStatsManager(需用户手动开启“使用情况访问权限”,且 Android 8.0+ 需要QUERY_USAGE_STATS权限) - 更现实的替代方案:检测该 App 是否能响应特定
Intent(例如唤起微信分享页),靠“能否成功跳转”反推其存在与可交互性
iOS 和鸿蒙根本无法检测其他 App 是否运行
iOS 系统级禁止跨 App 状态探测,UIApplication.shared.isRegisteredForRemoteNotifications 或 canOpenURL: 都只能判断“是否注册了某 URL Scheme”,不能说明它此刻正在运行。鸿蒙同理,bundleManager.canOpenLink() 只能查安装状态,不反映进程存活。
常见错误现象:
- 在 iOS 端调用原生插件返回
true,其实是缓存或模拟值,不是实时状态 - 试图用后台保活、监听通知等方式“曲线救国”,但 iOS 会主动 kill 后台进程,不可靠
- 鸿蒙配置了
uris却检测失败?检查module.json5中querySchemes是否在检测方也同步声明,漏配就返回false
uni-app 里真正能落地的“多开/活跃”判断,只有间接行为反馈
与其执着于“它有没有开”,不如关注“它能不能用”。这是目前最稳定、跨平台兼容性最好的路径。
使用场景举例:
- 检测微信是否可用:
uni.openLocation()失败后 fallback 到 H5 分享;或用plus.runtime.openURL('weixin://')(App-Plus 环境)看是否跳转成功 - 检测钉钉是否安装:
uni.navigateTo({ url: 'dd://...' })的fail回调中处理,iOS 和 Android 表现一致 - 鸿蒙端统一走
bundleManager.canOpenLink('schB://com.example.appb/open'),前提是双方module.json5配置严格匹配 scheme/host/path
安全性校验别依赖“多开检测”,那是伪需求
所谓“防多开”本质上是业务风控问题,不是技术探测问题。你在前端看到的“多个 WebView 实例”或“多个进程”,系统根本不保证你能准确识别——尤其在 iOS 和鸿蒙沙箱下,连自己 App 的进程数都难获取,更别说别人。
容易踩的坑:
- 把“检测到微信在运行”当作登录态可信依据,结果用户只是刚切出去又切回来,实际微信没做任何认证
- 在支付回调里加“必须微信前台运行”校验,导致部分 Android 厂商定制系统(如华为 EMUI)因后台策略误判而失败
- 混淆“安装状态”和“运行状态”,鸿蒙
canOpenLink()返回true只代表装了,不代表它当前活着
真要控多开,得靠服务端设备指纹 + 登录态绑定 + 操作频次熔断,前端最多只做体验层兜底。

















