¿Está el servicio de Android todavía vivo incluso después de que onDestroy () sea llamado?

Para estudiar el servicio de Android, escribí un programa de prueba que tiene tres botones "enlazar servicio", "desvincular servicio" y "enviar eco" en la pantalla. Cuando se hace clic, utilizan bindService() , unbindService() y un Messenger para comunicarse con el servicio.

Aquí están los códigos de servicio:

 public class MessengerService extends Service { private final Messenger mMessenger = new Messenger(new TempHandler()); private class TempHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(getApplicationContext(), "Hi, there.", Toast.LENGTH_SHORT).show(); break; case MSG_SAY_GOODBYE: Toast.makeText(getApplicationContext(), "See you next time.", Toast.LENGTH_SHORT).show(); break; case MSG_ECHO: Toast.makeText(getApplicationContext(), "Received " + msg.arg1 + " from client.", Toast.LENGTH_SHORT).show(); Messenger replyMessenger = msg.replyTo; Message replyMsg = Message.obtain(null, MSG_ECHO, msg.arg1, 0); try { replyMessenger.send(replyMsg); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } default: super.handleMessage(msg); } } } @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "Service bound", Toast.LENGTH_SHORT).show(); return mMessenger.getBinder(); } @Override public void onDestroy() { Log.d("", "Service.onDestroy()..."); super.onDestroy(); } } 

Y aquí está el código de la actividad:

 public class MessengerActivity extends Activity { private Messenger mMessengerService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity2); Button bind = (Button) findViewById(R.id.button5); bind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doBindService(); } }); Button unbind = (Button) findViewById(R.id.button6); unbind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doUnbindService(); } }); Button echo = (Button) findViewById(R.id.button7); echo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doSendEcho(); } }); } private void doBindService() { Intent intent = new Intent(getApplicationContext(), MessengerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } private void doUnbindService() { Message msg = Message.obtain(null, MessengerService.MSG_SAY_GOODBYE); try { mMessengerService.send(msg); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } unbindService(mConnection); } private void doSendEcho() { if (mMessengerService != null) { Message msg = Message.obtain(null, MessengerService.MSG_ECHO, 12345, 0); msg.replyTo = mMessenger; try { mMessengerService.send(msg); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private final Messenger mMessenger = new Messenger(new TempHandler()); private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Toast.makeText(getApplicationContext(), "Service is connected.", Toast.LENGTH_SHORT).show(); mMessengerService = new Messenger(service); Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO); try { mMessengerService.send(msg); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mMessengerService = null; Toast.makeText(getApplicationContext(), "Service is disconnected.", Toast.LENGTH_SHORT).show(); } }; private class TempHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MessengerService.MSG_ECHO: Toast.makeText(getApplicationContext(), "Get the echo message (" + msg.arg1 + ")", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } } 

Cuando hago clic en "enlazar servicio" y "enviar eco" botón. Puedo ver que el servicio está conectado y la comunicación del mensaje es buena. Y luego haga clic en "unbind service", vi el servicio onDestroy() ser llamado, por lo que espero que el servicio se detiene y no debe responder al mensaje que viene de nuevo. Pero en realidad es, el servicio parece estar vivo y podría obtener el mensaje de eco de nuevo cuando haga clic en el botón "enviar eco". Así que me pregunto ¿hay algo que hice incorrecto? ¿O tal vez no entiendo completamente el servicio?

Espero que alguien pueda ayudar, gracias.

Un servicio está "enlazado" cuando un componente de aplicación se une a él llamando a bindService() . Un servicio enlazado ofrece una interfaz cliente-servidor que permite a los componentes interactuar con el servicio, enviar solicitudes, obtener resultados e incluso hacerlo a través de procesos con comunicación interproceso (IPC). Un servicio enlazado se ejecuta sólo siempre y cuando otro componente de aplicación esté vinculado a él .

http://developer.android.com/guide/components/services.html

Un servicio se cerrará después de que todas las llamadas de bindService() hayan tenido sus llamadas unbindService() correspondientes. Si no hay clientes vinculados, el servicio también necesitará stopService () si y sólo si alguien llama a startService () en el servicio.

Dibujo del siguiente enlace.

¿Cómo comprobar si un servicio se está ejecutando en Android? .

 private void doSendEcho() { if(isMyServiceRunning()) // if service is running { if (mMessengerService != null) { Message msg = Message.obtain(null, MessengerService.MSG_ECHO, 12345, 0); msg.replyTo = mMessenger; try { mMessengerService.send(msg); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } private boolean isMyServiceRunning() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (MessengerService.class.getName().equals(service.service.getClassName())) { return true; } } return false; } @Override protected void onStop() { super.onStop(); // Unbind from the service unbindService(mConnection); Log.i("Stopped!",""+isMyServiceRunning()); Log.i("stopped", "Service Stopped"); } 

Ejemplo:

He probado el siguiente funciona bien.

 public class MessengerService extends Service { public static final int MSG_SAY_HELLO =1; public static final int MSG_SAY_GOODBYE =2; ArrayList<Messenger> mClients = new ArrayList<Messenger>(); private final Messenger mMessenger = new Messenger(new TempHandler()); private class TempHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: mClients.add(msg.replyTo); Toast.makeText(getApplicationContext(), "Hi, there.", Toast.LENGTH_SHORT).show(); break; case MSG_SAY_GOODBYE: mClients.add(msg.replyTo); break; default: super.handleMessage(msg); } } } @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "Service bound", Toast.LENGTH_SHORT).show(); return mMessenger.getBinder(); } @Override public void onDestroy() { Log.i("MessengerService", "Service Destroyed..."); super.onDestroy(); } } 

