乐趣区

关于android:Android在后台服务中获取前台任务包名

「Android」在后盾服务中获取前台工作包名

@wenmingvs 总结了在 Android 里判断 APP 是否处于前台的办法,并把它们整合成了一个工具库 AndroidProcess。

办法 判断原理 须要权限 特点
1 RunningTask Android 5.0 以上办法被废除
2 RunningProcess Android 5.1 以上只能获取本过程
3 UsageStatsService 最合乎 Google 标准
4 通过 Android 无障碍性能实现 须要用户手动受权
5 读取 /proc 目录下的信息 IO 操作会引起耗时且 Android 零碎限度

通过若干验证,以上办法大多都无奈(或存在较多限度) 在后盾服务中获取前台工作包名 。综合比较而言,办法 3 中通过 UsageStatsManager 类来实现前台工作包名的获取可行性较高。

UsageStatsManager

UsageStatsManager 类为应用状况统计管理者,该类提供了设施应用历史和统计信息,具体数据按天、周、月、年等工夫距离进行聚合。

首先须要在 AndroidManifest 中申明对应权限:

    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
                     tools:ignore="ProtectedPermissions"/>

以下办法为通过 UsageStatsManager 类来获取前台工作包名的具体实现:


    /**
     * 获取前台利用包名
     *
     * @param context 上下文
     * @return 前台利用包名
     */
    public static synchronized String getForegroundPackageName(Context context) {Log.info(true, TAG, "getForegroundPackageName");
        String pkgName = Constants.EMPTY_STRING;
        if (!checkUsageAccessPermission(context)) {
            // 疏导用户关上权限
            Log.info(true, TAG, "getForegroundPackageName: no usage access permission");
            Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
            intent.setData(Uri.parse("package:" + context.getPackageName()));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
            return Constants.EMPTY_STRING;
        }
        long time = System.currentTimeMillis();
        long duration = NUMBER_TEN * ONE_MINUTE;
        long beginTime = time - duration;
        long endTime = time;
        Object systemService = context.getSystemService(Context.USAGE_STATS_SERVICE);
        if (systemService == null) {return Constants.EMPTY_STRING;}
        if (!(systemService instanceof UsageStatsManager)) {return Constants.EMPTY_STRING;}
        UsageStatsManager usageStatsManager = (UsageStatsManager) systemService;
        UsageEvents usageEvents = usageStatsManager.queryEvents(beginTime, endTime);
        UsageEvents.Event event = new UsageEvents.Event();
        while (usageEvents.hasNextEvent()) {usageEvents.getNextEvent(event);
            if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {if (TextUtils.equals(context.getPackageName(), event.getPackageName())) {continue;}
                pkgName = event.getPackageName();}
        }
        Log.info(true, TAG, "pkgName:", pkgName);
        return pkgName;
    }

    /**
     * 判断是否具备用户应用状况权限
     *
     * @param context 上下文
     * @return 是否具备用户应用状况权限
     */
    private static boolean checkUsageAccessPermission(Context context) {Log.info(true, TAG, "checkUsageAccessPermission");
        Object systemService = context.getSystemService(Context.USAGE_STATS_SERVICE);
        if (systemService == null) {return false;}
        if (!(systemService instanceof UsageStatsManager)) {return false;}
        UsageStatsManager usageStatsManager = (UsageStatsManager) systemService;
        long time = System.currentTimeMillis();
        long duration = NUMBER_TEN * ONE_MINUTE;
        long beginTime = time - duration;
        long endTime = time;
        List<UsageStats> usageStatsList =
            usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, beginTime, endTime);
        return usageStatsList != null && usageStatsList.size() != Constants.DEFAULT_INT_ZERO;}

参考

https://effmx.com/articles/to…
https://github.com/wenmingvs/…

退出移动版