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

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 a bindService() sin iniciar el servicio?
  • ¿Por qué bindService() devuelve true incluso si el servicio no está funcionando? En este caso, no parece que el servicio se ha iniciado, basado en llamadas de Log .
  • Si hay el punto anterior es el comportamiento correcto / esperado de bindService() , hay una solución (es decir, de alguna manera garantizar que startService 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.

  1. 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.
  2. BindService con el indicador 0 siempre devuelve true.
  3. 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.

  • El servicio Android debe ejecutarse siempre (nunca detener o detener)
  • Mantener el servicio de fondo vivo después de la aplicación de salida del usuario
  • ¿Cómo mantener una aplicación Android funcionando indefinidamente?
  • Android: crea servicio que se ejecuta cuando se detiene la aplicación
  • ¿Cómo utilizo Android SpeechRecognizer como servicio?
  • Android Service nunca parece iniciar - onStartCommand () no se llama
  • ¿Cuáles son las ventajas y desventajas de ejecutar un servicio en un proceso diferente?
  • Android "cerrar la fuerza" lo que exactamente sucede con la memoria
  • Receptor de difusión de portapapeles android
  • Inicie Android Service cada 5 minutos
  • Evitar que algunos usuarios cierren el servicio de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.