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
}
}