¿Existe una forma nativa de Android para obtener una referencia a la Actividad actualmente en ejecución desde un servicio?
Tengo un servicio ejecutándose en segundo plano, y me gustaría actualizar mi Actividad actual cuando ocurra un evento (en el servicio). ¿Hay una manera fácil de hacer eso (como la que sugerí anteriormente)?
android
service
android-activity
Jorge
fuente
fuente
Respuestas:
No puede ser el propietario de la "Actividad actualmente en ejecución".
Intent
a la actividad: aquí hay un proyecto de muestra que demuestra este patrónPendingIntent
(por ejemplo, víacreatePendingResult()
) que el servicio invocabindService()
, y haga que el servicio llame a un método de evento en ese objeto de devolución de llamada / escuchaIntent
a la actividad, con una prioridad bajaBroadcastReceiver
como respaldo (para generar un mensajeNotification
si la actividad no está en la pantalla): aquí hay una publicación de blog con más información sobre este patrónfuente
instanceof
controles masivo o refactorizando las actividades para compartir una superclase o interfaz común. Y si va a refactorizar las actividades, también puede hacerlo de una manera que se ajuste mejor al marco y cubra más escenarios, como que ninguna de sus actividades esté activa. # 4 es probablemente el menos trabajo y el más flexible.Actualización : esto ya no funciona con las actividades de otras aplicaciones a partir de Android 5.0
Aquí hay una buena manera de hacerlo usando el administrador de actividades. Básicamente obtienes las RunningTasks del administrador de actividades. Siempre devolverá primero la tarea actualmente activa. Desde allí puede obtener la actividad superior.
Ejemplo aquí
Hay una manera fácil de obtener una lista de tareas en ejecución del servicio ActivityManager. Puede solicitar un número máximo de tareas que se ejecutan en el teléfono y, de manera predeterminada, la tarea activa actual se devuelve primero.
Una vez que tenga eso, puede obtener un objeto ComponentName solicitando topActivity de su lista.
Aquí hay un ejemplo.
Necesitará el siguiente permiso en su manifiesto:
fuente
As of LOLLIPOP, this method is no longer available to third party applications: the introduction of document-centric recents means it can leak person information to the caller. For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks, and possibly some other tasks such as home that are known to not be sensitive.
Advertencia: violación de Google Play
Google ha amenazado con eliminar aplicaciones de Play Store si usan servicios de accesibilidad para fines de no accesibilidad. Sin embargo, se informa que esto se está reconsiderando .
Usar un
AccessibilityService
AccessibilityService
.onAccessibilityEvent
devolución de llamada, verifique el tipo de evento para determinar cuándo cambia la ventana actual.TYPE_WINDOW_STATE_CHANGED
PackageManager.getActivityInfo()
.Beneficios
GET_TASKS
permiso.Desventajas
AccessibilityService
, no puede presionar el botón Aceptar 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 presionar el botón o cómo solucionarlo.AccessibilityService
no sabrá la actividad actual hasta el primer cambio de actividad.Ejemplo
Servicio
AndroidManifest.xml
Combina esto en tu manifiesto:
Información de servicio
Pon esto en
res/xml/accessibilityservice.xml
:Habilitar el servicio
Cada usuario de la aplicación deberá habilitar explícitamente el
AccessibilityService
para que pueda ser utilizado. Ver esta respuesta de StackOverflow para cómo hacer esto.Tenga en cuenta que el usuario no podrá presionar el botón Aceptar 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.
fuente
settingsActivity
deyour.app.ServiceSettingsActivity
, por lo que debe cambiarlo a su propia actividad de configuración para su servicio de accesibilidad. Creo que la actividad de configuración es opcional de todos modos, así que eliminé esa parte de mi respuesta para simplificarla.onAccessibilityEvent
no recibe ningún evento, pero si deshabilito y habilito nuevamente el Servicio de Accesibilidad, el servicio se reactiva yonAccessibilityEvent
comienza a funcionar.Se puede hacer por:
Implemente su propia clase de aplicación, regístrese en ActivityLifecycleCallbacks, de esta manera puede ver lo que está sucediendo con nuestra aplicación. En cada reanudación, la devolución de llamada asigna la actividad visible actual en la pantalla y, en pausa, elimina la asignación. Utiliza el método
registerActivityLifecycleCallbacks()
que se agregó en API 14.En su llamada de servicio
getApplication()
y transmítala al nombre de la clase de su aplicación (Aplicación en este caso). De lo que puede llamarapp.getActiveActivity()
, eso le dará una Actividad visible actual (o nula cuando no hay actividad visible). Puede obtener el nombre de la Actividad llamandoactiveActivity.getClass().getSimpleName()
fuente
onActivityResumed()
,onActivityPaused()
y paragetActiveActivity()
ver cómo se Callet, por lo que si alguna vez.activity
yactiveActivity
son los mismos antes de asignaractiveActivity
connull
el fin de errores Evita debido al fin de llamar entremezclado de los métodos del ciclo de vida de las diversas actividades.No pude encontrar una solución con la que nuestro equipo estaría contento, así que desarrollamos la nuestra. Usamos
ActivityLifecycleCallbacks
para hacer un seguimiento de la actividad actual y luego exponerla a través de un servicio:Luego configure su contenedor DI para devolver la instancia de
MyApplication
forContextProvider
, eg(Tenga en cuenta que la implementación de
getCurrent()
se omite del código anterior. Es solo una variable estática que se establece desde el constructor de la aplicación)fuente
activity
ycurrentActivity
son los mismos antes de asignarcurrentActivity
connull
el fin de errores Evita debido al fin de llamar entremezclado de los métodos del ciclo de vida de las diversas actividades.Utilizar
ActivityManager
Si solo desea conocer la aplicación que contiene la actividad actual, puede hacerlo utilizando
ActivityManager
. La técnica que puede usar depende de la versión de Android:ActivityManager.getRunningTasks
( ejemplo )ActivityManager.getRunningAppProcesses
( ejemplo )Beneficios
Desventajas
ActivityManager.RunningAppProcessInfo.processState
Ejemplo (basado en el código de KNaito )
Manifiesto
Agregue el
GET_TASKS
permiso aAndroidManifest.xml
:fuente
Estoy usando esto para mis pruebas. Sin embargo, es API> 19, y solo para actividades de su aplicación.
fuente
Use este código para API 21 o superior. Esto funciona y ofrece mejores resultados en comparación con las otras respuestas, detecta perfectamente el proceso en primer plano.
fuente
Aquí está mi respuesta que funciona bien ...
Debería poder obtener la Actividad actual de esta manera ... Si estructura su aplicación con algunas Actividades con muchos fragmentos y desea realizar un seguimiento de cuál es su Actividad actual, requeriría mucho trabajo. Mi senario fue que tengo una actividad con múltiples fragmentos. Por lo tanto, puedo realizar un seguimiento de la actividad actual a través del objeto de aplicación, que puede almacenar todo el estado actual de las variables globales.
Aquí hay un camino. Cuando inicia su Actividad, almacena esa Actividad por Application.setCurrentActivity (getIntent ()); Esta aplicación lo almacenará. En su clase de servicio, simplemente puede hacer como Intent currentIntent = Application.getCurrentActivity (); getApplication (). startActivity (currentIntent);
fuente
No sé si es una respuesta estúpida, pero resolví este problema almacenando una marca en las preferencias compartidas cada vez que ingresé en Crear () de cualquier actividad, luego utilicé el valor de las preferencias compartidas para descubrir cuál es la actividad en primer plano.
fuente
Recientemente me enteré de esto. Con apis como:
targetSdkVersion 26
ActivityManager.getCurrentActivity (contexto)
Espero que esto sea de alguna utilidad.
fuente
getCurrentActivity()
función en laActivityManager
clase ( developer.android.com/reference/android/app/ActivityManager ). Es curioso que esta función no existe:ActivityManager.isUserAMonkey()
.