web-dev-qa-db-fra.com

onTaskRemoved ne pas être appelé si l'activité démarrée par le service est supprimée

J'utilise oreo 8.1.0 . Je suis confronté à un problème étrange dont je ne trouve pas la solution sur stackoverflow, d’où l’écriture de cette question. Je connais une solution qui consiste à utiliser le service de premier plan, mais je ne trouve pas la notification conviviale dans le contexte de mon application.

Je vais décrire mon problème en utilisant deux cas.

Cas 1: Lorsque l’utilisateur ouvre mon application en cliquant sur l’icône et la supprime des applications récentes, le service redémarre automatiquement. C'est bon.

Cas 2: Ici, mon application est fermée et ne figure pas dans les applications récentes . Lorsqu'un utilisateur copie un texte, mon service démarre l'une des activités de mon application mais lorsqu'il le supprime des applications récentes, mon le service est arrêté définitivement.

Donc, mon problème réside dans le second cas, je ne veux pas que mon service soit tué. Même si ça tue, je veux que ça recommence.

J'ai essayé toutes les méthodes mentionnées sur le stackoverflow comme utiliser START_STICKY et onTaskRemoved mais je ne parviens pas à le faire fonctionner.

Même si j’ai essayé de supprimer mon activité chaque fois que l’utilisateur clique sur un bouton d’application récente et le supprime par programme des applications récentes, mais cela ne fonctionne pas non plus . .

Cette partie du code provient de l'activité qui s'ouvre lorsque l'utilisateur copie du texte. 

@Override
public void finish() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        super.finishAndRemoveTask();
    } else {
        super.finish();
    }

}

Cette partie du code provient du service qui démarre l'activité.

@Override
public void onTaskRemoved(Intent rootIntent){
    Log.d("testing 12","onTaskRemoved");
    Intent restartServiceTask = new Intent(getApplicationContext(),CBWatcherService.class);
    restartServiceTask.setPackage(getPackageName());
    PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartServiceTask, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(this.ALARM_SERVICE);
    myAlarmService.set(
            AlarmManager.ELAPSED_REALTIME,
            SystemClock.elapsedRealtime() + 1000,
            restartPendingIntent);

    super.onTaskRemoved(rootIntent);
}

@Override
public int onStartCommand(Intent intent,int flag,int startId){
    super.onStartCommand(intent, flag, startId);
    return START_STICKY;

}

EDIT 1
J'ai juste besoin du service pour rester en vie.Voici les choses qui ne gêneront pas l'expérience utilisateur dans mon cas d'application
1. Tuer l'activité vous-même par programme quand onPause est appelé pour que le service ne soit pas tué est acceptable si vous le réalisez
2. Afficher la notification pendant quelques secondes est acceptable
3. Le redémarrage du service est acceptable

9
royatirek

C’était le problème Chaque fois que mon service démarrait l’activité, son service était détruit après l’activité. 

Pourquoi onTaskRemoved ne fonctionnait pas?
Ce que je faisais ne fonctionnait pas parce que mon service était détruit et qu’il n’était donc pas actif d’écouter onTaskRemoved.

Comment je l'ai résolu?
La solution à ce problème consistait à mettre un contrôle dans l'activité (démarrée par le service) pour vérifier si le service était actif ou non. Comme dans mon cas, le service était en train d'être détruit. Par conséquent, je dois redémarrer le service si celui-ci n'est pas actif. 
Cela correspond même au modèle de conception OREO, car nous pouvons démarrer le service d’arrière-plan lorsque l’application est au premier plan et que le service reste actif même si l’activité est détruite.

Sur Oreo, le service est détruit après un certain temps, mais le problème est différent.

Plus d'informations

0
royatirek

Depuis Android Oreo, il existe un changement de paradigme visant à limiter l'exécution du service en arrière-plan. Il s'agissait d'une critique fréquente affectant la vie de la batterie, les performances et la sécurité. Comme indiqué dans les commentaires ci-dessus, il existe des approches alternatives telles que JobScheduler.

Le refactoring des services sur le modèle JobScheduler peut être très complexe. Je vous conseille de modifier votre IntentService en un JobintentService depuis la bibliothèque de support Android v4. Il utilise JobScheduler sur des cibles Oreo et ultérieures, mais rétablit la conception IntentService plus ancienne sur des périphériques plus anciens. Il vous suffit de remplacer votre remplacement de onHandleIntent par onHandleWork dans votre implémentation de service. 

Ajouter 

Android:permission="Android.permission.BIND_JOB_SERVICE"

à la déclaration de service dans votre AndroidManifest.xml. Il peut également être utile d’ajouter

 <uses-permission Android:name=”Android.permission.WAKE_LOCK” />

Mais en disant tout cela, en lisant votre question, il me semble que votre plainte fondamentale concerne la question esthétique des services de premier plan nécessitant une notification. À mon avis, votre solution consiste simplement à utiliser Context.startForegroundService ou à vous assurer que votre service est lié. Dans les deux cas, l'utilisateur que le service exécute utilise un contenu visible. Vous constaterez qu'il est difficile de subvertir les décisions de conception d'Android. mieux vaut l’accepter - ils veulent que vous montriez ces notifications à partir de maintenant. 

Quoi qu'il en soit, la mise à jour de votre code pour les nouvelles cibles Android est toujours une bonne pratique, même si vous ne pouvez pas complètement éviter ces icônes de notification. 

0
dr_g