Vinculación / desvinculación a un servicio en una aplicación
Tengo una aplicación de Android que se vincula a un servicio persistente (una vez iniciado con startService()
).
El servicio es una parte integral de la aplicación y por lo tanto se utiliza en casi todas las actividades. Por lo tanto, quiero enlazar al servicio sólo una vez (en lugar de enlazar / desvincular en cada actividad) y mantener el enlace durante la vida de mi aplicación.
- Cómo enviar la ubicación del dispositivo en el servidor cuando sea necesario
- AlarmManager o Servicio
- Conectarse a través del nombre del servicio Bluetooth
- Detectar si mi servicio de accesibilidad está habilitado
- ¿Cómo iniciar y detener el servicio de Android desde una shell de anuncios?
He extendido desde la aplicación y enlazar con el servicio en la aplicación # onCreate () . Sin embargo ahora tengo el problema que no sé cuando mi aplicación existe ya que la aplicación # onTerminate () nunca se llama, vea JavaDoc:
Este método se utiliza en entornos de procesos emulados. Nunca se llamará a un dispositivo Android de producción, donde los procesos se eliminan simplemente matándolos; No se ejecuta ningún código de usuario (incluida esta devolución de llamada) al hacerlo.
Entonces, ¿cómo puedo limpiar de forma limpia de un servicio enlazado en la aplicación?
- Cómo programar un evento de clics en Android
- Ejecutar el oyente GPS en segundo plano en Android
- Relación entre Foreground Services y PARTIAL_WAKE_LOCK
- Activar el servicio de fondo en un momento específico de Android
- Android Actualizaciones periódicas de la ubicación GPS con AlarmManager dentro de un servicio
- Cómo iniciar la aplicación Android de sólo servicio
- Cómo comunicarse entre un receptor de difusión de Android y un RemoteService
- Android: servicio destruido cuando se gira la pantalla
He resuelto este problema contando las referencias a la vinculación de servicios en la Application
. Cada Activity
tiene que llamar a acquireBinding()
en sus métodos onCreate()
y llamar a releaseBinding()
en onDestroy()
. Si el contador de referencia llega a cero, se libera la unión.
He aquí un ejemplo:
class MyApp extends Application { private final AtomicInteger refCount = new AtomicInteger(); private Binding binding; @Override public void onCreate() { // create service binding here } public Binding acquireBinding() { refCount.incrementAndGet(); return binding; } public void releaseBinding() { if (refCount.get() == 0 || refCount.decrementAndGet() == 0) { // release binding } } } // Base Activity for all other Activities abstract class MyBaseActivity extend Activity { protected MyApp app; protected Binding binding; @Override public void onCreate(Bundle savedBundleState) { super.onCreate(savedBundleState); this.app = (MyApp) getApplication(); this.binding = this.app.acquireBinding(); } @Override public void onDestroy() { super.onDestroy(); this.app.releaseBinding(); } }
De la respuesta de Sven:
He resuelto este problema contando las referencias a la vinculación de servicios en la aplicación. Cada actividad tiene que llamar a acquireBinding () en sus métodos onCreate () y llamar a releaseBinding () en onDestroy (). Si el contador de referencia llega a cero, se libera la unión.
Estoy de acuerdo, pero usted no debe hacerlo en onDestroy – que a menudo no se llama.
En su lugar, sugiero lo siguiente (basado en su ejemplo de código) …
// Base Activity for all other Activities abstract class MyBaseActivity extend Activity { protected MyApp app; protected Binding binding; @Override public void onCreate(Bundle savedBundleState) { super.onCreate(savedBundleState); this.app = (MyApp) getApplication(); this.binding = this.app.acquireBinding(); } @Override protected void onPause() { super.onPause(); // Pre-HC, activity is killable after this. if ((11 > Build.VERSION.SDK_INT) && (isFinishing())) onFinishing(); } @Override protected void onStop() { super.onStop(); if ((10 < Build.VERSION.SDK_INT) && (isFinishing())) onFinishing(); } protected void onFinishing() { // Do all activity clean-up here. this.app.releaseBinding(); } }
PERO, mi uso de isFinishing () es sólo un pensamiento – no estoy seguro de que sea fiable. Tal vez onPause / onStop se llama con isFinishing () false, pero luego la actividad se mata – y su releaseBinding () nunca se llama.
Si te deshaces del cheque isFinishing creo que necesitas mover la llamada de acquireBinding () de onCreate a onStart / onResume (dependiendo de la versión de sdk), para asegurarte de que tu cuenta de ref no sea desordenada.
¿Quién sabía que liberar el servicio de su aplicación sería tan complicado?
¿Es obligatorio desenrollar en este caso? La aplicación se mata de todos modos. Intenté implementar una aplicación de ejemplo haciendo esto sin desenlazar y parece funcionar correctamente.
- Cómo evitar la notación científica en doble?
- Cómo mostrar un ListFragment existente en un DialogFragment