普通网友 2025-08-09 18:05 采纳率: 97.8%
浏览 8
已采纳

如何在Android中获取当前正在运行的应用列表?

**问题描述:** 在Android开发中,如何兼容不同系统版本(尤其是Android 8.0及以上)获取当前正在运行的应用列表?使用`ActivityManager.getRunningTasks()`方法已被弃用,而`UsageStatsManager`需要用户授权且无法实时获取前台应用,导致开发者难以实现稳定、准确的运行应用检测功能。是否存在一种统一、高效且符合Google规范的方式来实现该需求?
  • 写回答

1条回答 默认 最新

  • Nek0K1ng 2025-08-09 18:05
    关注

    一、背景与问题概述

    在Android开发中,获取当前正在运行的应用列表是一项常见需求,尤其在系统监控、安全防护、应用管理等场景中尤为重要。然而,从Android 8.0(API 26)开始,Google逐步限制了对运行中任务的直接访问。

    • ActivityManager.getRunningTasks() 方法被弃用,且在高版本系统中无法返回有效信息。
    • UsageStatsManager 成为推荐替代方案,但需要用户手动授权,并且无法实时获取前台应用。

    因此,开发者面临一个两难问题:如何在兼容不同系统版本的前提下,实现稳定、高效、符合Google规范的应用运行状态检测?

    二、Android版本差异与权限变化

    从Android 5.0开始,Google逐步收紧对运行中任务的访问权限。以下是不同版本的主要变化:

    Android版本API等级支持方法限制说明
    Android 5.0 - 7.021 - 24getRunningTasks()返回部分信息,需声明权限
    Android 8.0 - 9.026 - 28getRunningTasks() 已弃用仅返回自身应用信息
    Android 10及以上29+UsageStatsManager需用户授权,无法实时获取

    三、主流解决方案分析

    目前开发者常用的方法包括:

    1. 使用UsageStatsManager获取使用统计
      • 需在Manifest中声明权限:android.permission.PACKAGE_USAGE_STATS
      • 需引导用户手动开启“使用情况访问”权限
      • 获取数据延迟较大,无法实时获取前台应用
    2. 通过AccessibilityService模拟前台应用检测
      • 监听通知栏或Activity切换事件
      • 需用户授权无障碍权限
      • 适用于特定场景,但不适用于通用检测
    3. Root权限绕过限制(非官方推荐)
      • 通过执行shell命令如psdumpsys获取进程信息
      • 依赖设备Root,不适用于普通用户
      • 违反Google Play政策,存在上架风险

    四、推荐方案与实现流程

    综合考虑兼容性、合规性与实用性,推荐采用如下混合方案:

    • 在Android 8.0以下使用ActivityManager.getRunningTasks()
    • 在Android 8.0及以上使用UsageStatsManager结合定时轮询
    • 对于需要实时检测前台应用的场景,考虑使用AccessibilityService

    流程图如下所示:

    graph TD
        A[获取运行应用列表] --> B{Android版本 < 8.0?}
        B -->|是| C[使用ActivityManager.getRunningTasks()]
        B -->|否| D[检查UsageStatsManager可用性]
        D --> E{是否已授权USAGE_STATS权限?}
        E -->|是| F[使用UsageStatsManager获取最近应用]
        E -->|否| G[引导用户前往设置授权]
        F --> H{是否需要实时检测前台应用?}
        H -->|是| I[启动AccessibilityService监听]
        H -->|否| J[完成获取]
        

    五、代码示例与实现细节

    以下是一个兼容不同Android版本的示例代码片段:

    
    public List getRunningApps(Context context) {
        List runningApps = new ArrayList<>();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
            long time = System.currentTimeMillis();
            List stats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 60, time);
            if (stats != null) {
                for (UsageStats usageStats : stats) {
                    runningApps.add(usageStats.getPackageName());
                }
            }
        } else {
            ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            List tasks = activityManager.getRunningTasks(10);
            for (ActivityManager.RunningTaskInfo task : tasks) {
                runningApps.add(task.topActivity.getPackageName());
            }
        }
        return runningApps;
    }
        

    注意:该方法无法实时获取前台应用,若需监听前台变化,需结合AccessibilityService或监听ACTION_SCREEN_ON等广播。

    六、未来展望与Google方向

    随着Android系统对隐私和安全的重视,Google将持续限制对系统运行状态的访问。未来可能的趋势包括:

    • 进一步限制UsageStatsManager的实时性与精度
    • 提供更多面向开发者的安全合规接口
    • 推动开发者使用系统级API或Google Play服务集成

    因此,开发者应提前规划,避免依赖非官方或即将被弃用的接口。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 10月23日
  • 创建了问题 8月9日