¿Cuándo se destruye un servicio iniciado y enlazado?

Estaba pasando por la documentación de servicios en android cuando noté dos puntos contradictorios:

En el documento de servicios se especifica en Gestión del ciclo de vida de un servicio

Estos dos caminos no están completamente separados. Es decir, puede vincular a un servicio que ya se inició con startService (). Por ejemplo, se podría iniciar un servicio de música de fondo llamando a startService () con un Intent que identifica la música que se va a reproducir. Posteriormente, posiblemente cuando el usuario quiera ejercer algún control sobre el reproductor o obtener información sobre la canción actual, una actividad puede vincularse al servicio llamando a bindService (). En casos como este, stopService () o stopSelf () realmente no detiene el servicio hasta que todos los clientes se desvinculan.

Pero en el documento sobre los servicios vinculados en la gestión del ciclo de vida de un servicio vinculado

Sin embargo, si decide implementar el método de devolución de llamada onStartCommand (), debe detener el servicio de forma explícita, ya que el servicio se considera iniciado. En este caso, el servicio se ejecuta hasta que el servicio se detiene con stopSelf () u otro componente llama a stopService (), independientemente de si está vinculado a cualquier cliente.

Puede que sea yo, pero creo que las declaraciones son contradictorias.

En realidad, ambos párrafos se complementan (aunque su redacción puede ser equivocada), y ambos párrafos son coherentes con la imagen de la documentación. Echemos un vistazo:

Estos dos caminos no están completamente separados. Es decir, puede vincular a un servicio que ya se inició con startService (). Por ejemplo, se podría iniciar un servicio de música de fondo llamando a startService () con un Intent que identifica la música que se va a reproducir. Posteriormente, posiblemente cuando el usuario quiera ejercer algún control sobre el reproductor o obtener información sobre la canción actual, una actividad puede vincularse al servicio llamando a bindService (). En casos como este, stopService () o stopSelf () realmente no detiene el servicio hasta que todos los clientes se desvinculan.

La quintaesencia es: Si inicia un servicio, a continuación, enlazar a un cliente a él, a continuación, intente detenerlo, el servicio no se detiene (destruido) antes de que todos los clientes desvincular. El segundo párrafo no contradice, refina esta afirmación.

Sin embargo, si decide implementar el método de devolución de llamada onStartCommand (), debe detener el servicio de forma explícita, ya que el servicio se considera iniciado. En este caso, el servicio se ejecuta hasta que el servicio se detiene con stopSelf () u otro componente llama a stopService (), independientemente de si está vinculado a cualquier cliente.

Esto significa: Un servicio iniciado y enlazado se ejecuta incluso si no hay clientes vinculados a él hasta que se detenga explícitamente. Por supuesto, la redacción podría ser un poco más clara en esto. Sin embargo, el diagrama de ciclo de vida de la documentación lo demuestra (y estoy bastante seguro de que ya lo he observado en "la vida real", aunque actualmente no tengo un ejemplo directo encima de mi cabeza):

Ciclo de vida de los servicios iniciados y enlazados

Aceptar que la documentación podría ser más clara. Lo que están tratando de decir es:

  • Si llama a startService (), el servicio continuará funcionando a menos y hasta que llame a stopSerivce () (o stopSelf () desde dentro del servicio)
  • Si llama a bindService (), el servicio seguirá funcionando a menos y hasta que llame unbindService ()
  • Por lo tanto, si llama a startService () y bindService (), el servicio continuará funcionando hasta que llame a stopService y unbindService (). Ni por sí solo detendrá el servicio.

Creó una actividad y un servicio muy simple y funcionó las secuencias siguientes de comienzo / para / bind / unbind. Observé que las llamadas daban los siguientes resultados.

Encuadernar

bindService() caused: onCreate() onBind() unbindService() caused: onUnbind() onDestroy() 

Start-bind-unbind-stop

 startService() caused: onCreate() onStartCommand() bindService() caused: onBind() unbindService() caused: onUnbind() stopService() caused: onDestroy() 

Inicio-bind-stop-unbind

 startService() caused: onCreate() onStartCommand() bindService() caused: onBind() stopService() caused: -- nothing unbindService() caused: onUnbind() onDestroy() 

