Le Service Android S'Arrête Lorsque L'Application Est Fermée

je commence un service de mon activité principale Android comme suit:

final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);

lorsque je ferme la page d'activité en la glissant dans la liste des dernières applications, le service cesse de fonctionner et redémarre après un certain temps. Je ne peux pas utiliser les services persistants avec des notifications à cause de mes exigences d'application. Comment puis-je empêcher le redémarrage ou l'arrêt du service et continuer à fonctionner sur app exit?

61
demandé sur Bam 2013-05-20 17:49:48

13 réponses

je suis dans la même situation, jusqu'à présent j'ai appris quand l'application est fermée le service se fermer aussi parce qu'ils sont dans un fil, de sorte que le service devrait être sur un autre fil pour qu'il ne soit pas fermé, regarder dans ce domaine et regarder pour garder le service vivant avec alarm manager ici un exemple http://www.vogella.com/articles/AndroidServices/article.html de cette façon votre service ne sera pas affiché dans la notification.

enfin, après tout les recherches que j'ai faites, je commence à réaliser que le meilleur choix pour un service à long terme est startForeground() , parce qu'il est fait pour cela et le système traite réellement bien votre service.

35
répondu aljuaid86 2016-06-25 14:55:36

ce peut vous aider. Je me trompe peut-être, mais il me semble que c'est lié au retour de START_STICKY dans votre méthode onStartCommand() . Vous pouvez éviter que le service ne soit appelé de nouveau en retournant START_NOT_STICKY à la place.

12
répondu artex 2017-05-23 12:02:34

vous rendre ce service dans votre Mainifest

 <service
            android:name=".sys.service.youservice"
            android:exported="true"
        android:process=":ServiceProcess" />

alors votre service sera exécuté sur un autre processus appelé ServiceProcess


si vous voulez que votre service ne meurent jamais :

  1. onStartCommand() return START_STICKY

  2. onDestroy () - > startself

  3. créer un Service Deamon

  4. jin -> créer un Natif Démon processus, vous pouvez trouver certains projets open-source sur github

  5. startForeground (), Il ya un moyen de startForeground sans Notification, google it

11
répondu alanban 2016-07-22 08:26:06
Les Services

sont parfois assez compliqués.

Lorsque vous démarrez un service à partir d'une activité (ou de vos), le service est essentiellement le même processus.

citant les notes du développeur

la plus grande confusion au sujet de la classe de Service tourne en fait autour de ce qu'elle n'est pas:

Un Service n'est pas un processus distinct. L'objet de Service lui-même ne signifie pas qu'il est en cours d'exécution dans son propre processus; sauf indication contraire, il s'exécute dans le même processus que l'application dont il fait partie.

un Service n'est pas un fil. Il n'est pas un moyen lui-même de faire travailler hors du fil principal (pour éviter L'Application ne répond pas aux erreurs).

donc, ce que cela signifie est, si l'utilisateur glisse l'application loin des tâches récentes, il supprimera votre processus(ce qui inclut toutes vos activités, etc). Maintenant, permet de prendre trois scénarios.

première lorsque le service n'a pas de de notification de connaissances nouvelles.

dans ce cas votre procédé est tué avec votre service.

Second où le service a une notification de premier plan

Dans ce cas, le service n'est pas tué et le processus non plus

troisième scénario Si le service n'a pas de notification avant-plan, il peut continuer à fonctionner si l'application est fermée. Nous pouvons le faire en rendant le service exécuté dans un processus différent. (Cependant, j'ai entendu certaines personnes dire que cela pourrait ne pas fonctionner. à vous de l'essayer vous-même )

, vous pouvez créer un service dans un processus séparé par y compris le dessous de l'attribut dans votre manifeste.

android: process=": yourService "

ou

android:process=" yourService " le nom du processus doit commencer par des minuscules.

citant des notes de développeur

si le nom attribué à cet attribut commence par deux points ( ' :'), un nouveau processus, privé à la demande, est créé quand il est nécessaire et le service fonctionne dans ce processus. Si le nom du processus commence par un caractère minuscule , le service fonctionnera dans un processus global de ce nom, à condition qu'il ait la permission de le faire. Cela permet aux composants de différentes applications de partager un processus, réduisant ainsi l'utilisation des ressources.

c'est ce que j'ai compris, si quelqu'un est un expert, s'il vous plaît me corriger si je me trompe :)

3
répondu mmmcho 2017-08-31 19:10:56

essayez ceci, il va garder le service en cours d'exécution dans l'arrière-plan.

BackServices.classe

