I'm trying to fetch the daily screen time of each application that is installed on my phone using the following code from a service.
UsageStatsManager statsManager = (UsageStatsManager)service.getSystemService(Context.USAGE_STATS_SERVICE);
//todayDate is start of the day and today is current time
dailyUsage = statsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, todayDate.toDate().getTime(), today.toDateTime().getMillis());
for(UsageStats stats: dailyUsage){
Long totalTime = stats.getTotalTimeInForeground();
String app = stats.getPackageName();
Log("TotalTimeUsedToday", app + " " + totalTime);
}
I'm getting duplicate apps and some apps show 0 totalTime though sometimes it shows correct screen time.
Since the queryUsageStats works in a weird way, I decided to drop it and use queryEvents instead. Here's the complete function that works like a charm for my use case:
private Map<String, Long> testUsageStats(long startTime) {
long currTime = System.currentTimeMillis();
UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
UsageEvents usageEvents = mUsageStatsManager.queryEvents(startTime, currTime);
Map<String, Long> eventUsage = new HashMap<>();
Map<String, Long> totalUsage = new HashMap<>();
String lastApp = "xx";
while (usageEvents.hasNextEvent()) {
UsageEvents.Event currentEvent = new UsageEvents.Event();
usageEvents.getNextEvent(currentEvent);
String app = currentEvent.getPackageName();
Long time = currentEvent.getTimeStamp();
if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED
|| currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_PAUSED) {
if (currentEvent.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED) {
eventUsage.put(app, time);
lastApp = app;
}
else {
if (eventUsage.containsKey(app))
if (totalUsage.containsKey(app))
totalUsage.put(app, totalUsage.get(app) + (time - eventUsage.get(app)));
else
totalUsage.put(app, (time - eventUsage.get(app)));
eventUsage.remove(app);
}
}
}
if(eventUsage.containsKey(lastApp))
if (totalUsage.containsKey(lastApp))
totalUsage.put(lastApp, totalUsage.get(lastApp) + (System.currentTimeMillis() - eventUsage.get(lastApp)));
else
totalUsage.put(lastApp, (System.currentTimeMillis() - eventUsage.get(lastApp)));
for (String key : totalUsage.keySet()) {
Log("TestTimeUsed", key + " " + totalUsage.get(key));
}
return totalUsage;
}
This snippet covers the edge case of currently running app. Edge case at start time in which app has been started before the start time can also be handled with a bit of tweaking.