Android 5.1.1及更高版本 - getRunningAppProcesses()仅返回我的应用程序包

Lio*_*luz 97 android android-6.0-marshmallow

谷歌似乎最终关闭了获取当前前台应用程序包的所有大门.

在Lollipop更新之后,getRunningTasks(int maxNum)由于这个答案,我使用此代码从Lollipop获取前台应用程序包:

final int PROCESS_STATE_TOP = 2;
RunningAppProcessInfo currentInfo = null;
Field field = null;
try {
    field = RunningAppProcessInfo.class.getDeclaredField("processState");
} catch (Exception ignored) { 
}
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = am.getRunningAppProcesses();
for (RunningAppProcessInfo app : appList) {
    if (app.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
        app.importanceReasonCode == 0 ) {
        Integer state = null;
        try {
            state = field.getInt( app );
        } catch (Exception ignored) {
        }
        if (state != null && state == PROCESS_STATE_TOP) {
            currentInfo = app;
            break;
        }
    }
}
return currentInfo;
Run Code Online (Sandbox Code Playgroud)

看起来,Android 5.1.1及以上版本(6.0 Marshmallow)也被杀死getRunningAppProcesses()了.它现在返回您自己的应用程序包的列表.


UsageStatsManager

我们可以使用此处所述的新UsageStatsManagerAPI,但它不适用于所有应用程序.某些系统应用程序将返回相同的包

com.google.android.googlequicksearchbox
Run Code Online (Sandbox Code Playgroud)

AccessibilityService(2017年12月:将被禁止供Google使用)

一些应用程序使用AccessibilityService(如此处所示)但它有一些缺点.


有没有其他方法来获取当前正在运行的应用程序包?

Jar*_*ler 92

要获取Android 1.6上运行进程的列表 - Android 6.0,您可以使用我写的这个库:https://github.com/jaredrummler/AndroidProcesses库读取/ proc以获取进程信息.

Google严格限制在Android Nougat中访问/ proc.要获取Android Nougat上正在运行的进程列表,您需要使用UsageStatsManager或具有root访问权限.

单击以前替代解决方案的编辑历史记录.

  • @androiddeveloper不,我只使用libsuperuser,因为它提供了一种简单的方法来运行shell命令(非root或root)并获得输出.如果有足够的需求,我可以在没有libsuperuser的情况下重新编写它. (3认同)
  • @BruceWayne我认为Jared正在引用这个链接:[https://source.android.com/devices/tech/security/selinux/index.html](https://source.android.com/devices/tech/security /selinux/index.html) (2认同)

Tar*_*rma 22

 private String printForegroundTask() {
    String currentApp = "NULL";
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        UsageStatsManager usm = (UsageStatsManager)this.getSystemService("usagestats");
        long time = System.currentTimeMillis();
        List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,  time - 1000*1000, time);
        if (appList != null && appList.size() > 0) {
            SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
            for (UsageStats usageStats : appList) {
                mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
            }
            if (mySortedMap != null && !mySortedMap.isEmpty()) {
                currentApp = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
            }
        }
    } else {
        ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> tasks = am.getRunningAppProcesses();
        currentApp = tasks.get(0).processName;
    }

    Log.e("adapter", "Current App in foreground is: " + currentApp);
    return currentApp;
}
Run Code Online (Sandbox Code Playgroud)

使用此方法获取前台任务.你需要一个系统权限"android:get_usage_stats"

public static boolean needPermissionForBlocking(Context context){
    try {
        PackageManager packageManager = context.getPackageManager();
        ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
        AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
        return  (mode != AppOpsManager.MODE_ALLOWED);
    } catch (PackageManager.NameNotFoundException e) {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

IF用户在设置 - >安全 - >应用程序中启用此功能并具有使用权限.之后你将获得前台任务.类似的过程通过Cheetahamobile 谷歌播放链接清洁matser

  • 这种方法至少在LG G3上不起作用,因为没有"设置 - >安全 - >带有使用访问权限的应用程序"菜单项 (2认同)
  • 这不是我的问题的答案.此外,此答案中未提供任何新信息. (2认同)

rva*_*rio 6

看看https://github.com/ricvalerio/foregroundappchecker,它可能就是你所需要的.提供示例代码,消除了必须实现跨版本前景检测器的痛苦.

这是两个样本:

AppChecker appChecker = new AppChecker();
String packageName = appChecker.getForegroundApp();
Run Code Online (Sandbox Code Playgroud)

或定期检查:

AppChecker appChecker = new AppChecker();
appChecker
    .when("com.other.app", new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .when("com.my.app", new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .other(new AppChecker.Listener() {
        @Override
        public void onForeground(String packageName) {
            // do something
        }
    )
    .timeout(1000)
    .start(this);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,但没有什么是新的.他只是包装了OP中提到的UsageStatsManager API.用户需要启用访问权限,与Android 5.1.1以来的其他方法一样 (2认同)