Solution 1:

I think the documentation was just short hand for the Calendar stuff. I don't think it actually works with just 2014; however I can be wrong.

In order to access the actually list of UsageStats, you would need to create a Calendar object with the correct month,day, and year. Exactly how MRK said in the other answer. I copied and corrected the errors in MRK's code so anyone who sees it in the future can see it.

Calendar beginCal = Calendar.getInstance();
beginCal.set(Calendar.DATE, 1);
beginCal.set(Calendar.MONTH, 0);
beginCal.set(Calendar.YEAR, 2012);

Calendar endCal = Calendar.getInstance();
endCal.set(Calendar.DATE, 1);
endCal.set(Calendar.MONTH, 0);
endCal.set(Calendar.YEAR, 2014);

final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, beginCal.getTimeInMillis(), endCal.getTimeInMillis());

-Credit MRK; corrected by me (he accidentally just put cal instead of beginCal and endCal)

The code for the usage access settings is below. :)

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

Solution 2:

I've created a sample of how to use UsageStats on my Github. Hopefully it can be of help to someone

https://github.com/ColeMurray/UsageStatsSample

Solution 3:

Answering your last question "How can I make the code return me a real list of apps?". queryUsageStats takes begin time and end time in milliseconds, not the value of the year in int.

Calendar beginCal = Calendar.getInstance();
beginCal.set(Calendar.DATE, 1);
beginCal.set(Calendar.MONTH, 0);
beginCal.set(Calendar.YEAR, 2012);

Calendar endCal = Calendar.getInstance();
endCal.set(Calendar.DATE, 1);
endCal.set(Calendar.MONTH, 0);
endCal.set(Calendar.YEAR, 2014);

final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, beginCal.getTimeInMillis(), endCal.getTimeInMillis());

This should return a list of UsageStats for the years 2012 and 2013 (keep in mind the end time is exclusive of the end result time range).

Solution 4:

There is actually an example app included in AOSP sample code: developers/samples/android/system/AppUsageStatistics/

It includes all the bits necessary to use UsageStats in an app:

  1. Declaring the permission in AndroidManifest.xml

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

  2. Show settings to grant permission to access UsageStatsManager

    startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

  3. Query UsageStatsManager for statistics.

    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.YEAR, -1);
    List<UsageStats> queryUsageStats = mUsageStatsManager
            .queryUsageStats(intervalType, cal.getTimeInMillis(),
                    System.currentTimeMillis());
    
  4. Creating a list of apps based on UsageStats

To summarize and apply to your example:

  • You seem to correctly ask for and grant permissions to access usage stats.
  • You correctly get the UsageStats system service.
  • However, the time period you query for is way too short: Arguments beginTime and endTime are measured in milliseconds since the epoch. Calendar instances can give you this value with getTimeinMillis(). What you erroneously do is to only give the year numbers (2015 and2017 if you would run the program today). These values are interpreted as milliseconds since the epoch and thus the interval is only 2 milliseconds long and is some time in 1970.

Instead of the following code snippet that you posted, you should copy the example I posted below:

Wrong:

final int currentYear=Calendar.getInstance().get(Calendar.YEAR);
final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,currentYear-2,currentYear);

Correct:

final long currentTime = System.currentTimeMillis(); // Get current time in milliseconds

final Calendar cal = Calendar.getInstance();
cal.add(Calendar.YEAR, -2); // Set year to beginning of desired period.
final long beginTime = cal.getTimeInMillis(); // Get begin time in milliseconds

final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, beginTime, currentTime);

Solution 5:

Use UsageStats will get the wrong information when user opens the notification drawer or on a locked screen. You have to use UsageStatsManager.queryEvents() and look for the latest event with MOVE_TO_FOREGROUND event type.