2

In one of my application, I need to launch manually an application thanks to an Intent (which is not mine). After that, I want to know if this application launched by an Intent is running in foreground, in background or killed.

I founded a lot of example and snippets showing how to get the list of running processes/applications but they are calling methods whose are now deprecated since API 21 like ActivityManager.RunningTasks(..) (http://developer.android.com/reference/android/app/ActivityManager.html).

The others methods like ActivityManager.RunningAppProcessInfo only return my current application and not all the other. I understand that this is a security issue of the access to personal information, but is there no other way ?

EDIT 1

After looking at the Android API, I found the class UsageStatsManager and judging by the following post, it seems to be an alternative : How to get list of recent apps with Android API 21 Lollipop?. I tried using UsageStatsManager but the result isn't satisfying. I've got a service which aim to regularly verify if the selected application is in foreground.

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);
    }
}

The service is working fine and log every two seconds the result of the method isAppInactive. Unfortunatetly, even if the concerned application is in background or killed, the result doesn't changed :

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

I thought I forget to add the permission in the AndroidManifest.xml but it doesn't fix it.

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

EDIT 2

Looking at another example (), I rewrote my isAppForeground function but still not working. My list of UsageStats is always empty.

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);
}

Thanks in advance.

Community
  • 1
  • 1
Schnapse
  • 485
  • 1
  • 5
  • 19

1 Answers1

1

Looking at my application settings, there was no trace of permission, so I decided to check if the permission PACKAGE_USAGE_STATS was really granted thanks to the following function.

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;
}

I was testing my application in debug mode and it didn't ask me to allow the previous permission. Thanks to the terminal and adb command line, I granted the permission manually and my function isAppForeground defined in previous EDIT is finally working fine.

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

Schnapse
  • 485
  • 1
  • 5
  • 19