¿Existe una forma nativa de android para obtener una referencia a la actividad que se está ejecutando actualmente desde un servicio?
Tengo un servicio que se ejecuta en el fondo, y me gustaría actualizar mi actividad actual cuando se produce un evento (en el servicio). ¿Existe una forma fácil de hacerlo (como la que he sugerido arriba)?
Aquí'hay una buena manera de hacerlo utilizando el gestor de actividades. Básicamente obtienes los RunningTasks del gestor de actividades. Siempre devolverá primero la tarea actualmente activa. Desde ahí puedes obtener el topActivity.
(http://qtcstation.com/2011/01/getting-info-about-your-currently-running-activities/)
Hay una forma sencilla de obtener una lista de tareas en ejecución desde el servicio ActivityManager. Puedes solicitar un número máximo de tareas en ejecución en el teléfono, y por defecto, se devuelve primero la tarea actualmente activa.
Una vez que tienes eso puedes obtener un objeto ComponentName solicitando el topActivity de tu lista.
Aquí'hay un ejemplo.
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
Log.d("topActivity", "CURRENT Activity ::" + taskInfo.get(0).topActivity.getClassName());
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();
Necesitará el siguiente permiso en su manifiesto:
<uses-permission android:name="android.permission.GET_TASKS"/>
Google ha amenazado con eliminar aplicaciones de la Play Store si utilizan servicios de accesibilidad con fines no relacionados con la misma. Sin embargo, al parecer se está reconsiderando esta medida.
Servicio de Accesibilidad
AccessibilityService
.onAccessibilityEvent
, comprueba el TYPE_WINDOW_STATE_CHANGED
tipo de evento para determinar cuándo cambia la ventana actual.PackageManager.getActivityInfo()
.GET_TASKS
.AccessibilityService
, no puede pulsar el botón OK si una aplicación ha colocado una superposición en la pantalla. Algunas aplicaciones que hacen esto son Velis Auto Brightness y Lux. Esto puede ser confuso porque el usuario puede no saber por qué no puede pulsar el botón o cómo solucionarlo.AccessibilityService
no conoce la actividad actual hasta el primer cambio de actividad.public class WindowChangeDetectingService extends AccessibilityService {
@Override
protected void onServiceConnected() {
super.onServiceConnected();
//Configure these here for compatibility with API 13 and below.
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(config);
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
if (event.getPackageName() != null && event.getClassName() != null) {
ComponentName componentName = new ComponentName(
event.getPackageName().toString(),
event.getClassName().toString()
);
ActivityInfo activityInfo = tryGetActivity(componentName);
boolean isActivity = activityInfo != null;
if (isActivity)
Log.i("CurrentActivity", componentName.flattenToShortString());
}
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public void onInterrupt() {}
}
Fusione esto en su manifiesto:
<application>
<service
android:label="@string/accessibility_service_name"
android:name=".WindowChangeDetectingService"
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/accessibilityservice"/>
</service>
</application>
Ponga esto en res/xml/accessibilityservice.xml
:
<?xml version="1.0" encoding="utf-8"?>
<!-- These options MUST be specified here in order for the events to be received on first
start in Android 4.1.1 -->
<accessibility-service
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews"
android:description="@string/accessibility_service_description"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="UnusedAttribute"/>
Cada usuario de la aplicación tendrá que habilitar explícitamente el AccessibilityService
para que pueda ser utilizado. Vea esta respuesta de StackOverflow para saber cómo hacerlo.
Tenga en cuenta que el usuario no podrá pulsar el botón OK cuando intente habilitar el servicio de accesibilidad si una aplicación ha colocado una superposición en la pantalla, como Velis Auto Brightness o Lux.
¿Existe una forma nativa de android para obtener una referencia a la actividad que se está ejecutando actualmente desde un servicio?
Usted no puede poseer la "Actividad actualmente en ejecución".
Tengo un servicio que se ejecuta en el fondo, y me gustaría actualizar mi actividad actual cuando se produce un evento (en el servicio). ¿Existe una manera fácil de hacerlo (como la que sugerí arriba)?
Intent
de difusión a la actividad -- aquí hay un proyecto de ejemplo que demuestra este patrónPendingIntent
(por ejemplo, a través de createPendingResult()
) que el servicio invocabindService()
, y que el servicio llame a un método de evento en ese objeto callback/listenerIntent
de difusión ordenado a la actividad, con un BroadcastReceiver
de baja prioridad como respaldo (para lanzar una Notificación
si la actividad no está en pantalla) -- aquí hay una entrada del blog con más información sobre este patrón