Continuar servicio incluso si la aplicación se borra de la aplicación reciente

Estoy teniendo un pequeño problema.

En mi aplicación, un servicio se inicia luego de que el usuario inició sesión correctamente. Anteriormente, el servicio necesitaba detenerse si se mataba la aplicación. (por ejemplo, quitado de la lista de aplicaciones recientes deslizando). Así que habíamos usado android:stopWithTask="true" . Ahora necesitamos que el Servicio se ejecute tal como está, incluso si la Tarea que lo inició se elimina de la Lista de aplicaciones recientes. Así que cambié el Servicio para incluir android:stopWithTask="false" . Pero eso no parece funcionar.

Código relacionado:

Aquí está la parte manifiesta relacionada con el Servicio:

  

En MyService.java:

 public class MyService extends AbstractService { @Override public void onStartService() { Intent intent = new Intent(this, MyActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); Notification notification = new Notification(R.drawable.ic_launcher, "My network services", System.currentTimeMillis()); notification.setLatestEventInfo(this, "AppName", "Message", pendingIntent); startForeground(MY_NOTIFICATION_ID, notification); } @Override public void onTaskRemoved(Intent rootIntent) { Toast.makeText(getApplicationContext(), "onTaskRemoved called", Toast.LENGTH_LONG).show(); System.out.println("onTaskRemoved called"); super.onTaskRemoved(rootIntent); } } 

AbstractService.java es una clase personalizada que extiende Sevrice :

 public abstract class AbstractService extends Service { protected final String TAG = this.getClass().getName(); @Override public void onCreate() { super.onCreate(); onStartService(); Log.i(TAG, "onCreate(): Service Started."); } @Override public final int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStarCommand(): Received id " + startId + ": " + intent); return START_STICKY; // run until explicitly stopped. } @Override public final IBinder onBind(Intent intent) { return m_messenger.getBinder(); } @Override public void onDestroy() { super.onDestroy(); onStopService(); Log.i(TAG, "Service Stopped."); } public abstract void onStartService(); public abstract void onStopService(); public abstract void onReceiveMessage(Message msg); @Override public void onTaskRemoved(Intent rootIntent) { Toast.makeText(getApplicationContext(), "AS onTaskRemoved called", Toast.LENGTH_LONG).show(); super.onTaskRemoved(rootIntent); } } 

Ahora, si inicio sesión en la aplicación, se inicia MyService. Después de eso, presiono el botón de Inicio para que la aplicación se mueva a segundo plano. Ahora elimino la aplicación de la lista de aplicaciones recientes. En ese momento, debería ver el mensaje Toast y consola, según la descripción de este método:

public void onTaskRemoved (Intención rootIntent)

Agregado en el nivel de API 14

Esto se llama si el servicio se está ejecutando actualmente y el usuario ha eliminado una tarea que proviene de la aplicación del servicio. Si ha configurado ServiceInfo.FLAG_STOP_WITH_TASK, no recibirá esta callback; en cambio, el servicio simplemente se detendrá.

Parámetros rootIntent El Intento raíz original que se utilizó para iniciar la tarea que se está eliminando.

Pero no estoy viendo nada de eso. El servicio está devolviendo START_STICKY en onStartCommand , así que creo que onTaskRemoved debe onTaskRemoved junto con flag android:stopWithTask="false" .

¿Me estoy perdiendo algo?

Avíseme en caso de que necesite agregar algún código que pueda ser importante para descubrir qué está mal.

PD: He probado esto en 4.2.2 hasta ahora.

PD: Acabo de probar el mismo código en 4.1.2, en el que el Servicio se mantiene en ejecución, y también recibo el mensaje “onTaskRemoved called” en el registro.

¿Qué debo hacer para que esto funcione en todas las versiones?

Simplemente siga estos escenarios, su servicio y procesos (los hilos ejecutados dentro de su servicio) se mantendrán continuos.

  1. Cree un servicio y use START_STICKY como valor de retorno en el método onStartCommand como se muestra a continuación

      @Override public int onStartCommand(final Intent intent, final int flags, final int startId) { //your code return START_STICKY; } 
  2. El código anterior reiniciará el servicio si se destruye y se mantendrá siempre en ejecución, pero el proceso (subprocesos) que se ejecuta desde el servicio dejará de funcionar si la aplicación se elimina de las aplicaciones recientes. Para asegurarse de que sus procesos (subprocesos) permanezcan siempre en ejecución, debe sobrescribir el métodoTaskRemoved () y agregar código para reiniciar tareas como se muestra a continuación.

     @Override public void onTaskRemoved(Intent rootIntent){ Intent restartServiceTask = new Intent(getApplicationContext(),this.getClass()); restartServiceTask.setPackage(getPackageName()); PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartServiceTask, PendingIntent.FLAG_ONE_SHOT); AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); myAlarmService.set( AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartPendingIntent); super.onTaskRemoved(rootIntent); } 
  3. Comience el servicio como abajo

startService (nuevo Intent (this, YourService.class));

En su servicio, agregue el siguiente código. Me funciona bien en 4.4.2

Aquí hay una solución que encontré y funciona bien para reiniciar un servicio si su proceso se cancela al cerrar la aplicación.

  @Override public void onTaskRemoved(Intent rootIntent){ Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass()); PendingIntent restartServicePendingIntent = PendingIntent.getService( getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmService = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmService.set(ELAPSED_REALTIME, elapsedRealtime() + 1000, restartServicePendingIntent); super.onTaskRemoved(rootIntent); } 

Si se vincula a su servicio desde una subclase de la clase de aplicación y se aferra a su conexión de IBinder, el servicio permanecerá activo incluso después de que la aplicación se elimine de las aplicaciones recientes.

Parece que al eliminar una aplicación de las “tareas recientes” se elimina todo lo que se adjunta.

Tal vez deberías echarle un vistazo para encontrar una manera de reiniciar tu servicio si se detiene: https://stackoverflow.com/a/22464640/4232337

Escribe las 5 líneas que agregué en oncreate() de la clase de servicio

Me gusta esto:

 public class AlarmService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Intent iHeartBeatService = new Intent(AlarmService.this, AlarmService.class); PendingIntent piHeartBeatService = PendingIntent.getService(this, 0, iHeartBeatService, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(piHeartBeatService); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, piHeartBeatService); } } 

o

prueba este

 public class MyService extends Service{ @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); System.out.println("service created"); } @SuppressLint("NewApi") @Override public void onTaskRemoved(Intent rootIntent) { // TODO Auto-generated method stub System.out.println("onTaskRemoved"); super.onTaskRemoved(rootIntent); } @Override @Deprecated public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); System.out.println("Service started"); new Handler().postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub System.out.println("Service is running"); } }, 5000); } }