Android: maintenir en vie un service d’arrière-plan (prévention de la mort du processus)

J’ai un service qui est défini comme suit:

public class SleepAccelerometerService extends Service implements SensorEventListener 

Essentiellement, je crée une application qui surveille l’activité de l’accéléromètre pour diverses raisons pendant que l’utilisateur dort avec son téléphone / appareil sur le lit. C’est un service de longue durée qui NE DOIT PAS être tué pendant la nuit. En fonction du nombre d’applications d’arrière-plan et de processus périodiques intervenant pendant la nuit, Android arrête parfois mon processus, mettant ainsi fin à mon service. Exemple:

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

Je ne veux pas forcer l’utilisateur à avoir «SleepActivity» ou une autre activité dans mon application comme premier plan. Je ne peux pas faire fonctionner mon service périodiquement, car il intercepte constamment onSensorChanged.

Des conseils? le code source est ici: http://code.google.com/p/elecsortingcsleep/

Pour Android 2.0 ou version ultérieure, vous pouvez utiliser la méthode startForeground() pour démarrer votre service au premier plan.

La documentation dit ceci :

Un service démarré peut utiliser l’ startForeground(int, Notification) pour placer le service dans un état de premier plan, où le système considère qu’il s’agit de quelque chose dont l’utilisateur est activement conscient et qu’il n’est donc pas susceptible de tuer lorsqu’il manque de mémoire. (Il est toujours théoriquement possible que le service soit supprimé sous une pression de mémoire extrême de l’application de premier plan en cours, mais en pratique, cela ne devrait pas être un problème.)

Le but principal est que lorsque la destruction du service perturberait l’utilisateur, par exemple, la suppression d’un service de lecteur de musique arrêterait la lecture de musique.

Vous devez fournir une Notification à la méthode affichée dans la barre de notifications de la section En cours.

Lorsque vous liez votre service à l’activité avec BIND_AUTO_CREATE, votre service est tué juste après que votre activité a été détruite et non liée. Cela ne dépend pas de la manière dont vous avez implémenté votre méthode Services unBind qui sera toujours supprimée.

L’autre méthode consiste à démarrer votre méthode Service with startService à partir de votre activité. De cette façon, même si votre activité est détruite, votre service ne sera pas détruit ni même interrompu, mais vous devrez le mettre en pause / le détruire vous-même avec stopSelf / stopService, le cas échéant.

Comme Dave l’a déjà souligné , vous pouvez exécuter votre Service avec une priorité de premier plan. Mais cette pratique ne devrait être utilisée que lorsque cela est absolument nécessaire, c’est-à-dire lorsque cela pourrait causer une mauvaise expérience utilisateur si le Service était tué par Android. C’est ce que le “premier plan” signifie vraiment: votre application est en quelque sorte au premier plan et l’utilisateur le remarque immédiatement si elle est tuée (par exemple parce qu’elle a joué une chanson ou une vidéo).

Dans la plupart des cas, demander une priorité de premier plan pour votre service est contre-productif!

Pourquoi donc? Lorsque Android décide de tuer un Service , il le fait parce qu’il manque de ressources (généralement de la RAM). Sur la base des différentes classes de priorité, Android décide quels processus en cours d’exécution, et cela inclut les services, pour terminer afin de libérer des ressources. Il s’agit d’un processus sain que vous souhaitez que l’utilisateur ait une expérience fluide. Si vous demandez une priorité de premier plan, sans raison valable, pour éviter que votre service ne soit tué, cela entraînera probablement une mauvaise expérience utilisateur. Ou pouvez-vous garantir que votre service rest dans une consommation de ressources minimale et qu’il n’y a aucune fuite de mémoire? 1

Android fournit des services sécurisés pour marquer les services qui doivent être redémarrés après une période de grâce s’ils ont été tués. Ce redémarrage se produit généralement en quelques secondes.

Image que vous souhaitez écrire un client XMPP pour Android. Devriez-vous demander une priorité de premier plan pour le Service qui contient votre connexion XMPP? Absolument pas, il n’y a absolument aucune raison de le faire. Mais vous souhaitez utiliser START_STICKY comme indicateur de retour pour la méthode onStartCommand votre service. Alors que votre service est arrêté quand il y a une pression sur les ressources et redémarré une fois que la situation est revenue à la normale.

1 : Je suis presque sûr que de nombreuses applications Android présentent des memory leaks. C’est quelque chose dont le programmeur occasionnel (bureau) ne se soucie pas tant.

J’ai eu un problème similaire. Sur certains appareils, après un certain temps, Android tue mon service et même startForeground () n’aide pas. Et mon client n’aime pas ce problème. Ma solution consiste à utiliser la classe AlarmManager pour vérifier que le service est en cours d’exécution lorsque cela est nécessaire. J’utilise AlarmManager pour créer une sorte d’horloge de surveillance. Il vérifie de temps en temps si le service doit être exécuté et le redémarrer. Aussi, j’utilise SharedPreferences pour garder l’indicateur si le service doit être exécuté.

Création / rejet de mon horloge de surveillance:

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

Réception et traitement de l’intention à partir du temporisateur de surveillance:

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

En effet, j’utilise WakefulBroadcastReceiver au lieu de BroadcastReceiver . Je vous ai donné le code avec BroadcastReceiver juste pour le simplifier.

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

public static final int BIND_ABOVE_CLIENT – Ajouté dans l’ API niveau 14

Indicateur pour bindService(Intent, ServiceConnection, int) : indique que l’application cliente liée à ce service considère que le service est plus important que l’application elle-même. Lorsqu’elle est définie, la plate-forme essaie de faire en sorte que le killer hors mémoire supprime l’application avant qu’elle ne tue le service auquel elle est liée, bien que cela ne soit pas garanti.

Les autres indicateurs du même groupe sont: BIND_ADJUST_WITH_ACTIVITY, BIND_AUTO_CREATE, BIND_IMPORTANT, BIND_NOT_FOREGROUND, BIND_WAIVE_PRIORITY.

Notez que la signification de BIND_AUTO_CREATE a changé dans ICS, et que les anciennes applications qui ne spécifient pas BIND_AUTO_CREATE auront automatiquement les indicateurs BIND_WAIVE_PRIORITY et BIND_ADJUST_WITH_ACTIVITY .

Gardez votre empreinte de service réduite, cela réduit la probabilité de fermeture de votre application par Android. Vous ne pouvez pas l’empêcher d’être tué, car si vous le pouviez, les gens pourraient facilement créer des logiciels espions persistants.

Je travaille sur une application et je suis confronté au problème de la destruction de mon service par l’application. J’ai fait des recherches sur Google et j’ai constaté que je devais le faire en avant-plan. voici le code:

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

houblon ça peut aider !!!!