MainAactivity.java

 public class MainActivity extends Activity { boolean mIsBound=false; Messenger mService = null; private boolean isMyServiceRunning() { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (MessengerService.class.getName().equals(service.service.getClassName())) { return true; } } return false; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button bind = (Button) findViewById(R.id.button1); bind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doBindService(); } }); Button unbind = (Button) findViewById(R.id.button2); unbind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doUnbindService(); } }); } class TempHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MessengerService.MSG_SAY_GOODBYE: Toast.makeText(MainActivity.this,"Received from service: " + msg.arg1,1000).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ final Messenger mMessenger = new Messenger(new TempHandler()); /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the service object we can use to // interact with the service. We are communicating with our // service through an IDL interface, so get a client-side // representation of that from the raw service object. mService = new Messenger(service); // mCallbackText.setText("Attached."); // We want to monitor the service for as long as we are // connected to it. try { Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO); msg.replyTo = mMessenger; mService.send(msg); // Give it some value as an example. // msg = Message.obtain(null, // MessengerService.MSG_E, this.hashCode(), 0); // mService.send(msg); } catch (RemoteException e) { // In this case the service has crashed before we could even // do anything with it; we can count on soon being // disconnected (and then reconnected if it can be restarted) // so there is no need to do anything here. } // As part of the sample, tell the user what happened. Toast.makeText(MainActivity.this, "remote_service_connected", Toast.LENGTH_SHORT).show(); } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; // mCallbackText.setText("Disconnected."); // As part of the sample, tell the" user what happened. Toast.makeText(MainActivity.this, "remote_service_disconnected", Toast.LENGTH_SHORT).show(); } }; void doBindService() { // Establish a connection with the service. We use an explicit // class name because there is no reason to be able to let other // applications replace our component. bindService(new Intent(MainActivity.this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); mIsBound=true; Toast.makeText(MainActivity.this, "Binding",1000).show(); } void doUnbindService() { if (mIsBound) { // If we have received the service, and hence registered with // it, then now is the time to unregister. if (mService != null) { try { Message msg = Message.obtain(null, MessengerService.MSG_SAY_GOODBYE); msg.replyTo = mMessenger; mService.send(msg); } catch (RemoteException e) { // There is nothing special we need to do if the service // has crashed. } } // Detach our existing connection. unbindService(mConnection); mIsBound = false; Toast.makeText(MainActivity.this, "UnBinding"+isMyServiceRunning(),1000).show(); } } } 

Este enlace ( ¿Necesito llamar a unbindService y stopService para los servicios de Android? ) Dice que debe llamar a stopService antes de unbindService.

Trata eso.

Desde http://developer.android.com/guide/components/services.html :

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.

Así que tienes que llamar a unBindService () y después de stopService ()

Yo personalmente encuentro la terminología / nomenclatura para ser insatisfactoria / engañosa. "OnDestroy" y "stopService" podrían entenderse mejor si se llaman "FlagForAndroidOSDestruction" y "FlagForAndroidStopService".

Si uno descarga / compila / ejecuta cualquiera de los siguientes ejemplos, se puede ver que incluso cuando el OnHandleIntent está terminado o stopService ha sido llamado, el proceso e incluso el servicio todavía puede colgar alrededor! Para ver esto, simplemente inicie los siguientes ejemplos y, a continuación, en su teléfono / tablet goto Configuración-> Aplicaciones-> Ejecución-> Mostrar servicios y configuraciones en ejecución-> Aplicaciones-> Ejecución-> Mostrar procesos en caché

Cuando vea esto, intente lanzar una tonelada de otras aplicaciones en el teléfono y ENTONCES usted verá Android destruyendo dicho servicio y proceso.

http://developer.android.com/guide/components/services.html#ExtendingIntentService

http://android-er.blogspot.com/2013/03/stop-intentservice.html

¿Cómo comprobar todos los servicios en ejecución en android?

Sí, esta es una conclusión extraída de los documentos oficiales :

Un servicio puede iniciarse y tener conexiones vinculadas a él. En tal caso, el sistema mantendrá el servicio funcionando siempre que se inicie o haya una o más conexiones con el indicador Context.BIND_AUTO_CREATE. Una vez que ninguna de estas situaciones se mantiene, el método onDestroy () del servicio es llamado y el servicio se termina de manera efectiva . Todas las operaciones de limpieza (detención de subprocesos, cancelación de registros de receptores) deben completarse al regresar de onDestroy ().

  • Cómo depurar dos procesos en Android?
  • ¿Cómo puedo guardar datos del servicio de Android?
  • ¿Cómo mantener un servicio ejecutándose en segundo plano incluso después de que el usuario abandone la aplicación?
  • No se pueden recibir las actualizaciones de ubicación de LocationClient después de que la pantalla se apagó
  • ¿Por qué el servicio Android falla con NullPointerException?
  • OnBind () en servicio siempre devuelve Falso - Android
  • Detectando Android L Battery Saver
  • Implementación de NotificationListenerService
  • Enviar datos de la actividad al servicio
  • Android Service está creando una y otra vez
  • ¿Cómo puedo saber si mi servicio ha iniciado
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.