Android获取前台进程包名

在Android L之前的版本,获取前台进程基本上是用下面两种方法:(现在都已失效)

方法一:getRunningTasks()

这种方法不仅可以获取前台进程包名,还可以获取前台activity名。

public String getForegroundActivity() {
    ActivityManager mActivityManager =
        (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        if (mActivityManager.getRunningTasks(1) == null) {
            Log.e(TAG, "running task is null, ams is abnormal!!!");
            return null;
        }
        ActivityManager.RunningTaskInfo mRunningTask =
                    mActivityManager.getRunningTasks(1).get(0);
        if (mRunningTask == null) {
            Log.e(TAG, "failed to get RunningTaskInfo");
            return null;
        }
 
        String pkgName = mRunningTask.topActivity.getPackageName();
        //String activityName =  mRunningTask.topActivity.getClassName();
        return pkgName;
}

方法二:getRunningAppProcesses()

这种方法只能获取前台包名。

    public String getForegroundApp(Context context) {
        ActivityManager am =
            (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List lr = am.getRunningAppProcesses();
        if (lr == null) {
            return null;
        }
 
        for (RunningAppProcessInfo ra : lr) {
            if (ra.importance == RunningAppProcessInfo.IMPORTANCE_VISIBLE
                || ra.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return ra.processName;
            }
        }
 
        return null;
    }

 在Android L上,google收紧了这两个API的权限,只能获取自身的包名,无法获取其他应用的包名。具体原因就是下面这个权限检查方法:

    private boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
        boolean allowed = checkPermission(android.Manifest.permission.REAL_GET_TASKS,
                callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
        if (!allowed) {
            if (checkPermission(android.Manifest.permission.GET_TASKS,
                    callingPid, callingUid) == PackageManager.PERMISSION_GRANTED) {
                // Temporary compatibility: some existing apps on the system image may
                // still be requesting the old permission and not switched to the new
                // one; if so, we'll still allow them full access.  This means we need
                // to see if they are holding the old permission and are a system app.
                try {
                    if (AppGlobals.getPackageManager().isUidPrivileged(callingUid)) {
                        allowed = true;
                        Slog.w(TAG, caller + ": caller " + callingUid
                                + " is using old GET_TASKS but privileged; allowing");
                    }
                } catch (RemoteException e) {
                }
            }
        }
        if (!allowed) {
            Slog.w(TAG, caller + ": caller " + callingUid
                    + " does not hold REAL_GET_TASKS; limiting output");
        }
        return allowed;
}

很明显,只有两种情况可以通过该权限检查:

  • 拥有REAL_GET_TASKS权限授权
  • 拥有GET_TASKS权限授权,同时自己是privileged app,也就是安装在/system/priv-app/下的app

查看frameworks/base/core/res/AndroidManifest.xml可知,REAL_GET_TASKS只有系统签名的app可以申请,第三方app申请了也白搭。

    
    
 
    
    

那么,在Android L之后,还有没有方法可以获取到前台包名呢?答案是肯定的,用usage statistics API。这个API本来是系统用来统计app使用情况的,包含了每个app最近一次被使用的时间。我们只需要找出距离现在时间最短的那个app,就是当前在前台的app

    private String getForegroundApp(Context context) {
        UsageStatsManager usageStatsManager = 
            (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
        long ts = System.currentTimeMillis();
        List queryUsageStats =
            usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, 0, ts);
        UsageEvents usageEvents = usageStatsManager.queryEvents(isInit ? 0 : ts-5000, ts);
        if (usageEvents == null) {
            return null;
        }


        UsageEvents.Event event = new UsageEvents.Event();
        UsageEvents.Event lastEvent = null;
        while (usageEvents.getNextEvent(event)) {
            // if from notification bar, class name will be null
            if (event.getPackageName() == null || event.getClassName() == null) {
                continue;
            }

            if (lastEvent == null || lastEvent.getTimeStamp() < event.getTimeStamp()) {
                lastEvent = event;
            }
        }

        if (lastEvent == null) {
            return null;
        }
        return lastEvent.getPackageName();
    }

你可能感兴趣的:(Android应用)