Obtener el nombre del paquete de la aplicación en primer plano en Android

En el desarrollo de aplicaciones Android, es común necesitar determinar qué aplicación está actualmente en primer plano. Esto puede ser útil para funcionalidades como monitoreo de uso o restricciones. A continuación, se presentan tres métodos para lograrlo.

1. Uso de ActivityManager con el método getRunningTasks

Este método requiere el permiso GET_TASKS, pero está obsoleto en versiones recientes de Android.

public String obtenerPaqueteEnPrimerPlano(Context context) {
    ActivityManager gestorActividades = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> tareas = gestorActividades.getRunningTasks(1);
    if (!tareas.isEmpty()) {
        ComponentName actividadSuperior = tareas.get(0).topActivity;
        return actividadSuperior.getPackageName();
    }
    return null;
}

Agregar en AndroidManifest.xml:

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

2. Empleo de UsageStatsManager para aplicaciones recientes

Este enfoque permite obtener el paquete de la aplicación más recientemente usada mediante el servicio de estadísticas de uso. Se necesita el permiso PACKAGE_USAGE_STATS y que el usuario active manualmente el acceso.

public String obtenerPaqueteReciente(Context context) {
    UsageStatsManager gestorEstadisticas = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
    long tiempoActual = System.currentTimeMillis();
    long ventanaTiempo = 30 * 60 * 1000; // 30 minutos en milisegundos
    List<UsageStats> listaEstadisticas = gestorEstadisticas.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, tiempoActual - ventanaTiempo, tiempoActual);
    
    if (listaEstadisticas != null && !listaEstadisticas.isEmpty()) {
        TreeMap<Long, UsageStats> mapaOrdenado = new TreeMap<>();
        for (UsageStats estadisticas : listaEstadisticas) {
            mapaOrdenado.put(estadisticas.getLastTimeUsed(), estadisticas);
        }
        if (!mapaOrdenado.isEmpty()) {
            UsageStats masReciente = mapaOrdenado.get(mapaOrdenado.lastKey());
            return masReciente.getPackageName();
        }
    }
    return null;
}

Para habilitar el acceso, redirigir al usuario a la configuración:

Intent intento = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
context.startActivity(intento);

Declaración en AndroidManifest.xml:

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

3. Obtención mediante AccessibilityService

Los servicios de accesibilidad pueden interceptar eventos de ventana, lo que permite rastrear la aplicación en primer plano. Este método proporciona tanto el nombre del paquete como el de la actividad.

Primero, declarar el servicio en AndroidManifest.xml:

<service
    android:name=".servicio.MonitorAccesibilidad"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/config_accesibilidad" />
</service>

Crear el archivo de configuración en res/xml/config_accesibilidad.xml:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagRetrieveInteractiveWindows"
    android:canRetrieveWindowContent="true"
    android:canRequestFilterKeyEvents="false"
    android:notificationTimeout="100"
    android:description="@string/descripcion_accesibilidad" />

Implementar el servicio de accesibilidad:

public class MonitorAccesibilidad extends AccessibilityService {
    private String paqueteActual;
    private String actividadActual;

    @Override
    public void onAccessibilityEvent(AccessibilityEvent evento) {
        if (evento.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            paqueteActual = evento.getPackageName() != null ? evento.getPackageName().toString() : "";
            actividadActual = evento.getClassName() != null ? evento.getClassName().toString() : "";
            // Se puede usar paqueteActual para obtener el paquete en primer plano
        }
    }

    @Override
    public void onInterrupt() {
        // Manejar interrupciones si es necesario
    }
}

Este método puede ser detenido por el sistema en algunos dispositivos cuando la aplicación se cierra en segundo plano.

Etiquetas: Android ActivityManager UsageStatsManager AccessibilityService

Publicado el 7-3 02:16