web-dev-qa-db-fra.com

Android Oreo JobIntentService Continuez à fonctionner en arrière-plan pour Android 7 et inférieur et se plantent souvent dans Android 8 et ci-dessus

J'ai récemment remplacé tous mes services de services de premier plan et JobIntentService, car il existe certaines limites d'exécution en arrière-plan ( https://developer.Android.com/about/versions/oreo/background ) dans OREO et les versions ultérieures. Conformément à la documentation, JobIntentService agit comme Intent Service pour Android 7 et versions antérieures et comme JobScheduler pour Android 8 et versions ultérieures. J'ai remarqué un problème dans le nouveau JobIntentService fourni par Google.

Android 8 et supérieur: 

Un crash se produit continuellement dans Android 8 et supérieur. Il y avait un ticket soulevé ici mentionnant à propos du même problème https://issuetracker.google.com/issues/63622293 et j'ai ajouté un correctif temporaire suggéré par quelques geeks. 

Android 7 & ci-dessous: JobIntentService qui agit comme si Intent Service n'était pas arrêté une fois le travail terminé.

J'ai implémenté JobIntentService dans un service qui se déclenche chaque fois qu'une action est effectuée par un utilisateur.

Code

public class SampleJobIntentService extends FixedJobIntentService {

public static void postData(Context context, String data) {
    Intent intent = new Intent(context, SampleJobIntentService.class);
            intent.setAction(INITIAL_ACTION);
            intent.putExtra(SAMPLE_ID, data);
            SampleJobIntentService.enqueueWork(context,intent);
}

public static void enqueueWork(Context context, Intent work) {
    SampleJobIntentService.enqueueWork(context, SampleJobIntentService.class, JOB_ID, work);

 @Override
    protected void onHandleWork(@NonNull Intent intent) {
        if (intent != null) {
            SampleRequest sampleRequest = requests.get(intent.getAction());
            if (sampleRequest != null) {
                try {
                   // perform some networking operations
                } catch (Exception ex) {
                    Log.d("Error for intent ");
                }
                Log.i("send action ");
            } else
                Log.e("action not found for ");
        }
    }
    }

Pour éviter le blocage avec JobIntentService, j'ai pris quelques références de https://issuetracker.google.com/issues/63622293

public abstract class FixedJobIntentService extends JobIntentService {

    @Override
    GenericWorkItem dequeueWork() {
        try {
            return new FixedGenericWorkItem(super.dequeueWork());
        } catch (SecurityException ignored) {
            doStopCurrentWork();
        }
        return null;
    }

    private class FixedGenericWorkItem implements GenericWorkItem {
        final GenericWorkItem mGenericWorkItem;

        FixedGenericWorkItem(GenericWorkItem genericWorkItem) {
            mGenericWorkItem = genericWorkItem;
        }

        @Override
        public Intent getIntent() {
            if (mGenericWorkItem != null) {
                return mGenericWorkItem.getIntent();
            }
            return null;
        }

        @Override
        public void complete() {
            try {
                if (mGenericWorkItem != null) {
                    mGenericWorkItem.complete();
                }
            } catch (IllegalArgumentException ignored) {
                doStopCurrentWork();
            }
        }
    }
}
3
Kalai.G

Eh bien ..., c'est beaucoup une grande théorie ... !! Il ne serait pas capable de tout mettre ici. Je ferai de mon mieux pour que vos concepts soient clairs.


J'ai déjà perdu mes deux années complètes dans la lecture de documentations sur Google ... Ce sont use-less... Avec no proper documentation et avec no proper sample codes for its developers .. !! Donc, je mentionne cela dans chacun de mes messages sur stack-overflow, car cela aidera à gagner du temps pour les autres .. !!


Il semble que vous soyez un bon programmeur. juste besoin de hints to your posted question:

Astuce-1:

VOUS: - J'ai récemment remplacé tous mes services de services de premier plan et JobIntentService

service de premier plan:  

Si vous avez besoin de ALL THE TIME RUNNING PROCESS; WHICH WILL NEVER END... ONCE IT IS STARTED, il est utilisé dans le service qui renvoie START_STICKY à partir de sa OnStartCommand. Encore une fois, il est déconseillé de l'utiliser comme si vous vouliez l'implémenter à tout prix ... vous devrez alors utiliser une notification avec setOngoing(true) Quel utilisateur final ne pourrait pas effacer votre notification, elle y restera indéfiniment .. ..

Utilisation du service de premier plan:  

Il y a eu aussi des restrictions sur les destinataires; ci-dessus Oreo et vous ne pouvez pas utiliser tous les destinataires et actions d'intention en le déclarant dans un manifeste et en créant simplement un destinataire ... Je vous conseille d'utiliser simplement la permission BootComplete et d'utiliser un seul receiver qui reçoit le boot_completed intention et appelle un service si en dessous de O et appelle un service de premier plan au-dessus de O. Maintenant, à partir de ce service de premier plan, vous implémentez les récepteurs d'exécution pour tous et annulez son enregistrement dans les méthodes Ondestroy. Je n'ai jamais trouvé d'exemple de code officiel pour la mise en œuvre du récepteur d'exécution et, finalement, je l'ai mis en œuvre avec succès depuis plusieurs mois. Oui, ce n'était pas un travail intelligent, car Google

Quand utiliser le service de premier plan:

Seulement si vous souhaitez implémenter des récepteurs de diffusion ... Si vous ne souhaitez implémenter aucun récepteur de diffusion; RESTE LOIN.......

Astuce-2:

VOUS: - J'ai récemment remplacé tous mes services de services de premier plan et JobIntentService

** le service a sa qualité de: ** 

Je viens juste de faire un travail minuscule ... et juste de sortir ... il faut le quitter par StopSelf()... Encore une fois, Services can cause data-loss s'il est appelé plusieurs fois ... Comme le même fil de service peut être exécuté plus d'une fois ... Encore une fois si vous voulez qu'un service fasse beaucoup de travail ... Utilisez START_STICKY... Mais encore une fois, ce n'est pas recommandé et je vous l'ai déjà suggéré, quand l'utiliser dans le conseil 1.

** Intentservice a sa qualité de: ** 

Si vous exécutez des tâches relativement longues et que vous avez property of execution serially only, si vous appelez encore et encore la même intentService, tous les appels seront conservés dans une queue et seront exécutés one by one après avoir terminé one by one. Ce qui n’est pas le cas dans le service décrit ci-dessus. Il se termine tout seul ... pas besoin de le terminer par un développeur .. !!

** Qualité unique de tous: ** 

Une fois qu’ils sont crashed, Android peut les empêcher d’appeler à l’avenir sans vous en avertir lors du blocage de l’application. Doit être manipulé avec try-catch-exception à avoid crash. Encore une fois ... Si you are implementing threads within services puis try-catch-exceptionwill not save your application from being crashing...

** ALORS CE QUE CELA ET COMMENT LE METTRE EN OEUVRE ALORS: **

Utilisez FireBaseJobScedular: - 

  1. Facile à utiliser
  2. Utilise JobService simple
  3. Peut exécuter des tâches de temps plus longues ou plus petites ... EVEN ALL THE TIME RUNNING TASK
  4. EVEN SUPPORTED BY NON STANDARD COMPANIES comme vivo, mi, oppo, one + 3, ... qui prend stock-Android le modifie et donne des noms tels que FunTouchOs, ColorOs, OxygenOs
  5. Il suffit de modifier les paramètres de la batterie pour "Ne pas optimiser cette application"
  6. Oui, google le soutient officiellement et recommande de l'utiliser
  7. Il crée l'instance de GooglePlyService et s'exécute à l'intérieur. De toute évidence, les entreprises non standard n'empêcheraient pas les applications Google de s'acquitter de leurs tâches.
  8. Fonctionne sur Oreo .., Même si je l’ai testé sur Android P et fonctionne sous Android version 5.0 en tant que tâches AlarmManager.
  9. Néanmoins, je recommande d’utiliser minsdk above 16, target sdk 26 comme si vous vouliez télécharger votre application sur google play, il est maintenant obligatoire et cette nouvelle aurait été entendue par vous. et compile sdk 26.
  10. Liez simplement votre JobService dans le manifeste et utilisez une permission de ligne unique de receive_boot_complete
  11. Il suffit de le programmer ... Et il démarrera sur tous les appareils disponibles sur le marché de tous les fabricants ... même sur cold boot et hot boot
  12. Il minimise beaucoup, beaucoup et beaucoup de code et you can focus on actual tasks.
  13. Une fois la tâche terminée, vous pouvez return false pour indiquer que la tâche est terminée et que le JobService sera terminé.

Pourquoi je suggère parce que je suis CTO d'une société bien -UNKNOwn et que j'ai été confronté aux problèmes causés par foreground service parmi les nombreux types de fabricants de téléphones Android ... Ce n'est pas le Apple and ios et nous avons dû le vivre. Je reste développeur depuis 18 ans et je code surtout aujourd'hui ... dans tous les projets de développement et leurs stratégies de développement sont uniquement conçues par moi.

Corrigez-moi ... aussi ... Comme vous n'avez pas mentionné what your tasks et project est lié à ... et à ce que vous voulez exactement faire en foreground service and intent-service... Faites-moi savoir ..., je me ferai un plaisir de vous aider. C’est une réponse théorique générale plutôt que ce que vous voulez .... Mais pour vous donner une réponse réelle, j’aurai besoin de la portée de votre projet.

5
sandhya sasane

JobIntentService qui agit comme si Intent Service n'était pas arrêté une fois le travail terminé

Le problème se situe dans votre méthode de classe de classe FixeJobIntentService dequeueWork.

Essayez de changer quelque chose comme ci-dessous

GenericWorkItem superValue = super.dequeueWork();
if (superValue != null) {
    return new FixedGenericWorkItem(superValue);
}
return null;

En regardant le code de JobIntentSerivce, la logique du processeur des éléments de travail est présentée ci-dessous, c'est-à-dire jusqu'à ce qu'il ne reste aucun élément de travail dans la file d'attente, tous les éléments sont traités (par exemple, onHandleWork est appelé pour chaque élément).

    while ((work = dequeueWork()) != null) {
        if (DEBUG) Log.d(TAG, "Processing next work: " + work);
        onHandleWork(work.getIntent());
        if (DEBUG) Log.d(TAG, "Completing work: " + work);
        work.complete();
    }

Dans votre implémentation, le problème survient après le traitement du premier élément de travail. Super.dequeueWork () renvoie null, dont vous ne vous occupez pas, et envoyez simplement un nouvel objet FixedGenericWorkItem en transmettant la valeur null. Vous remarquerez peut-être qu'une valeur null est transmise à votre onHandleWork lors de vos appels suivants.

J'espère que cela vous aidera à résoudre votre problème. 

0
pamradi

Je pense que vous avez juste besoin de ce code. Créez une nouvelle classe MyJobIntentService, écrivez cette partie du code et appelez postData () pour démarrer votre service.

public class MyJobIntentService extends JobIntentService {

public static void postData(Context context, String data) {
    final Intent intent = new Intent(context, MyJobIntentService.class);
    intent.setAction(INITIAL_ACTION);
    intent.putExtra(SAMPLE_ID, data);
    enqueueWork(context, MyJobIntentService.class, 1000, intent);
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onDestroy() {
    Ln.d("Cancelled service");
    super.onDestroy();
}

@Override
    protected void onHandleWork(@NonNull Intent intent) {
        if (intent != null) {
            final SampleRequest sampleRequest = requests.get(intent.getAction());
            if (sampleRequest != null) {
                try {
                   // perform some networking operations
                } catch (Exception ex) {
                    Log.d("Error for intent ");
                }
                Log.i("send action ");
            } else {                
               Log.e("action not found for ");
            }
        }
    }
}

Et assurez-vous d'ajouter votre service dans le fichier manifeste

<service
            Android:name="service.MyJobIntentService"
            Android:exported="false"
            Android:permission="Android.permission.BIND_JOB_SERVICE" />
0
Ankur