Android: manteniendo vivo el servicio de fondo (evitando la muerte del proceso)

Tengo un servicio que se define como:

public class SleepAccelerometerService extends Service implements SensorEventListener 

Básicamente, estoy haciendo una aplicación que monitorea la actividad del acelerómetro por varias razones mientras el usuario duerme con su teléfono / dispositivo en la cama. Este es un servicio de larga duración que NO DEBE matarse durante la noche. Dependiendo de cuántas aplicaciones en segundo plano y procesos periódicos se producen durante la noche, a veces Android mata a mi proceso, lo que termina mi servicio. Ejemplo:

 10-04 03:27:41.673: INFO/ActivityManager(1269): Process com.androsz.electricsleep (pid 16223) has died. 10-04 03:27:41.681: INFO/WindowManager(1269): WIN DEATH: Window{45509f98 com.androsz.electricsleep/com.androsz.electricsleep.ui.SleepActivity paused=false} 

No quiero forzar al usuario a tener ‘SleepActivity’ u otra actividad en mi aplicación como primer plano. No puedo hacer que mi servicio se ejecute periódicamente, ya que está interceptando constantemente OnSensorChanged.

¿Algun consejo? El código fuente está aquí: http://code.google.com/p/electricsleep/

Para Android 2.0 o posterior, puede utilizar el método startForeground() para iniciar su Servicio en primer plano.

La documentación dice lo siguiente :

Un servicio iniciado puede usar la startForeground(int, Notification) para poner el servicio en un estado de primer plano, donde el sistema considera que es algo que el usuario conoce activamente y, por lo tanto, no es candidato para matar cuando tiene poca memoria. (Todavía es teóricamente posible que el servicio sea eliminado bajo la presión de memoria extrema de la aplicación de primer plano actual, pero en la práctica esto no debería ser una preocupación).

El objective principal es cuando matar el servicio sería perjudicial para el usuario, por ejemplo, matar un servicio de reproducción de música detendría la reproducción de música.

Tendrá que proporcionar una Notification para el método que se muestra en la Barra de notificaciones en la sección En curso.

Cuando vincula su Servicio a la Actividad con BIND_AUTO_CREATE, su servicio se destruye justo después de que su Actividad se Destruye y desata. No depende de cómo hayas implementado el método de desvinculación de servicios, aún se eliminará.

La otra forma es comenzar su Servicio con el método startService de su Actividad. De esta forma, incluso si se destruye tu actividad, tu servicio no se destruirá o incluso se detendrá, pero tienes que pausar / destruirlo por ti mismo con stopSelf / stopService cuando corresponda.

Como Dave ya señaló , podría ejecutar su Service con prioridad de primer plano. Pero esta práctica solo debe usarse cuando sea absolutamente necesario, es decir, cuando causaría una mala experiencia de usuario si el servicio fuera aniquilado por Android. Esto es lo que realmente significa el “primer plano”: su aplicación está de alguna manera en primer plano y el usuario lo notaría inmediatamente si se mata (por ejemplo, porque reproducía una canción o un video).

En la mayoría de los casos, ¡solicitar prioridad en primer plano para su Servicio es contraproducente!

¿Porqué es eso? Cuando Android decide matar un Service , lo hace porque le faltan recursos (normalmente RAM). En función de las diferentes clases de prioridad, Android decide qué procesos en ejecución, y esto incluye servicios, para finalizar con el fin de liberar recursos. Este es un proceso saludable que desea que suceda para que el usuario tenga una experiencia fluida. Si solicita prioridad en primer plano, sin una buena razón, solo para evitar que se mate su servicio, lo más probable es que cause una mala experiencia de usuario. ¿O puede garantizar que su servicio se mantenga dentro de un consumo mínimo de recursos y no tenga pérdidas de memoria? 1

Android proporciona servicios fijos para marcar los servicios que deben reiniciarse después de un período de gracia si son asesinados. Este reinicio generalmente ocurre dentro de unos segundos.

Imagen que desea escribir un cliente XMPP para Android. ¿Debería solicitar prioridad de primer plano para el Service que contiene su conexión XMPP? Definitivamente no, no hay absolutamente ninguna razón para hacerlo. Pero desea usar START_STICKY como indicador de devolución para el método onStartCommand su servicio. De modo que su servicio se detiene cuando hay presión de recursos y se reinicia una vez que la situación vuelve a la normalidad.

1 : estoy bastante seguro de que muchas aplicaciones de Android tienen pérdidas de memoria. Es algo que al progtwigdor casual (de escritorio) no le importa tanto.

Tuve un problema similar. En algunos dispositivos, después de un tiempo, Android mata mi servicio e incluso startForeground () no ayuda. Y a mi cliente no le gusta este problema. Mi solución es usar la clase AlarmManager para asegurarme de que el servicio se esté ejecutando cuando sea necesario. Uso AlarmManager para crear un tipo de temporizador de vigilancia. Comprueba de vez en cuando si el servicio debería estar ejecutándose y lo reinicia. También utilizo SharedPreferences para mantener el indicador de si el servicio se debe ejecutar.

Crear / descartar mi temporizador de vigilancia:

 void setServiceWatchdogTimer(boolean set, int timeout) { Intent intent; PendingIntent alarmIntent; intent = new Intent(); // forms and creates appropriate Intent and pass it to AlarmManager intent.setAction(ACTION_WATCHDOG_OF_SERVICE); intent.setClass(this, WatchDogServiceReceiver.class); alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager am=(AlarmManager)getSystemService(Context.ALARM_SERVICE); if(set) am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, alarmIntent); else am.cancel(alarmIntent); } 

Recibir y procesar la intención del temporizador de vigilancia:

 /** this class processes the intent and * checks whether the service should be running */ public static class WatchDogServiceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(ACTION_WATCHDOG_OF_SERVICE)) { // check your flag and // restart your service if it's necessary setServiceWatchdogTimer(true, 60000*5); // restart the watchdogtimer } } } 

De hecho, uso WakefulBroadcastReceiver en lugar de BroadcastReceiver . Te di el código con BroadcastReceiver solo para simplificarlo.

http://developer.android.com/reference/android/content/Context.html#BIND_ABOVE_CLIENT

public static final int BIND_ABOVE_CLIENT – Agregado en el nivel de API 14

Indicador para bindService(Intent, ServiceConnection, int) : indica que el enlace de la aplicación cliente a este servicio considera que el servicio es más importante que la aplicación en sí. Cuando se establezca, la plataforma intentará que el asesino sin memoria mate la aplicación antes de que mate el servicio al que está destinada, aunque no se garantiza que sea así.

Otros indicadores del mismo grupo son: BIND_ADJUST_WITH_ACTIVITY, BIND_AUTO_CREATE, BIND_IMPORTANT, BIND_NOT_FOREGROUND, BIND_WAIVE_PRIORITY.

Tenga en cuenta que el significado de BIND_AUTO_CREATE ha cambiado en ICS, y las aplicaciones antiguas que no especifican BIND_AUTO_CREATE tendrán automáticamente las banderas BIND_WAIVE_PRIORITY y BIND_ADJUST_WITH_ACTIVITY configuradas para ellas.

Mantenga su huella de servicio pequeña, esto reduce la probabilidad de que Android cierre su aplicación. No puedes evitar que se mate porque, si pudieras, las personas podrían crear fácilmente spyware persistente

Estoy trabajando en una aplicación y estoy enfrentando el problema de matar mi servicio al matar aplicaciones. Investigué en Google y descubrí que tengo que ponerlo en primer plano. siguiente es el código:

 public class UpdateLocationAndPrayerTimes extends Service { Context context; @Override public void onCreate() { super.onCreate(); context = this; } @Override public int onStartCommand(Intent intent, int flags, int startId) { StartForground(); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } private void StartForground() { LocationChangeDetector locationChangeDetector = new LocationChangeDetector(context); locationChangeDetector.getLatAndLong(); Notification notification = new NotificationCompat.Builder(this) .setOngoing(false) .setSmallIcon(android.R.color.transparent) //.setSmallIcon(R.drawable.picture) .build(); startForeground(101, notification); } } 

salta que puede ayudar !!!!