Bind-start-stop-unbind

 bindService() caused: onCreate() onBind() startService() caused: onStartCommand() stopService() caused: -- nothing -- still running unbindService() caused: onUnbind() onDestroy() 

Bind-start-unbind-stop

 bindService() caused: onCreate() onBind() startService() caused: onStartCommand() unbindService() caused: onUnbind() stopService() caused: onDestroy() 

Como se puede ver, en cada caso en que se llamaban ambos bind y start, el servicio se mantuvo en funcionamiento hasta que se llamaron a unbind y stop. La secuencia de unbind / stop no es importante.

Aquí está el código de ejemplo que se llamó desde botones separados en mi aplicación de prueba simple:

 public void onBindBtnClick(View view) { Intent intent = new Intent(MainActivity.this, ExampleService.class); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } public void onUnbindBtnClick(View view) { if (serviceIsBound) { unbindService(serviceConnection); serviceIsBound = false; } } public void onStartBtnClick(View view) { Intent intent = new Intent(MainActivity.this, ExampleService.class); startService(intent); } public void onStopBtnClick(View view) { Intent intent = new Intent(MainActivity.this, ExampleService.class); exampleService.stopService(intent); } 

Sí, funciona. Quiero completar con un código de ejemplo:

Tuve que hacer una aplicación con un servicio iniciado por una actividad, la actividad tiene que llamar a algunos métodos en el servicio, el servicio tiene que correr en segundo plano incluso si la actividad se ha matado, y cuando la actividad se reinicia, no tiene que Reinicie el servicio si se está ejecutando. Espero que te ayude, puedes ver cómo funciona con el Registro. Así que ese es el código:

  public class MyActivity extends Activity{ private MyService myService; private boolean mIsBound = false; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder binder) { MyService.MyBinder b = (MyService.MyBinder) binder; myService = b.getService(); mIsBound = true //Do something // Here you can call : myService.aFonctionInMyService(); } public void onServiceDisconnected(ComponentName className) { // Do something mIsBound = false; } } protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); //Checked if my service is running if (!isMyServiceRunning()) { //if not, I start it. startService(new Intent(this,MyService.class)); } } private boolean isMyServiceRunning() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager .getRunningServices(Integer.MAX_VALUE)) { if (MyService.class.getName().equals( service.service.getClassName())) { return true; } } return false; } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); doBindService(); } //Connection to the Service private void doBindService() { bindService(new Intent(this,MyService.class), mConnection, Context.BIND_AUTO_CREATE); } // Disconnection from the service private void doUnbindService() { if (mIsBound) { // Detach our existing connection. unbindService(mConnection); } } @Override protected void onPause() { // TODO Auto-generated method stub doUnbindService(); super.onPause(); } } public class MyService extends Service{ public static String Tag = "MyService"; private final IBinder mBinder = new MyBinder(); @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.d(Tag, "onCreate()"); } public class MyBinder extends Binder { public LocationService getService() { return LocationService.this; } } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.d(Tag, "onBind()"); return mBinder; } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub Log.d(Tag, "onUnBind()"); return super.onUnbind(intent); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.d(Tag,"onStartCommand()"); return START_STICKY; } @Override public void onDestroy() { // TODO Auto-generated method stub Log.d(Tag, "onDestroy"); super.onDestroy(); } public void aFonctionInMyService(){ //Do Something } } 
  • ¿cuál es el mejor enfoque para escanear filesytem para archivos mp3 en android?
  • Llamar setVolumeControlStream desde un servicio
  • Diferencias entre intención y pendiente
  • Razones por las que la intención pasada sería NULL en onStartCommand
  • Servicio enlazado a BroadcastReceiver
  • El servicio de Android onStartCommand nunca se llama
  • Enviar datos de la actividad al servicio
  • ¿Cómo ejecuto un método de servicio periódicamente?
  • Context.getApplicationContext () devuelve null en un Service
  • Cómo supervisar el cambio de estado de SIM
  • Servicio de detector de balizas de estimación en segundo plano
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.