Intereting Posts
TestUI (Дженкинс) с использованием эспрессо Вопросы о шифровании активов приложений Google Play Измените погоду на погоду на Android в Цельсию? Как настроить приложение: layout_scrollFlags для панели инструментов программно View's getWidth () и getHeight (), возвращающие 0 Передача данных через кабель аудиоразъема на двух устройствах Android Как передать предварительный просмотр камеры на поверхность, созданный MediaCodec.createInputSurface ()? Ошибка 1 libavcodec.so Формат файла не распознан Android GL Live Wallpaper Как сделать запрос с учетом регистра с помощью ContentResolver в Android? Конфигурация Proguard для facebook sdk. Разделите все, кроме аналитики Использует ли «Избегайте базиса инъекций зависимостей» в Руководстве по памяти Android для кинжала? AccountManager без адаптера синхронизации? Как использовать Zxing в портретном режиме? Android: масштабировать графическое или фоновое изображение? База данных SQLite «контекст» передается адаптеру

Как использовать UsageStatsManager?

Задний план

Google отвергла функцию « getRecentTasks » класса «ActivityManager». Теперь все, что он делает, – это получить список приложений, которые открылось текущим приложением.

Я даже написал сообщение об этом здесь, в StackOverflow , но я заметил, что это невозможно.

Проблема

Я сделал сообщение об этом ( здесь и еще один, похожий на другой, созданный кем-то еще здесь ), и попросил его пересмотреть его, и Google решил создать новый класс, который, похоже, обеспечивает аналогичную функциональность (более похожее Статистика, но может также оказаться полезной), но я не могу узнать, как ее использовать.

Класс называется «UsageStatsManager», и я предполагаю, что функция « queryUsageStats » выполняет эту работу.

Кроме того, похоже, что у него есть новое разрешение («android.permission.PACKAGE_USAGE_STATS»), которое является системным разрешением, но написано, что:

Объявление разрешения подразумевает намерение использовать API, и пользователь устройства может предоставить разрешение через приложение «Настройки».

Вот еще одна ссылка об этой новой функциональности.

Что я нашел

Я просмотрел код Android и заметил, что «Контекст» имеет 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"; 

Странно то, что не только он говорит «строка состояния», но и имя пакета не соответствует (должно быть «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); 

В самом эмуляторе я перешел в «Настройки» -> «Безопасность» -> «Приложения с доступом к использованию» и включил мое приложение.

Однако при запуске кода все, что я получаю, это пустой список …

Вопрос

Как вы используете UsageStatsManager?

Кроме того, как вы позволяете пользователю предоставлять разрешение самым простым способом? Или это автоматически делается, как только приложение пытается получить необходимую информацию?

Что происходит при попытке использовать этот класс, пока пользователь еще не подтвердил его?

Как я могу заставить код вернуть мне реальный список приложений?

Solutions Collecting From Web of "Как использовать UsageStatsManager?"

Я думаю, что документация была просто короткой для материала календаря. Я не думаю, что он работает с 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()); 

-Credit MRK; (Он случайно просто положил cal вместо beginCal и endCal)

Код для параметров доступа к использованию приведен ниже. 🙂

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

Я создал образец того, как использовать UsageStats в моем Github. Надеюсь, это может помочь кому-то

https://github.com/ColeMurray/UsageStatsSample

Отвечая на ваш последний вопрос «Как я могу заставить код вернуть мне реальный список приложений?». 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 годов (помните, что время окончания не ограничивается диапазоном конечных результатов).

Использование UsageStats приведет к неправильной информации, когда пользователь откроет ящик уведомлений или на заблокированном экране. Вы должны использовать UsageStatsManager.queryEvents () и искать последнее событие с типом события MOVE_TO_FOREGROUND.

На самом деле есть пример приложения, включенного в пример кода AOSP : developers/samples/android/system/AppUsageStatistics/

Он включает все биты, необходимые для использования UsageStats в приложении:

  1. Объявление разрешения в AndroidManifest.xml

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

  2. Показать настройки для разрешения доступа к UsageStatsManager

    startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

  3. Query UsageStatsManager для статистики.

     Calendar cal = Calendar.getInstance(); cal.add(Calendar.YEAR, -1); List<UsageStats> queryUsageStats = mUsageStatsManager .queryUsageStats(intervalType, cal.getTimeInMillis(), System.currentTimeMillis()); 
  4. Создание списка приложений на основе 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); 

Вы можете сделать это

 //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);