检查应用程序是否 运行 在前台

Checking if an application is running in foreground

在我的一个应用程序中,由于 Intent(不是我的),我需要手动启动一个应用程序。在那之后,我想知道这个由 Intent 启动的应用程序是 运行 在前台,在后台还是被杀死。

我创建了很多示例和片段,展示了如何获取 运行 processes/applications 的列表,但它们调用的方法自 API 21 以来已被弃用,例如 [=15] =] (http://developer.android.com/reference/android/app/ActivityManager.html).

其他方法如 ActivityManager.RunningAppProcessInfo 仅 return 我当前的应用程序而不是所有其他方法。我知道这是访问个人信息的安全问题,但是没有其他办法吗?

编辑 1

看了AndroidAPI,发现了classUsageStatsManager,从下面的post判断,好像是备选的:How to get list of recent apps with Android API 21 Lollipop?。我尝试使用 UsageStatsManager 但结果并不令人满意。我有一项服务旨在定期验证所选应用程序是否在前台。

public class CastService extends Service
{
    private static final String TAG = "CastService";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        ResolveInfo launchable = (ResolveInfo)intent.getExtras().get("selectedApp");
        final String packageName = launchable.activityInfo.packageName;

        final Handler handler = new Handler();
        final int delay = 2000; // ms

        handler.postDelayed(new Runnable()
        {
            @Override
            public void run()
            {
                Log.i(TAG, "isAppInactive(" + packageName + ") : " + isAppInactive(packageName));
                handler.postDelayed(this, delay);
            }
        }, delay);

        return Service.START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        return null;
    }

    protected boolean isAppInactive(String packageName)
    {
        UsageStatsManager usageStatsManager = (UsageStatsManager)getSystemService(Context.USAGE_STATS_SERVICE);
        return usageStatsManager.isAppInactive(packageName);
    }
}

该服务工作正常,每两秒记录一次方法 isAppInactive 的结果。不幸的是,即使相关应用程序在后台或被杀死,结果也不会改变:

I/CastService: isAppInactive(com.sec.android.gallery3d) : false

我以为我忘记在 AndroidManifest.xml 中添加权限,但它并没有解决它。

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

编辑 2

查看另一个示例 (),我重写了 isAppForeground 函数,但仍然无法正常工作。我的 UsageStats 列表总是空的。

protected boolean isAppForeground(String packageName)
{
    UsageStatsManager usageStatsManager = (UsageStatsManager)getSystemService(Context.USAGE_STATS_SERVICE);
    long time = System.currentTimeMillis();

    List<UsageStats> stats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 10, time);

    String topPackageName = new String();

    if(stats != null)
    {
        SortedMap<Long,UsageStats> mySortedMap = new TreeMap<>();

        for (UsageStats usageStats : stats)
        {
            mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
        }

        if(mySortedMap != null && !mySortedMap.isEmpty())
        {
            topPackageName =  mySortedMap.get(mySortedMap.lastKey()).getPackageName();
        }
    }

    return topPackageName.equals(packageName);
}

提前致谢。

查看我的应用程序设置,没有权限的踪迹,所以我决定检查权限 PACKAGE_USAGE_STATS 是否真的被授予,感谢以下功能。

public static boolean isPermissionGranted(Context context, String permission)
{
    AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    int mode = appOps.checkOpNoThrow(permission, android.os.Process.myUid(), context.getPackageName());
    boolean granted = mode == AppOpsManager.MODE_ALLOWED;

    Log.i(TAG, "isPermissionGranted(" + permission + ", " + android.os.Process.myUid() + ", " + context.getPackageName() + ") : " + granted);

    return granted;
}

我在调试模式下测试我的应用程序,它没有要求我允许之前的权限。多亏了终端和 adb 命令行,我手动授予了权限,我在之前编辑中定义的函数 isAppForeground 终于可以正常工作了。

adb -d shell pm grant com.package.name android.permission.PACKAGE_USAGE_STATS