Skip to content

判断App是否在前台,获取前台App的包名(仅支持系统App),同时对不同版本做兼容 #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 15, 2016

Conversation

onlylemi
Copy link
Contributor

判断 APP 是否在前台

  • 第三方 APP 通过 RunningAppProcessInfo 进可判断自己应用本身是否在前台,二不能判断某个 APP 是否在前台;
  • 系统 APP 可先获得前台 APP 包名,然后做对比,这样就可以判断某个 APP 是否在前台

如果需要获取前台 APP 的包名(仅针对系统 APP,第三方 APP 没有 PACKAGE_USAGE_STATS 权限),针对不同的版本做了兼容

  • API < 21,采用 RunningTaskInfo,需添加 android.permission.GET_TASKS 权限
  • 22 > API >= 21,采用 RunningAppProcessInfo
  • API >= 22,采用 UsageStatsManager,需添加 android.permission.PACKAGE_USAGE_STATS 权限

@onlylemi
Copy link
Contributor Author

@Blankj @jp1017 做了兼容,系统 APP 可以获取前台包名

@Blankj Blankj merged commit 03fba42 into Blankj:master Oct 15, 2016
@Blankj
Copy link
Owner

Blankj commented Oct 17, 2016

/**
 * 获取前台应用包名
 *
 * @param context 上下文
 * @return 前台应用包名
 */
public static String getForegroundApp(Context context) {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> infos = manager.getRunningAppProcesses();
    if (infos == null || infos.size() == 0) {
        return null;
    }
    for (ActivityManager.RunningAppProcessInfo ra : infos) {
        if (ra.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
            return ra.processName;
        }
    }
    return null;
}

这个也可以判断其他应用,所以不需要其他方法了,你的getPackegeName3和4我root测试都是返回null

@onlylemi
Copy link
Contributor Author

@Blankj

你这种就是 getPackegeName2,此方法在 API 21 之前只有在自己的 APP 在前台时可以抓取到其包名,其他 APP 在前台时 infos.size() 为 0,是获取不到的;API 21 之后采用系统提供的 UsageStatsManager 是可以获取到的(仅支持系统 APP 调用,第三方 APP 调用返回 null),亲测可用

@Blankj
Copy link
Owner

Blankj commented Oct 18, 2016

我今天测试了,stackoverflow上也说到不需要 系统应用,只需要添加Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);这个选项应用打开,在加上那个权限即可,下面是我的完整代码。

/**
/**
 * 获取前台应用包名
 * <p>当不是查看当前App,且SDK >= 22时,
 * 需添加权限 {@code <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>}</p>
 *
 * @param context 上下文
 * @return 前台应用包名
 */
public static String getForegroundProcessName(Context context) {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> infos = manager.getRunningAppProcesses();
    if (infos != null && infos.size() != 0) {
        for (ActivityManager.RunningAppProcessInfo info : infos) {
            if (info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return info.processName;
            }
        }
    }
    if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP) {
        PackageManager packageManager = context.getPackageManager();
        Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
        List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        System.out.println(list);
        if (list.size() > 0) {// 有"有权查看使用权限的应用"选项
            try {
                ApplicationInfo info = packageManager.getApplicationInfo(context.getPackageName(), 0);
                AppOpsManager aom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
                if (aom.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, info.uid, info.packageName) != AppOpsManager.MODE_ALLOWED) {
                    context.startActivity(intent);
                }
                if (aom.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, info.uid, info.packageName) != AppOpsManager.MODE_ALLOWED) {
                    LogUtils.d("getForegroundApp", "没有打开\"有权查看使用权限的应用\"选项");
                    return null;
                }
                UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
                long endTime = System.currentTimeMillis();
                long beginTime = endTime - 86400000 * 7;
                List<UsageStats> usageStatses = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, beginTime, endTime);
                if (usageStatses == null || usageStatses.isEmpty()) return null;
                UsageStats recentStats = null;
                for (UsageStats usageStats : usageStatses) {
                    if (recentStats == null || usageStats.getLastTimeUsed() > recentStats.getLastTimeUsed()) {
                        recentStats = usageStats;
                    }
                }
                return recentStats == null ? null : recentStats.getPackageName();
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
        } else {
            LogUtils.d("getForegroundApp", "无\"有权查看使用权限的应用\"选项");
        }
    }
    return null;
}

@onlylemi
Copy link
Contributor Author

@Blankj

我刚刚在 小米note 上测试了,是不可以的,返回 null。权限管理里并没有该权限,可能跟系统厂商有关

@Blankj
Copy link
Owner

Blankj commented Oct 20, 2016

恩,有些厂商给阉割了,所以加了if (list.size() > 0)这个判断,我MIUI8和原生6.0测的,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants