¿Cómo podemos evitar que el sistema operativo mate a un servicio?

Estoy usando el Service en mi aplicación y debe ejecutarse hasta que se desinstale la aplicación, pero el problema es que el sistema operativo lo matará.

¿Cómo podemos evitar que sea asesinado por el sistema operativo? O si se mata, ¿podemos reiniciar ese servicio nuevamente mediante progtwigción?

Puede ejecutar el servicio en primer plano utilizando startForeground () .

Un servicio en primer plano es un servicio considerado como algo que el usuario conoce activamente y, por lo tanto, no es un candidato para que el sistema lo mate cuando queda poca memoria.

Pero tenga en cuenta que un servicio en primer plano debe proporcionar una notificación para la barra de estado ( lea aquí ), y que la notificación no puede ser descartada a menos que el servicio sea detenido o eliminado del primer plano.

Nota: Esto todavía no garantiza en forma absoluta que el servicio no se destruirá en condiciones de memoria extremadamente bajas. Solo hace menos probable que sea asesinado.

Me ha sorprendido recientemente el mismo problema que el suyo. Pero ahora, he encontrado una buena solución. En primer lugar, debe saber que, incluso su sistema operativo mató su servicio, el sistema operativo invocará el método onCreate de su servicio en poco tiempo. Así que puede hacer algo con el método onCreate de esta manera:

 @Override public void onCreate() { Log.d(LOGTAG, "NotificationService.onCreate()..."); //start this service from another class ServiceManager.startService(); } @Override public void onStart(Intent intent, int startId) { Log.d(LOGTAG, "onStart()..."); //some code of your service starting,such as establish a connection,create a TimerTask or something else } 

el contenido de “ServiceManager.startService ()” es:

 public static void startService() { Log.i(LOGTAG, "ServiceManager.startSerivce()..."); Intent intent = new Intent(NotificationService.class.getName()); context.startService(intent); } 

Sin embargo, esta solución solo está disponible para la situación de que su servicio sea asesinado por GC. A veces nuestro servicio podría ser eliminado por el usuario con el Administrador del progtwig. En esta situación, sus prosses serán asesinados, y su servicio nunca se volverá a instanciar. Entonces su servicio no puede ser reiniciado. Pero la buena noticia es que cuando el PM mata su servicio, llamará a su método onDestroy. Así que podemos hacer algo con ese método.

  @Override public void onDestroy() { Intent in = new Intent(); in.setAction("YouWillNeverKillMe"); sendBroadcast(in); Log.d(LOGTAG, "onDestroy()..."); } 

La cadena de “YouWillNeverKillMe” es una acción personalizada. Lo más importante de este método es, no agregue ningún código antes de enviar la transmisión. Como el sistema no esperará la finalización de onDestroy (), debe enviar la transmisión lo antes posible. Luego registre un receptor en manifast.xml:

       

Finalmente, cree un BroadcastReceiver e inicie su servicio en el método onReceive:

 @Override public void onReceive(Context context, Intent intent) { Log.d(LOGTAG, "ServeiceDestroy onReceive..."); Log.d(LOGTAG, "action:" + intent.getAction()); Log.d(LOGTAG, "ServeiceDestroy auto start service..."); ServiceManager.startService(); } 

Espero que esto sea útil para ti, y disculpa mi pobre inglés escrito.

Reemplazar el método onStartCommand() en su clase de servicio y simplemente devolver START_STICKY (como lo sugiere “No está en blanco”). Eso es todo lo que necesitas. Si el proceso que ejecuta su servicio es eliminado (por una condición de poca memoria, por ejemplo), el sistema Android lo reiniciará automáticamente (por lo general con un poco de retraso, como 5 segundos).

onStart() no usas onStart() como se sugiere en otra respuesta, está en desuso.

utilizar

 @Override public int onStartCommand(Intent intent, int flags, int startId) { //**Your code ** // We want this service to continue running until it is explicitly // stopped, so return sticky. return START_STICKY; } 

ref Documentación del ciclo de vida del servicio.

Editar método agregado

Encontré otra solución al problema que garantiza que su servicio estará siempre vivo. En mi caso, este esquema resuelve también el problema con FileObserver, que detiene el trabajo después de un período de tiempo.

  1. Use una actividad (StartServicesActivity) para iniciar el servicio (FileObserverService) como servicio de primer plano.
  2. Utilice la clase BroadcastReceiver (en el ejemplo CommonReceiver) para reiniciar su servicio en algunas situaciones especiales y en caso de que se haya cancelado.

Utilicé este código en mi aplicación “Email Photos Automatically” https://play.google.com/store/apps/details?id=com.alexpap.EmailPicturesFree

Aquí está la clase CommonReceiver.

 public class CommonReceiver extends BroadcastReceiver { public void onReceive(Context paramContext, Intent paramIntent) { paramContext.startService(new Intent(paramContext, FileObserverService.class)); } } 

Esta es su definición en AndroidManifest.xml justo antes de la etiqueta de cierre de la aplicación.

            

Comience el servicio en la actividad StartServicesActivity.

 Intent iFileObserver = new Intent(StartServicesActivity.this, FileObserverService.class); StartServicesActivity.this.startService(iFileObserver); 

Aquí está el método onStartCommand () del servicio.

 public int onStartCommand(Intent intent, int flags, int startId) { int res = super.onStartCommand(intent, flags, startId); /*** Put your code here ***/ startServiceForeground(intent, flags, startId); return Service.START_STICKY; } public int startServiceForeground(Intent intent, int flags, int startId) { Intent notificationIntent = new Intent(this, StartServicesActivity.class); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); Notification notification = new NotificationCompat.Builder(this) .setContentTitle("File Observer Service") .setContentIntent(pendingIntent) .setOngoing(true) .build(); startForeground(300, notification); return START_STICKY; } 

Probé este código usando la aplicación Task Killer, y cada vez que se cancelaba el servicio, se reiniciaba casi de inmediato (realiza onStartCommand ()). Se reinicia también cada vez que enciendes el teléfono y después de reiniciar. Uso este código en mi aplicación, que envía por correo electrónico cada imagen que toma con su teléfono para predefinir la lista de correos electrónicos. El correo electrónico de envío y la lista de correos electrónicos de recepción se configuran en otra actividad y se almacenan en Preferencias compartidas. Tomé alrededor de 100 fotos en varias horas y todas fueron enviadas correctamente para recibir correos electrónicos.

 @Override public void onDestroy() { super.onDestroy(); startService(new Intent(this, YourService.class)); } 

escriba el código anterior en su servicio y su servicio nunca se detendrá, incluso si el usuario desea destruirlo o si quieren matarlo, nunca lo matará hasta que su aplicación no se desinstale de su dispositivo

Puede intentar iniciar su servicio repetidamente, por ejemplo, cada 5 segundos. De esta forma, cuando su servicio se esté ejecutando, se ejecutará en StartTech () cada 5 segundos. Probé este esquema y es muy confiable, pero desafortunadamente aumenta un poco la sobrecarga del teléfono. Aquí está el código en su actividad donde comienza el servicio.

 Intent iFileObserver = new Intent(StartServicesActivity.this, FileObserverService.class); PendingIntent pendingIntentFileObserver = PendingIntent.getService(StartServicesActivity.this, 0, iFileObserver, 0); AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE); Date now = new Date(); //start every 5 seconds alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, now.getTime(), 5*1000, pendingIntentFileObserver); 

Y aquí está onStartCommand () del servicio.

 //class variable public static boolean isStarted = false; public int onStartCommand(Intent intent, int flags, int startId) { int res = super.onStartCommand(intent, flags, startId); //check if your service is already started if (isStarted){ //yes - do nothing return Service.START_STICKY; } else { //no isStarted = true; } /**** the rest of your code ***/ return Service.START_STICKY; } 

Hasta donde sé, se onDestroy() solo cuando el servicio se detenga explícitamente (Force Stop). Pero no se llamará a este método en caso de que el servicio sea aniquilado por OS / deslizando la lista de Aplicaciones Recientes. En esos casos, se llama a otro controlador de eventos llamado onTaskRemoved(Intent) . Esto se debe a un defecto en Android 4.3-4.4 según el enlace aquí . Intenta usar el siguiente código: –

 public void onTaskRemoved(Intent intent){ super.onTaskRemoved(intent); Intent intent=new Intent(this,this.getClass()); startService(intent); } 

Primero crea el servicio en otro proceso y escribe una emisora ​​que se ejecuta en recursión en intervalos de tiempo

 protected CountDownTimer rebootService = new CountDownTimer(9000, 9000) { @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { sendBroadcast(reboot); this.start(); Log.d(TAG, "rebootService sending PREVENT AUTOREBOT broadcast"); } }; 

Después de eso, registre el receptor de difusión en el proceso principal también con la recursión del temporizador que se inicia después de que llegó la primera transmisión del servicio.

 protected static class ServiceAutoRebooter extends BroadcastReceiver { private static ServiceAutoRebooter instance = null; private RebootTimer rebootTimer = null; private static ServiceAutoRebooter getInstance() { if (instance == null) { instance = new ServiceAutoRebooter(); } return instance; } public class RebootTimer extends CountDownTimer { private Context _context; private Intent _service; public RebootTimer(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { _context.startService(_service); this.cancel(); Log.d(TAG, "Service AutoRebooted"); } } @Override public void onReceive(Context context, Intent intent) { if (rebootTimer == null) { Log.d(TAG, "rebootTimer == null"); rebootTimer = new RebootTimer(10000, 10000); rebootTimer._context = context; Intent service = new Intent(context, SomeService.class); rebootTimer._service = service; rebootTimer.start(); } else { rebootTimer.cancel(); rebootTimer.start(); Log.d(TAG, "rebootTimer is restarted"); } } } 

El servicio será reiniciado automáticamente si el tiempo en RebootTimer (proceso principal) expira, lo que significa que la transmisión “PREVENIR AUTOREBOT” del servicio no ha llegado

encontré una solución …. respuesta tardía pero quería responder …

podemos enviar una transmisión en el ondestroy del servicio y crear un receptor que reciba la transmisión y vuelva a iniciar el servicio … cuando se destruya por alguna razón …

pls intente seguir:

 final Messenger mMessenger = new Messenger(new IncomingHandler()); class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { default: super.handleMessage(msg); } } } @Override public void onCreate() { super.onCreate(); makeServiceForeground(); } @Override public IBinder onBind(Intent arg0) { return mMessenger.getBinder(); } private void makeServiceForeground() { IActivityManager am = ActivityManagerNative.getDefault(); try { am.setProcessForeground(onBind(null), android.os.Process.myPid(), true); } catch (RemoteException e) { Log.e("", "cant set to foreground" + e.toString()); } } 

también es necesario agregar en manifest.xml