0

I need to get the current Activity of the foreground App. I tried following this answer and later used this library(because the first solution only worked from Lollipop), and them indeed worked well telling the foreground app's package name, but I need to know what activity is open.

2 Answers2

6

Hey @Capitan Luzzatto,

  • Pre LOLLIPOP(API 21) we can get list of running apps from ActivityManager
  • But From LOLLIPOP we should get only from UsageStatsManager

First you need 2 permissions to read the tasks

<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />

And you should check first the user API level is 21 or more if yes you should get access for usage access settings like below

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP && !mIsChecked) {
        if (getUsageStatsList(getActivity()).isEmpty()) {

            Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
            startActivity(intent);
        }
 }

to get Usage stats list

    public static List<UsageStats> getUsageStatsList(Context context){
    UsageStatsManager usm = (UsageStatsManager) context.getSystemService("usagestats");
    Calendar calendar = Calendar.getInstance();
    long endTime = calendar.getTimeInMillis();
    calendar.add(Calendar.DATE, -1);
    long startTime = calendar.getTimeInMillis();

    List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,startTime,endTime);

    return usageStatsList;
}

Finally you can get the latest Foreground app using the following method

public String getRecentApps(Context context) {
    String topPackageName = "";

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);

        long time = System.currentTimeMillis();

        UsageEvents usageEvents = mUsageStatsManager.queryEvents(time - 1000 * 30, System.currentTimeMillis() + (10 * 1000));
        UsageEvents.Event event = new UsageEvents.Event();
        while (usageEvents.hasNextEvent()) {
            usageEvents.getNextEvent(event);
        }

        if (event != null && !TextUtils.isEmpty(event.getPackageName()) && event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
            if (AndroidUtils.isRecentActivity(event.getClassName())) {
                return event.getClassName();
            }
            return event.getPackageName();
        } else {
            topPackageName = "";
        }
    } else {
        ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
        ComponentName componentInfo = taskInfo.get(0).topActivity;

        if (AndroidUtils.isRecentActivity(componentInfo.getClassName())) {
            return componentInfo.getClassName();
        }

        topPackageName = componentInfo.getPackageName();
    }


    return topPackageName;
}

To get Foreground activity use the method like this

public String getRecentActivity(Context context) {
    String topActivityName = "";

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);

        long time = System.currentTimeMillis();

        UsageEvents usageEvents = mUsageStatsManager.queryEvents(time - 1000 * 30, System.currentTimeMillis() + (10 * 1000));
        UsageEvents.Event event = new UsageEvents.Event();
        while (usageEvents.hasNextEvent()) {
            usageEvents.getNextEvent(event);
        }

        if (event != null && !TextUtils.isEmpty(event.getPackageName()) && event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
            return event.getClassName();
        } else {
            topActivityName = "";
        }
    } else {
        ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
        ComponentName componentInfo = taskInfo.get(0).topActivity;

        topActivityName = componentInfo.getClassName();
    }


    return topActivityName;
}

AndroidUtils.java - To get the device recent screen in Hack way, Maybe we should investigate more on this, Not sure it will work on all device, but it works on almost all devices

public class AndroidUtils {
    private static final String RECENT_ACTIVITY;

    static {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            RECENT_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
        } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
            RECENT_ACTIVITY = "com.android.systemui.recent.RecentsActivity";
        } else {
            RECENT_ACTIVITY = "com.android.internal.policy.impl.RecentApplicationDialog";
        }
    }

    /**
     * To get the Device recent screen activity
     *
     * @param className
     * @return activity
     */
    public static boolean isRecentActivity(String className) {
        if (RECENT_ACTIVITY.equalsIgnoreCase(className)) {
            return true;
        }

        return false;
    }
}
Muthukrishnan Rajendran
  • 11,122
  • 3
  • 31
  • 41
0

You should not be able to do it due to security issues. You don't want another app to know your current open activity. So other apps don't want you to spy on them. This is an OS limitation.

Robert K.
  • 1,043
  • 1
  • 8
  • 20