Как использовать UsageStatsManager?
Фон
Google устарел функции " getRecentTasks
"класса"ActivityManager". Теперь все, что он делает, это получает список приложений, которые открыло текущее приложение.
Я даже написал пост об этом здесь в Stackru, но заметил, что это невозможно.
Эта проблема
Я сделал пост об этом ( здесь и другой, похожий, созданный кем-то другим, здесь) и попросил пересмотреть его, и Google решил создать новый класс, который, похоже, предоставляет аналогичную функциональность (больше похоже на статистика, но также может быть полезным), но я не могу узнать, как ее использовать.
Класс называется UsageStatsManager
"и я думаю, что функция" queryUsageStats
"делает работу.
Кроме того, похоже, у него есть новое разрешение (" android.permission.PACKAGE_USAGE_STATS
"), что является разрешением системы, но написано, что:
объявление разрешения подразумевает намерение использовать API, и пользователь устройства может предоставить разрешение через приложение "Настройки".
Вот еще одна ссылка об этой новой функциональности.
Что я нашел
Я посмотрел на код Android и заметил, что у "Context" есть USAGE_STATS_SERVICE, что в JavaDocs говорит следующее:
/**
* Use with {@link #getSystemService} to retrieve a {@link
* android.app.UsageStatsManager} for interacting with the status bar.
*
* @see #getSystemService
* @see android.app.UsageStatsManager
* @hide
*/
public static final String USAGE_STATS_SERVICE = "usagestats";
Странно то, что не только это говорит status bar
msgstr ", но также имя пакета не совпадает (должно быть" android.app.usage.UsageStatsManager
вместо этого.
Я также добавил правильное разрешение:
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
и вот код, который я использую:
final UsageStatsManager usageStatsManager=(UsageStatsManager)context.getSystemService("usagestats");// Context.USAGE_STATS_SERVICE);
final int currentYear=Calendar.getInstance().get(Calendar.YEAR);
final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,currentYear-2,currentYear);
В самом эмуляторе я зашел на Settings"->"security"->"apps with usage access
", и включил мое приложение.
Однако при запуске кода все, что я получаю, это пустой список...
Вопрос
Как вы используете UsageStatsManager
?
Кроме того, как вы позволяете пользователю предоставлять разрешение самым простым способом? Или это делается автоматически, как только приложение пытается получить необходимую информацию?
Что происходит при попытке использовать этот класс, пока пользователь еще не подтвердил это?
Как сделать так, чтобы код возвращал мне реальный список приложений?
7 ответов
Я думаю, что документация была просто краткой записью для календаря. Я не думаю, что это действительно работает только с 2014 года; однако я могу ошибаться.
Чтобы получить доступ к фактически списку UsageStats, вам нужно создать объект Calendar с правильными месяцем, днем и годом. Точно, как MRK сказал в другом ответе. Я скопировал и исправил ошибки в коде MRK, чтобы любой, кто увидит его в будущем, мог это увидеть.
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());
-Кредит МРК; исправил я (он случайно просто поставил cal вместо beginCal и endCal)
Код для настроек доступа к использованию приведен ниже.:)
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(intent);
Я создал пример того, как использовать UsageStats на моем Github. Надеюсь, это может помочь кому-то
На самом деле пример приложения включен в пример кода AOSP: developers/samples/android/system/AppUsageStatistics/
Включает в себя все необходимые биты UsageStats
в приложении:
Объявление разрешения в
AndroidManifest.xml
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
Показать настройки, чтобы предоставить разрешение на доступ
UsageStatsManager
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
запрос
UsageStatsManager
для статистики.Calendar cal = Calendar.getInstance(); cal.add(Calendar.YEAR, -1); List<UsageStats> queryUsageStats = mUsageStatsManager .queryUsageStats(intervalType, cal.getTimeInMillis(), System.currentTimeMillis());
Создание списка приложений на основе
UsageStats
Подведем итог и применим к вашему примеру:
- Вы, кажется, правильно запрашиваете и предоставляете разрешения для доступа к статистике использования.
- Вы правильно получаете
UsageStats
системный сервис. - Тем не менее, период времени, который вы запрашиваете, является коротким: Аргументы
beginTime
а такжеendTime
измеряются в миллисекундах с начала эпохи.Calendar
экземпляры могут дать вам это значение сgetTimeinMillis()
, То, что вы ошибочно делаете, это только давать номера года (2015
а также2017
если бы вы запустили программу сегодня). Эти значения интерпретируются как миллисекунды с начала эпохи, и поэтому интервал составляет всего 2 миллисекунды и составляет некоторое время в 1970 году.
Вместо приведенного ниже фрагмента кода вам следует скопировать приведенный ниже пример:
Неправильно:
final int currentYear=Calendar.getInstance().get(Calendar.YEAR);
final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,currentYear-2,currentYear);
Правильный:
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);
Отвечая на ваш последний вопрос "Как сделать так, чтобы код возвращал мне реальный список приложений?". queryUsageStats принимает время начала и время окончания в миллисекундах, а не значение года в 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());
Это должно вернуть список UsageStats за 2012 и 2013 годы (имейте в виду, что время окончания не входит в диапазон времени конечного результата).
Use UsageStats будет получать неверную информацию, когда пользователь открывает ящик уведомлений или на заблокированном экране. Вы должны использовать UsageStatsManager.queryEvents() и искать последнее событие с типом события MOVE_TO_FOREGROUND.
Если вы хотите увидеть статистику использования за определенный период времени. Сначала вы должны рассчитать продолжительность времени в миллисекундах начала и конца вашего периода времени, начиная с эпохи. (epoch - это количество секунд, прошедших с 00:00:00 UTC, четверг 1, 1970 г.) Или, как я покажу в следующем примере кода, простой способ - вычислить в обратном направлении текущее время в миллисекундах.
Например, если вы хотите получить статистику за последние 4 дня, это будет:
UsageStatsManager mUsageStatsManager = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE);
List<UsageStats> queryUsageStats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
(System.currentTimeMillis() - 345600000), System.currentTimeMillis());
Число 345600000 - это количество миллисекунд за 4 дня.
И для INTERVAL_TYPE это хорошо объясняется.
Система собирает и объединяет данные за 4 различных интервала времени: INTERVAL_DAILY, INTERVAL_WEEKLY, INTERVAL_MONTHLY и INTERVAL_YEARLY. Системные записи ограничены во времени, поэтому вы сможете получать данные об использовании приложения до 7 дней с интервалом в день, до 4 недель с интервалом в неделю, до 6 месяцев в месяц и, наконец, до 2 лет в год, Следует упомянуть о пятом варианте: INTERVAL_BEST выберет наиболее подходящий интервал между четырьмя выше, основываясь на выбранном вами временном интервале.
Ты можешь сделать это
//noinspection ResourceType
final UsageStatsManager usageStatsManager=(UsageStatsManager)context.getSystemService("usagestats");// Context.USAGE_STATS_SERVICE);
final int currentYear=Calendar.getInstance().get(Calendar.YEAR);
final List<UsageStats> queryUsageStats=usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY,currentYear-2,currentYear);