2012-04-29 19 views
15

Tengo un escenario donde una actividad inicia un servicio invocando el método startService: tanto el Activity como el Service están en el mismo paquete. Luego, el servicio, de acuerdo con sus parámetros de configuración, podría iniciar una actividad (llamémoslo ExternalActivity) contenida en un paquete diferente: esta actividad enlaza el servicio a través de bindService; una vez que esta actividad ha terminado sus tareas, se llama al método de la siguiente manera unbindService ...Evitar que se destruya un servicio de Android después de desvincular

// method of ExternalActivity 
@Override 
public void onDestroy() { 
    super.onDestroy(); 
    unbindService(...); 
} 

Como consecuencia, el servicio también es destruido. ¿Existe la posibilidad de evitar la destrucción del servicio?

+0

Según la [guía dev] (http://developer.android.com/guide/topics/fundamentals/bound-services.html): * * Un servicio enlazado se destruye una vez que todos los clientes se desvinculan, a menos que el servicio también se haya iniciado. ** ¿Lo detiene manualmente en el método onUnbind()? – yorkw

+0

@yorkw: mi servicio no implementa el método 'onUnbind'. – enzom83

Respuesta

10

Como consecuencia, el servicio también se destruye.

Como yorkw explicó, un servicio se destruye sólo cuando tanto de lo siguiente es cierto:

  1. Todas las llamadas a bindService() han ido acompañados de las llamadas correspondientes a unbindService().

  2. Si alguien llama startService(), alguien también llamado stopService() o el servicio llamado stopSelf().

¿Existe la posibilidad de evitar la destrucción del servicio?

Encuentra un mejor momento para llamar al stopService() o stopSelf(), cualquiera de los que estés utilizando.

+1

Llamo manualmente 'stopService' solo cuando hago clic en un botón de la actividad que inicia el servicio. Sin embargo, el servicio se destruye cuando 'ExternalActivity' (la única aplicación que vincula el servicio) llama a' unbindService'. – enzom83

+0

@ enzom83: Entonces, está funcionando correctamente. ¡Estupendo! Es muy importante que su servicio se cierre cuando ya no sea necesario. Si el usuario presiona un botón específicamente para decir que ya no necesita el servicio, respete sus deseos. De lo contrario, te atacarán con asesinos de tareas y forzarán paradas desde Configuración, y no te gustará ese pedazo. – CommonsWare

+2

He solucionado el mal funcionamiento anulando el método 'onStartCommand', por lo que ahora devuelve' START_STICKY'. – enzom83

1

¿Qué tal esto?

public class MainActivity extends Activity { 

private LocalService mBoundService; 
private boolean mIsBound; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    if (LocalService.isRunning()) 
     doBindService(false); 

    Button startService = (Button) findViewById(R.id.startService); 
    startService.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      doBindService(true); 
     } 
    }); 
    Button stopService = (Button) findViewById(R.id.stopService); 
    stopService.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      doUnbindService(true); 
     } 
    }); 
} 

void doBindService(boolean start) { 

    Intent i = new Intent(this, LocalService.class); 
    if (start) 
     startService(i); 
    bindService(i, mConnection, Context.BIND_AUTO_CREATE); 

    mIsBound = true; 
} 

void doUnbindService(boolean stop) { 
    if (mIsBound) { 
     // Detach our existing connection. 
     unbindService(mConnection); 
     if (stop) 
      stopService(new Intent(this, LocalService.class)); 
     mIsBound = false; 
    } 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    doUnbindService(false); 
} 

private ServiceConnection mConnection = new ServiceConnection() { 
    public void onServiceConnected(ComponentName className, IBinder service) { 

     mBoundService = ((LocalService.LocalBinder) service).getService(); 

     // Tell the user about this for our demo. 
     Toast.makeText(MainActivity.this, R.string.local_service_connected, Toast.LENGTH_SHORT).show(); 
    } 

    public void onServiceDisconnected(ComponentName className) { 

     mBoundService = null; 
     Toast.makeText(MainActivity.this, R.string.local_service_disconnected, Toast.LENGTH_SHORT).show(); 
    } 
}; 

} 

LocalService.java de https://developer.android.com/reference/android/app/Service.html#LocalServiceSample

public class LocalService extends Service { 

... 
private static boolean isRunning=false; 
... 

@Override 
public void onCreate() { 
    mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 
    L.i("Service.onCreate() "); 
    // Display a notification about us starting. We put an icon in the status bar. 
    showNotification(); 
    isRunning = true; 

} 

@Override 
public void onDestroy() { 
    // Cancel the persistent notification. 
    mNM.cancel(NOTIFICATION); 
    isRunning = false; 
    // Tell the user we stopped. 
    Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show(); 
} 
... 

public static boolean isRunning() 
{ 
    return isRunning; 
} 
} 
Cuestiones relacionadas