El proceso del servicio se cancela después de que la aplicación se elimina de la bandeja de aplicaciones

Estoy comenzando un servicio (o reiniciando el servicio en ejecución) cuando se inicia una actividad, usando:

Intent intent = new Intent(this, MyService.class); startService(intent);

Más tarde, en función de ciertas acciones, la misma actividad se une al servicio utilizando

 bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE); 

Y cuando la actividad se destruye, llamo

 unbindService(mConnection); 

Anteriormente, el servicio solía reiniciarse cuando eliminaba la misma actividad / aplicación de la bandeja de aplicaciones y mostraba el “mensaje 1 proceso 1 servicio en ejecución” en las aplicaciones en ejecución.

Ahora, el servicio no se reinicia al matar la misma actividad / aplicación.

Y recibo el mensaje “0 proceso 1 servicio en ejecución” , lo que significa que el servicio en realidad no se está ejecutando.

El servicio no se reinicia al cerrarse la aplicación. Mi aplicación consiste en una actividad. Además, el servicio se inicia con éxito cuando se inicia después de un arranque del sistema.

¿Por qué se mata el proceso del servicio cuando lo comienzo usando startService ()?

editar

El servicio solía reiniciar antes después de cerrar la aplicación desde la bandeja de la aplicación. Pero ahora de repente con el mismo código, no es así. Sucede con otras aplicaciones también cuando las cierro. p.ej.

enter image description here

Aquí hay una solución que encontré y funciona bien para reiniciar un servicio si su proceso se cancela al cerrar la aplicación. En su servicio, agregue el siguiente código.

Me encontré con esta solución en este hilo.

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

Parece ser un error que mata el proceso de la aplicación. No tiene sentido que un servicio se ejecute si se mata su proceso.

Tenga en cuenta que: onDestroy no siempre se llama. No deberías poner el código de esa manera.
Cuando la actividad forzada se cierra o cierra de manera anormal, onDestroy no recibe ninguna llamada.

Desafortunadamente, este es un problema complicado debido a la forma en que funciona Android. Hay una serie de estrategias que funcionan en torno a diferentes partes del problema. Para mejores resultados, combine varias estrategias juntas.

Tenga en cuenta que algunas de estas estrategias ya no son necesarias en las versiones de Android más recientes.

1. Comience una actividad

Qué hacer

Tomado del servicio de primer plano muerto al recibir la transmisión después de que la actividad desapareció en la lista de tareas :

En el servicio de primer plano:

  @Override public void onTaskRemoved( Intent rootIntent ) { Intent intent = new Intent( this, DummyActivity.class ); intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); startActivity( intent ); } 

En el manifiesto:

   

(Si su servicio se encuentra en un proceso diferente, establezca el proceso de esta actividad en el mismo).

En DummyActivity.java:

  public class DummyActivity extends Activity { @Override public void onCreate( Bundle icicle ) { super.onCreate( icicle ); finish(); } } 

Efectos secundarios

Hace que se cierre la actividad reciente. Normalmente, borrar una aplicación no cierra la actividad reciente.

Desventajas

Esto solo tiene efecto cuando se inicia la actividad ficticia , que puede demorar medio segundo o más, por lo que aún deja el servicio abierto para que se mate por un momento.

Explicación

Cuando elimina / desliza su aplicación, se establece una waitingToKill llamada waitingToKill . Mientras se establece esta marca, Android puede matar el proceso en cualquier momento en el futuro , como cuando recibe una transmisión . Comenzar una actividad borra esta bandera.

2. Spam un BroadcastReceiver con transmisiones en primer plano

Qué hacer

Combina esto en tu código de servicio:

 if (Build.VERSION.SDK_INT >= 16) { Intent intent = new Intent(this, DummyReceiver.class); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); //This seems to be timing-related; the more times we do this, //the less likely the process gets killed for (int i = 0; i < 50; ++i) sendBroadcast(intent); } 

Crear un receptor de difusión ficticio:

 public class DummyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) {} } 

Agregue el receptor a su manifiesto:

  

Efectos secundarios

Puede ocasionar un ligero retraso (~ 250 ms) cuando la tarea se elimina de la pantalla Recientes.

Desventajas

Esto solo mantiene vivo el proceso mientras recibe las transmisiones. la bandera de waitingToKill todavía está configurada , por lo que el proceso puede ser eliminado después, como cuando se recibe una transmisión.

Explicación

Si su proceso no se ejecuta en prioridad de primer plano, Android intentará eliminarlo inmediatamente . Recibir transmisiones en primer plano evita temporalmente esto, lo que da como resultado que se waitingToKill indicador waitingToKill .

3. No se una a los servicios

La vinculación a un servicio parece boost la probabilidad de que el proceso del servicio se elimine inmediatamente cuando se elimina una tarea.

Sé que esta pregunta es antigua, pero recientemente me encontré con este problema y de repente mi servicio se detuvo al cerrar la aplicación. Antes estaba funcionando bien. Este problema desperdició mi montón de tiempo. Para otros que tengan un problema similar, asegúrese de que SU RESTRICCIÓN DE DATOS DE ANTECEDENTES ESTÁ APAGADA. Este era el problema que tenía y, de hecho, tiene sentido, ya que cuando los datos de fondo son restringidos, el proceso en segundo plano no se ejecuta.

onDestroy no siempre se llama. El problema principal en su caso es que no puede iniciar el servicio cuando se cierra la aplicación, esa vez el sistema operativo Android ( en algunos sistemas operativos ) matará el servicio. Si no puede reiniciar el servicio, llame a un administrador de alarmas para iniciar el receptor como esta,

Manifiesto es,

        

IN Main Activty inicia el administrador de alarmas de esta manera,

 String alarm = Context.ALARM_SERVICE; AlarmManager am = (AlarmManager) getSystemService(alarm); Intent intent = new Intent("REFRESH_THIS"); PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0); int type = AlarmManager.RTC_WAKEUP; long interval = 1000 * 50; am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi); 

esto llamará a un receptor y un receptor es,

 public class AlarmReceiver extends BroadcastReceiver { Context context; @Override public void onReceive(Context context, Intent intent) { this.context = context; System.out.println("Alarma Reciver Called"); if (isMyServiceRunning(this.context, BackgroundService.class)) { System.out.println("alredy running no need to start again"); } else { Intent background = new Intent(context, BackgroundService.class); context.startService(background); } } public static boolean isMyServiceRunning(Context context, Class< ?> serviceClass) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List services = activityManager.getRunningServices(Integer.MAX_VALUE); if (services != null) { for (int i = 0; i < services.size(); i++) { if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) { return true; } } } return false; } } 

Y este receptor de Alaram llama una vez cuando se abre la aplicación de Android y cuando se cierra la aplicación. El servicio es así,

 public class BackgroundService extends Service { private String LOG_TAG = null; @Override public void onCreate() { super.onCreate(); LOG_TAG = "app_name"; Log.i(LOG_TAG, "service created"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(LOG_TAG, "In onStartCommand"); //ur actual code return START_STICKY; } @Override public IBinder onBind(Intent intent) { // Wont be called as service is not bound Log.i(LOG_TAG, "In onBind"); return null; } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); Log.i(LOG_TAG, "In onTaskRemoved"); } @Override public void onDestroy() { super.onDestroy(); Log.i(LOG_TAG, "In onDestroyed"); } } 

cuando no hay un enlace a un servicio o un primer plano bien establecido, el sistema de Android reconoce el servicio como un servicio de sobrecarga no utilizado que debe cerrarse. Esta es la mejor manera de mantener su servicio incluso si la aplicación está cerrada: AlarmManager o Servicio