Je souhaite qu'un service s'exécute tout le temps dans mon application. Je souhaite donc le redémarrer même s’il est fermé de force par l’utilisateur. Il existe certainement un moyen de le faire en appliquant des applications comme Facebook (ce n'est pas fait avec la notification Push, Facebook redémarre son service même si Internet est désactivé).
Toute aide serait appréciée. Merci!
Tout d’abord, il est très mauvais modèle d’exécuter le service avec force contre la volonté de l’utilisateur.
Quoi qu'il en soit, vous pouvez le redémarrer en utilisant un BroadcastReceiver
qui gère la diffusion envoyée à partir de onDestroy()
de votre service.
StickyService.Java
public class StickyService extends Service
{
private static final String TAG = "StickyService";
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
sendBroadcast(new Intent("YouWillNeverKillMe"));
}
}
RestartServiceReceiver.Java
public class RestartServiceReceiver extends BroadcastReceiver
{
private static final String TAG = "RestartServiceReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "onReceive");
context.startService(new Intent(context.getApplicationContext(), StickyService.class));
}
}
Déclarez le fichier composants du manifeste:
<service Android:name=".StickyService" >
</service>
<receiver Android:name=".RestartServiceReceiver" >
<intent-filter>
<action Android:name="YouWillNeverKillMe" >
</action>
</intent-filter>
</receiver>
Démarrez le StickyService
dans un composant (c'est-à-dire Application
, Activity
, Fragment
):
startService(new Intent(this, StickyService.class));
OR
sendBroadcast(new Intent("YouWillNeverKillMe"));
Vous devez créer un sticky service
avec méthode onTaskRemoved
prioritaire, dans laquelle vous pouvez configurer un service d’alarme pour déclencher à nouveau votre code.
public class BackgroundService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onTaskRemoved(Intent rootIntent) {
//create an intent that you want to start again.
Intent intent = new Intent(getApplicationContext(), BackgroundService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
super.onTaskRemoved(rootIntent);
}
}
Également dans certains appareils comme Xiaomi, l'application Huwaei est fermée de force une fois qu'elle a été supprimée des applications récentes. En effet, les fabricants disposent de fonctionnalités de gestion des tâches qui améliorent les performances de la RAM/batterie.
Vous pouvez consulter ce lien pour plus d'informations: https://stackoverflow.com/a/41360159/2798289
Chaque fois qu'un service est tué, sa méthode onDestroy
est toujours appelée. Il est préférable d'utiliser BroadcastReceiver pour démarrer votre service lorsqu'il est supprimé.
Voici un exemple de code illustrant sa mise en oeuvre: -
@Override
public void onDestroy() {
Intent in = new Intent();
in.setAction("StartkilledService");
sendBroadcast(in);
Log.d("debug", "Service Killed");
}
Puis enregistrez un destinataire dans AndroidManifest.xml
: -
<receiver Android:name=".app.ServiceDestroyReceiver" >
<intent-filter>
<action Android:name="StartKilledService" >
</action>
</intent-filter>
</receiver>
Enfin, créez un BroadcastReceiver, et démarrez votre service avec la méthode onReceive
: -
@Override
public void onReceive(Context context, Intent intent) {
Log.d("debug", "ServeiceDestroy onReceive...");
Log.d("debug", "action:" + intent.getAction());
Log.d("debug", "Starting Service");
ServiceManager.startService();
}
J'espère que cela t'aides.
Selon le Android document
Starting from Android 3.1, the system's package manager keeps track of applications
that are in a stopped state and provides a means of controlling their launch from
background processes and other applications.
Note that an application's stopped state is not the same as an Activity's stopped
state. The system manages those two stopped states separately.
FLAG_INCLUDE_STOPPED_PACKAGES — Include intent filters of stopped applications in the
list of potential targets to resolve against.
FLAG_EXCLUDE_STOPPED_PACKAGES — Exclude intent filters of stopped applications from the
list of potential targets.
When neither or both of these flags is defined in an intent, the default behavior is to
include filters of stopped applications in the list of potential targets.
Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents.
It does this to prevent broadcasts from background services from inadvertently or
unnecessarily launching components of stopped applications. A background service
or application can override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES
flag to broadcast intents that should be allowed to activate stopped applications.
À l'arrêt forcé de l'application, Android supprimez simplement l'ID de processus. Aucun avertissement, des rappels sont donnés au service/aux activités. Selon le Android document, lorsque le L'application est tuée, il y a des chances qu'elle appelle onPause ().
Quand j'ai essayé dans mon application, même onPause () n'a pas été appelé. Je pense que le seul moyen est d'utiliser l'indicateur d'intention FLAG_INCLUDE_STOPPED_PACKAGES
Et de l'envoyer depuis une autre application.
sur la méthode startCommand du service, retournez START_STICKY. généralement, il demande au système d'exploitation de démarrer le service quand il est tué.
Si je comprends bien, cela n’est pas possible Android pour forcer la fermeture de l’application a été conçue pour permettre à l’utilisateur de se débarrasser des applications non souhaitées, de sorte qu’il n’autorise aucune activité jusqu’à ce que l’utilisateur redémarre l'une de ses activités.
Si la situation permet d'utiliser 'root', il est généralement possible d'appliquer le paradigme Humpty-Dumpty.
Votre application (1ère) installe une autre application (2e, prenant APK des actifs) et exécute le service de la 2e application. Le service de la 2e application se lie au premier service de l'application et se rétablit lorsqu'il est déconnecté. La 1ère application fait la même chose.
Bien sûr, cela ne va pas aider lorsque toutes les applications sont tuées par une application gratuite RAM ou similaire, mais lorsque Android tue l’une de ces deux applications, l’autre redémarre sa homologue.
La seule solution réelle pour maintenir les services en vie consiste à appeler Service.startForeground(...)
avec une notification fournie. Ce sera la seule solution valable. Les deux autres dépendront beaucoup de la manière dont Google modifiera le comportement de son système. Avec chaque mise à jour de l'API, Google pourrait empêcher tout piratage sur deux.
Cela permet également à l'utilisateur de savoir que votre application exécute une tâche en arrière-plan qui la maintiendra en vie et que l'utilisateur doit l'arrêter. Si vous donnez à l'utilisateur la possibilité de l'arrêter, cela fait partie de votre application.
void startForeground (int id, Notification notification)
Faites en sorte que ce service soit exécuté au premier plan, en fournissant la notification en cours à afficher à l'utilisateur lorsqu'il se trouve dans cet état. Par défaut, les services sont en arrière-plan, ce qui signifie que si le système doit les supprimer pour récupérer davantage de mémoire (par exemple, pour afficher une page volumineuse dans un navigateur Web), ils peuvent être supprimés sans trop de dégâts. Vous pouvez définir cet indicateur si la suppression de votre service perturberait l'utilisateur, par exemple si votre service effectuait la lecture de musique de fond, afin que l'utilisateur puisse remarquer si la lecture de leur musique était arrêtée.
Il existe une solution très astucieuse pour maintenir le service en marche même si vous forcez l’arrêter. Je ne le recommande pas, car cela va à l'encontre de la volonté de l'utilisateur. Vous pouvez définir un récepteur de diffusion pour qu'il reçoive une intention avec l'action X. Gestionnaire onStartCommand de votre service, diffusion X (si le service n'est pas encore démarré). sur le récepteur de diffusion à la réception de X, démarrez d’abord le service, puis attendez quelques minutes, puis rediffusez X.