studio programacion herramientas fundamentos con avanzado aplicaciones android android-service

programacion - manual de android en pdf



¿Cuándo se destruye un Servicio iniciado y vinculado? (3)

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

  • Si llama a startService (), entonces el servicio continuará ejecutándose a menos y hasta que llame a stopSerivce () (o stopSelf () desde dentro del servicio)
  • Si llama a bindService (), entonces el servicio continuará ejecutándose a menos y hasta que llame a unbindService ()
  • Por lo tanto, si llama tanto a startService () como a bindService (), entonces el servicio continuará funcionando hasta que llame tanto a stopService como a unbindService (). Ni por su cuenta detendrá el servicio.

Creó una actividad y servicio muy simple y ejecutó las siguientes secuencias de inicio / parada / enlace / desvinculación. Observé que las llamadas dieron los siguientes resultados.

ligar

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()

iniciar-enlazar-detener-desenlazar

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 puede ver, en cada caso en el que se llamaron tanto bind como start, el servicio siguió ejecutándose hasta que se llamó a desvincular y detener. La secuencia de desvinculación / parada 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); }

Estaba revisando 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 enlazar a un servicio que ya se inició con startService (). Por ejemplo, un servicio de música de fondo podría iniciarse llamando a startService () con un Intent que identifique la música que se reproducirá. Más tarde, posiblemente cuando el usuario quiera ejercer algún control sobre el reproductor u obtener información sobre la canción actual, una actividad puede vincularse al servicio llamando a bindService (). En casos como este, stopService () o stopSelf () no detiene el servicio hasta que todos los clientes se desvinculan.

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

Sin embargo, si elige implementar el método de devolución de llamada onStartCommand (), debe detener el servicio explícitamente, ya que ahora se considera que el servicio está 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 algún cliente.

Puede que sea yo, pero creo que las declaraciones son contradictorias. ¿Podría alguien aclarar ...?


En realidad, ambos párrafos se complementan entre sí (aunque su redacción puede ser errónea), y ambos párrafos son consistentes con la imagen de la documentación. Echemos un vistazo:

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

La quintaesencia es: si inicia un servicio, luego le enlaza un cliente, luego intenta detenerlo, el servicio no se detiene (se destruye) antes de que todos los clientes se desvinculen. El segundo párrafo no contradice, refina esta afirmación.

Sin embargo, si elige implementar el método de devolución de llamada onStartCommand (), debe detener el servicio explícitamente, ya que ahora se considera que el servicio está 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 algún cliente.

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


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 ejecutarse en segundo plano incluso si la actividad fue eliminada, 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 } }