public class BackServices extends Service{

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      // Let it continue running until it is stopped.
      Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
      return START_STICKY;
   }
   @Override
   public void onDestroy() {
      super.onDestroy();
      Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
   }
}

dans votre activité principale onCreate supprimez cette ligne de code

startService(new Intent(getBaseContext(), BackServices.class));

maintenant le service va rester en cours d'exécution en arrière-plan.

2
répondu Youssef Al Subaihi 2016-12-13 08:36:27

le principal problème dans l'impossibilité de démarrer le service lorsque l'application est fermée,OS android( dans certains OS ) va tuer le service pour L'optimisation des ressources, si vous n'êtes pas en mesure de redémarrer le service puis appeler un gestionnaire d'alarme pour démarrer le reciver comme ceci,Voici le code entier,ce code va garder en vie votre service.

manifeste est,

         <service
            android:name=".BackgroundService"
            android:description="@string/app_name"
            android:enabled="true"
            android:label="Notification" />
        <receiver android:name="AlarmReceiver">
            <intent-filter>
                <action android:name="REFRESH_THIS" />
            </intent-filter>
        </receiver>

Activty début de l'alarme de manger de cette façon,

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

cela s'appellera reciver et reciver is,

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<ActivityManager.RunningServiceInfo> 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;
    }
}

et cet Alaram reciver appelle une fois quand l'application android est ouverte et quand l'application est fermée.Donc le service est comme ceci,

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");
    }
}
1
répondu Ajith K P 2017-01-17 07:10:00

la meilleure solution est d'utiliser l'Adaptateur sync dans android pour démarrer le service. Créez un adaptateur de synchronisation et appelez le service de démarrage.. intérieur de la méthode onPerformSync. pour créer un compte sync, référez-vous au lien https://developer.android.com/training/sync-adapters/index.html

Pourquoi SyncAdapter? Ans: parce que plus tôt vous aviez l'habitude de lancer le service en utilisant votre contexte D'application. donc, chaque fois que votre processus d'application se tuer (lorsque u le supprimer de la tâche gestionnaire ou OS tuer en raison du manque de ressources ) à ce moment-là votre service sera également supprimé. SyncAdapter ne fonctionnera pas dans le thread d'application.. donc, si u appel à l'intérieur.. service ne sera plus enlevé.. sauf si tu écris un code pour le supprimer.

1
répondu Nishanth S Babu 2017-07-06 08:08:03

utiliser le même processus pour le service et l'activité et START_STICKY ou START_REDELIVER_INTENT dans le service est le seul moyen d'être en mesure de redémarrer le service lorsque l'application redémarre, ce qui se produit lorsque l'utilisateur ferme l'application par exemple, mais aussi lorsque le système décide de la fermer pour des raisons d'optimisation. Vous ne pouvez pas avoir un service qui fonctionnera de façon permanente sans aucune interruption. C'est par conception, les smartphones ne sont pas faits pour exécuter des processus continus pour une longue période de temps. Cela est dû au fait que la durée de vie est la priorité la plus élevée. Vous devez concevoir votre service de sorte qu'il traite étant arrêté à tout moment.

1
répondu stef 2017-08-06 09:57:51

pourquoi ne pas utiliser un IntentService?

IntentService ouvre un nouveau fil en dehors du fil principal et fonctionne là, de cette façon la fermeture de l'effet de l'application il

soyez avisé que IntentService exécute le onHandleIntent() et quand son fait le service ferme, voir si elle répond à vos besoins. http://developer.android.com/reference/android/app/IntentService.html

0
répondu sharon gur 2015-05-31 09:02:36
<service android:name=".Service2"
            android:process="@string/app_name"
            android:exported="true"
            android:isolatedProcess="true"
            />

déclarez ceci dans votre manifeste. Donner un nom personnalisé à votre processus et que le processus isolé et exportés .

0
répondu Nishanth S Babu 2017-07-07 10:37:38

vous devez ajouter ce code dans votre classe de Service afin qu'il gère le cas lorsque votre processus est tué

 @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);
    }
0
répondu Kaustubh Bhagwat 2017-10-03 07:45:47

exécuter un service d'intention sera plus facile. Service dans la création d'un thread dans la demande, mais il est toujours dans l'application.

0
répondu Seb 2017-11-14 22:52:05

juste outrepasser la méthode onDestroy dans votre première activité visible comme après splash vous avez la page d'accueil et tout en redirigeant de splash à la page d'accueil vous avez déjà fini splash. mettez donc détruire en page d'accueil. et arrêter le service dans cette méthode.

-5
répondu user2689337 2016-01-18 10:30:43