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?
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.
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 :
-
onStartCommand() return START_STICKY
-
onDestroy () - > startself
-
créer un Service Deamon
-
jin -> créer un Natif Démon processus, vous pouvez trouver certains projets open-source sur github
-
startForeground (), Il ya un moyen de startForeground sans Notification, google it
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 :)
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.
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");
}
}
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.
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.
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
<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 .
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);
}
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.
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.