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

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

办法判断原理须要权限特点
1RunningTaskAndroid 5.0 以上办法被废除
2RunningProcessAndroid 5.1 以上只能获取本过程
3UsageStatsService最合乎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/...