Как получить последние задачи на Android "L"?
Фон
Мое приложение позволяет сортировать список приложений по времени их недавнего запуска.
Эта проблема
Начиная с Android "L", функция getRecentTasks будет просто возвращать список приложений, запущенных текущим приложением, как написано в документации:
Если ваше приложение использует ActivityManager.getRecentTasks()...
С появлением в следующем выпуске новой функции одновременных документов и задач (см. Ниже раздел "Параллельные документы и действия на экране" Последние "") метод ActivityManager.getRecentTasks () устарел для улучшения конфиденциальности пользователей. Для обратной совместимости этот метод по-прежнему возвращает небольшое подмножество своих данных, включая собственные задачи вызывающего приложения и, возможно, некоторые другие не чувствительные задачи (такие как Home). Если ваше приложение использует этот метод для извлечения своих собственных задач, используйте вместо этого android.app.ActivityManager.getAppTasks() для получения этой информации.
То же самое написано при использовании ADT для отображения документации этой функции (в настоящее время недоступна в Интернете):
Этот метод устарел. Начиная с L, этот метод больше не доступен для сторонних приложений: поскольку введение документ-центрированных копий означает, что он может передавать утечку личной информации вызывающей стороне. Для обратной совместимости он по-прежнему будет возвращать небольшое подмножество своих данных: по крайней мере, собственные задачи вызывающего (хотя см. GetAppTasks () для правильного поддерживаемого способа получения этой информации) и, возможно, некоторые другие задачи, такие как home, которые известны не будь чувствительным.
Я не понимаю, почему был принят этот акт, так как легко увидеть, какие приложения есть у пользователя, и даже без какого-либо разрешения.
Дело в том, что это большое ограничение для этой функции, которую я добавил, поэтому я надеюсь, что есть способ преодолеть это.
Что я пробовал
Пока я использовал только эвристический способ, с помощью которого приложения были запущены недавно - вместо этого я получаю список запущенных процессов.
Я мог бы также использовать значение важности процессов и, возможно, "priorityReasonComponent", но это всего лишь эвристика и догадки...
Вопрос
Есть ли способ преодолеть это ограничение? Любой обходной путь, о котором я не думал?
Может это возможно с рутом? Или BusyBox?
4 ответа
Чтобы получить имя верхнего (переднего плана) пакета, которое запущено в данный момент, вам нужно использовать API статистики использования в Android Lollipop.
Но обратите внимание, что пользователь должен подтвердить доступ к данным об использовании в настройках каждого Приложения. Таким образом, вы должны предложить пользователю прямо к настройке, запустив действие настройки с
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
Чтобы получить лучшее имя пакета:
String topPackageName ;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService("usagestats");
long time = System.currentTimeMillis();
// We get usage stats for the last 10 seconds
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*10, time);
// Sort the stats by the last time used
if(stats != null) {
SortedMap<Long,UsageStats> mySortedMap = new TreeMap<Long,UsageStats>();
for (UsageStats usageStats : stats) {
mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
}
if(!mySortedMap.isEmpty()) {
topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
}
Если вы используете UsageStats для получения текущего пакета переднего плана, вы получите неверную информацию, когда пользователь откроет ящик уведомлений или на заблокированном экране. (протестировано на Android Lollipop и Marshmallow)
Вы должны использовать UsageStatsManager.queryEvents() и искать последнее событие с типом события MOVE_TO_FOREGROUND для определения текущего пакета переднего плана.
@user3742392 ответ хороший, однако использование TreeMap для нахождения последнего использованного времени немного излишне (особенно, если вы хотите периодически проверять приложение, запущенное в начале).
Вот отредактированный ответ без TreeMap с простым циклом:
String topPackageName;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager mUsageStatsManager = (UsageStatsManager) getSystemService("usagestats");
long currentTime = System.currentTimeMillis();
// get usage stats for the last 10 seconds
List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, currentTime - 1000 * 10, currentTime);
// search for app with most recent last used time
if (stats != null) {
long lastUsedAppTime = 0;
for (UsageStats usageStats : stats) {
if (usageStats.getLastTimeUsed() > lastUsedAppTime) {
topPackageName = usageStats.getPackageName();
lastUsedAppTime = usageStats.getLastTimeUsed();
}
}
}
}
Леденец осудил метод; однако есть новый API, который позволяет вам просматривать использование приложения. Метод устарел из-за проблем безопасности.: \
UsageStatsManager имеет несколько полезных методов для просмотра активности между интервалами времени. Надеюсь, этого достаточно для ваших нужд!
https://developer.android.com/reference/android/app/usage/package-summary.html