Servicio enlazado versus servicio iniciado en Android y cómo hacer ambas cosas
Estoy haciendo una pregunta vehemente que ha sido (en parte, a mi juicio) abordado aquí y aquí . Digamos, como en muchos ejemplos, que queremos crear una aplicación de música, utilizando (digamos) una sola actividad y un servicio. Queremos que el servicio persista cuando la actividad se detiene o se destruye. Este tipo de ciclo de vida sugiere un servicio iniciado:
Un servicio se "inicia" cuando un componente de aplicación (como una actividad) lo inicia llamando a startService (). Una vez iniciado, un servicio puede ejecutarse en segundo plano indefinidamente, incluso si el componente que lo inició se destruye
- Lidiando con la intención implícita en la depreciación futura en Lollipop
- Android Silent Push
- Android: Compruebe si el servicio se está ejecutando a través de. BindService
- ¿Cómo puedo reiniciar mi servicio de aplicaciones si el usuario lo detiene (mata) desde la configuración?
- Cómo enviar la ubicación del dispositivo en el servidor cuando sea necesario
Ok, pero también queremos ser capaces de comunicarse con el servicio, por lo que necesitamos un servicio vinculante. No hay problema, tenemos un servicio enlazado y puesto en marcha como sugiere esta respuesta :
- Al iniciar la actividad (o algún otro punto) llamamos startService ()
- Después de eso llamamos bindService () para obtener la interfaz de IBinder , y proceder desde allí.
Hasta ahora todo está bien, pero un problema surge del hecho de que cuando se inicia la actividad, no sabemos si el servicio está cerca o no. Puede haber sido comenzado o no pudo haber sido. La respuesta podría ser algo como:
- En el inicio, intenta vincular al servicio (utilizar bindService () sin el indicador BIND_AUTO_CREATE )
- Si eso falla, a continuación, inicie el servicio mediante
startService()
y, a continuación, vincular a él.
Esta idea se basa en una lectura particular de los documentos para bindService()
:
Conéctese a un servicio de aplicaciones, creándolo si es necesario.
Si cero bandera significa "servicio no es realmente necesario" que estamos bien. Así que probamos algo como esto usando el siguiente código:
private void connectToService() { Log.d("MainActivity", "Connecting to service"); // We try to bind to an existing service Intent bindIntent = new Intent(this, AccelerometerLoggerService.class); boolean bindResult = bindService(bindIntent, mConnection, 0); if (bindResult) { // Service existed, so we just bound to it Log.d("MainActivity", "Found a pre-existing service and bound to it"); } else { Log.d("MainActivity", "No pre-existing service starting one"); // Service did not exist so we must start it Intent startIntent = new Intent(this, AccelerometerLoggerService.class); ComponentName startResult = startService(startIntent); if (startResult==null) { Log.e("MainActivity", "Unable to start our service"); } else { Log.d("MainActivity", "Started a service will bind"); // Now that the service is started, we can bind to it bindService(bindIntent, mConnection, 0); if (!bindResult) { Log.e("MainActivity", "started a service and then failed to bind to it"); } else { Log.d("MainActivity", "Successfully bound"); } } } }
Y lo que obtenemos es un enlace exitoso cada vez:
04-23 05:42:59.125: D/MainActivity(842): Connecting to service 04-23 05:42:59.125: D/MainActivity(842): Found a pre-existing service and bound to it 04-23 05:42:59.134: D/MainActivity(842): onCreate
La pregunta global es "¿Estoy malentendiendo los servicios vinculados versus los iniciados y cómo usarlos?" Preguntas más específicas son:
- ¿Es la correcta comprensión de los documentos pensar que cero bandera pasó a
bindService()
significa "No iniciar el servicio"? Si no, ¿no hay forma de llamar abindService()
sin iniciar el servicio? - ¿Por qué
bindService()
devuelvetrue
incluso si el servicio no está funcionando? En este caso, no parece que el servicio se ha iniciado, basado en llamadas deLog
. - Si hay el punto anterior es el comportamiento correcto / esperado de
bindService()
, hay una solución (es decir, de alguna manera garantizar questartService
se llama sólo si el servicio no se está ejecutando?)
PS He pasado del problema en mi propio código: startService()
llamadas startService()
, ya que repetidas startService()
son simplemente ignoradas. Sin embargo, todavía me gustaría entender los problemas mejor.
- Paho MqttAndroidClient.connect siempre falla
- Uso del servicio de aplicación en otra aplicación
- El servicio de Android se detiene al salir de la aplicación
- Android reproduciendo música en fondo
- Android Asynctask vs Runnable vs timertask vs Servicio
- Manejo de la funcionalidad "Deslizar para salir" de la lista de aplicaciones recientes de ICS
- Ciclo de vida del servicio que se inicia y se enlaza?
- Utilizar una intención para enviar datos a mi actividad
- Si bindService con 0 flag, el servicio no se iniciará. Puede bindService con el indicador BIND_AUTO_CREATE y si el servicio no se inicia, se iniciará. Sin embargo, cuando unbindService el servicio será destruido.
- BindService con el indicador 0 siempre devuelve true.
- Siempre puede llamar a startService. Si el servicio ya se está ejecutando, no se creará un nuevo servicio. Se llamará al servicio de ejecución onStartCommand.
No debería haber ningún problema si iniciaService en onCreate y luego bindService en onResume y unbindService en onPause.
- Android Studio mantiene la congelación incluso con la nueva versión de 2.2.3 para Windows
- Texto de recorte de Facebook en Android cuando se usa una intención de ACTION_SEND