¿Cómo obtener tareas recientes en Android “L”?

Fondo

Mi aplicación permite ordenar una lista de aplicaciones cuando se lanzaron recientemente.

El problema

A partir de Android “L”, la función getRecentTasks simplemente devolverá la lista de aplicaciones que ha lanzado la aplicación actual, como está escrito en la documentación :

Si su aplicación usa ActivityManager.getRecentTasks () …

Con la introducción de la nueva función de tareas concurrentes de documentos y actividades en la próxima versión (consulte Documentos concurrentes y actividades en la pantalla Recientes a continuación), el método ActivityManager.getRecentTasks () ahora está en desuso para mejorar la privacidad del usuario. Por compatibilidad con versiones anteriores, este método aún devuelve un pequeño subconjunto de sus datos, incluidas las tareas propias de la aplicación llamante y posiblemente algunas otras tareas no sensibles (como Home). Si su aplicación está utilizando este método para recuperar sus propias tareas, utilice android.app.ActivityManager.getAppTasks () en su lugar para recuperar esa información.

Lo mismo se escribe cuando se usa ADT para mostrar la documentación de esta función (actualmente no disponible en Internet):

Este método está en desuso. A partir de L, este método ya no está disponible para aplicaciones de terceros: como la introducción de elementos centrados en documentos significa que puede filtrar información personal a la persona que llama. Para la compatibilidad con versiones anteriores, aún devolverá un pequeño subconjunto de sus datos: al menos las tareas propias de la persona que llama (aunque vea getAppTasks () para la forma correcta de recuperar esa información), y posiblemente algunas otras tareas como el hogar que son conocidas por no ser sensible

No entiendo por qué se tomó este acto, ya que es fácil ver qué aplicaciones tiene el usuario, e incluso sin ningún permiso.

La cosa es que esta es una gran restricción para esta función que he agregado, así que espero que haya una manera de superar esto.

Lo que he intentado

Por ahora, solo utilicé una forma heurística acerca de qué aplicaciones se lanzaron recientemente; en su lugar, obtengo la lista de procesos en ejecución.

También podría usar el valor de importancia de los procesos y quizás el “importanceReasonComponent”, pero esto es solo heurística y conjeturas …

La pregunta

¿Hay alguna manera de superar esta restricción? ¿Alguna solución que no haya pensado?

Tal vez es posible con la raíz? ¿O BusyBox?

Para obtener el nombre del paquete superior (primer plano) en ejecución, debe usar la API Stats de uso en Android Lollipop.

Pero tenga en cuenta que el usuario debe aprobar el acceso a los datos de uso en la configuración de cada aplicación. Por lo tanto, debe solicitar al usuario directamente a la configuración iniciando la acción de configuración con

 Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); 

Para obtener el mejor nombre de paquete:

 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 stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*10, time); // Sort the stats by the last time used if(stats != null) { SortedMap mySortedMap = new TreeMap(); for (UsageStats usageStats : stats) { mySortedMap.put(usageStats.getLastTimeUsed(),usageStats); } if(!mySortedMap.isEmpty()) { topPackageName = mySortedMap.get(mySortedMap.lastKey()).getPackageName(); } } } 

Si usa UsageStats para obtener el paquete de primer plano actual, obtendrá la información incorrecta cuando el usuario abra el cajón de notificaciones o en una pantalla bloqueada. (probado en Android Lollipop y Marshmallow)

Debe usar UsageStatsManager.queryEvents () y buscar el último evento con el tipo de evento MOVE_TO_FOREGROUND para decidir el paquete de primer plano actual.

@ user3742392 la respuesta es buena, sin embargo, usar TreeMap para encontrar el último tiempo utilizado es un poco exagerado (especialmente si desea verificar periódicamente la aplicación que se ejecuta más arriba).

Aquí está la respuesta editada sin el TreeMap con bucle simple en su lugar:

 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 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(); } } } } 

Lollipop desaprobó el método; sin embargo, hay una nueva API que le permite ver el uso de la aplicación. El método fue desaprobado debido a problemas de seguridad. : \

UsageStatsManager tiene algunos métodos útiles para ver la actividad entre un intervalo de tiempo. Espero que esto sea suficiente para sus necesidades!

https://developer.android.com/reference/android/app/usage/package-summary.html