queryUsageStats interval duration

As UsageStatsManager doc says:

A request for data in the middle of a time interval will include that interval.

It seems that usage data is stored in buckets, and minimum bucket is a day, so you can't query usage stats for period less than a day. Even if you query a one-hour interval for a particular day, usage stats for the whole day is returned.


A little late to the party, but I think this might be useful to some.

You could use the queryEvents(long startTime, long endTime) from UsageStatsManager for achieving the desired result. The method could look like this (inspired by this post):

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public HashMap<String, AppUsageInfo> queryUsageStatistics(Context context, long startTime, long endTime) {
    UsageEvents.Event currentEvent;
    List<UsageEvents.Event> allEvents = new ArrayList<>();
    HashMap<String, AppUsageInfo> map = new HashMap<>();
    UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
    assert mUsageStatsManager != null;
    // Here we query the events from startTime till endTime.
    UsageEvents usageEvents = mUsageStatsManager.queryEvents(startTime, endTime);

    // go over all events.
    while (usageEvents.hasNextEvent()) {
        currentEvent = new UsageEvents.Event();
        usageEvents.getNextEvent(currentEvent);
        String packageName = currentEvent.getPackageName();
        if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED || currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED ||
                    currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED) {
            allEvents.add(currentEvent); // an extra event is found, add to all events list.
            // taking it into a collection to access by package name
            if (!map.containsKey(packageName)) {
                map.put(packageName, new AppUsageInfo());
            }
        }
    }

    // iterate through all events.
    for (int i = 0; i < allEvents.size() - 1; i++) {
        UsageEvents.Event event0 = allEvents.get(i);
        UsageEvents.Event event1 = allEvents.get(i + 1);

        //for launchCount of apps in time range
        if (!event0.getPackageName().equals(event1.getPackageName()) && event1.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED) {
            // if true, E1 (launch event of an app) app launched
            Objects.requireNonNull(map.get(event1.getPackageName())).launchCount++;
        }

        //for UsageTime of apps in time range
        if (event0.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED &&
                (event1.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED || event1.getEventType() == UsageEvents.Event.ACTIVITY_STOPPED)
                && event0.getPackageName().equals(event1.getPackageName())) {
            long diff = event1.getTimeStamp() - event0.getTimeStamp();
            Objects.requireNonNull(map.get(event0.getPackageName())).timeInForeground += diff;
        }
    }
    // and return the map.
    return map;
}

The AppUsageInfo class would be:

public class AppUsageInfo {

    public long timeInForeground;
    public int launchCount;

    AppUsageInfo() {
        this.timeInForeground = 0;
        this.launchCount = 0;
    }
}

To then get the usage stats for the last two hours, simply call

Calendar startCalendar = Calendar.getInstance();
startCalendar.add(Calendar.HOUR_OF_DAY, -2);
Calendar endCalendar = Calendar.getInstance();

HashMap<String, AppUsageInfo> result = queryUsageStatistics(context, startCalendar.getTimeInMillis(), endCalendar.getTimeInMillis();