web-dev-qa-db-fra.com

Android AlarmManager.setExactAndAllowWhileIdle () et WakefulBroadcastReceiver Ne fonctionne pas dans certains nouveaux appareils fabriqués et à bas prix

Je pense que cette question est posée à plusieurs reprises dans stackoverflow mais encore tant de gens ont du mal à la résoudre.

Dans mon Android je dois réveiller l'appareil toutes les demi-heures pour obtenir l'emplacement actuel et l'envoyer au serveur. Pour cela, j'ai utilisé AlarmManager avec setExactAndAllowWhileIdle() méthode et WakefulBroadcastReceiver. Cela fonctionne très bien dans presque tous les appareils standard/populaires comme samsung, LG (Nexus), Sony, Panasonic, lenovo, Motorola, Micro max et ainsi de suite .... Mais certains autres appareils la plupart des appareils en Chine ne prennent pas en charge ou ne permettent pas le réveil de l'appareil du mode somnolence avec setExactAndAllowWhileIdle(). Je l'ai testé dans leeco letV (Android OS 6.1) appareil qui ne permet pas au gestionnaire d'alarmes de se réveiller à un intervalle spécifique.

Ma portion de code que j'ai mentionnée ci-dessous:

UserTrackingReceiverIntentService.Java

public class UserTrackingReceiverIntentService extends IntentService {

    public static final String TAG = "UserTrackingReceiverIntentService";
    Context context;
    public UserTrackingReceiverIntentService() {
        super("UserTrackingReceiverIntentService");
    }

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onHandleIntent(Intent intent) {
        this.context = this;

        if (!Util.isMyServiceRunning(LocationService.class, context)) {
            context.startService(new Intent(context, LocationService.class));
        }

        Calendar calendar = Calendar.getInstance();
        //********************************** SETTING NEXT ALARM *********************************************
            Intent intentWakeFullBroacastReceiver = new Intent(context, SimpleWakefulReceiver.class);
            PendingIntent sender = PendingIntent.getBroadcast(context, 1001, intentWakeFullBroacastReceiver, 0);
            AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);

        if (calendar.get(Calendar.MINUTE) >= 0 && calendar.get(Calendar.MINUTE) < 30) {
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
            calendar.set(Calendar.MINUTE, 30);
            calendar.set(Calendar.SECOND, 0);
        } else if (calendar.get(Calendar.MINUTE) >= 30) {
            if (calendar.get(Calendar.HOUR_OF_DAY) == 23) {
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            } else {
                calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1);
            }
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        } else {
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
        }

        //Marshmallow OR ABOVE
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
                    calendar.getTimeInMillis(), sender);
        }
        //Lollipop 21 OR ABOVE
        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
            AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(calendar.getTimeInMillis(), sender);
            alarmManager.setAlarmClock(alarmClockInfo, sender);
        }
        //KitKat 19 OR ABOVE
        else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat) {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP,
                    calendar.getTimeInMillis(), sender);
        }
        //FOR BELOW KitKat ALL DEVICES
        else {
            alarmManager.set(AlarmManager.RTC_WAKEUP,
                    calendar.getTimeInMillis(), sender);
        }


        Util.registerHeartbeatReceiver(context);
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }
}

Chaque fois au-dessus du service, régler l'alarme suivante après 30 minutes une fois qu'il a appelé.

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Calendar calendar = Calendar.getInstance();
        Intent service = new Intent(context, UserTrackingReceiverIntentService.class);
        Date date = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        String DateTime = sdf.format(date);
        DateTime = Util.locatToUTC(DateTime);
        service.putExtra("date", String.valueOf(DateTime));

        String latitude = Util.ReadSharePrefrence(context, "track_lat");
        String longitude = Util.ReadSharePrefrence(context, "track_lng");

        service.putExtra("lat", latitude);
        service.putExtra("lon", longitude);

        Log.i("SimpleWakefulReceiver", "Starting service @ " + calendar.get(Calendar.HOUR_OF_DAY) + " : " + calendar.get(Calendar.MINUTE) + " : " + calendar.get(Calendar.SECOND));

        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, service);
    }
}

Comme j'ai modifié manuellement certains paramètres de leeco letV appareil comme Paramètres> Batterie> Aligner le réveil> Désactivé les deux options. S'il a activé la batterie, il peut ignorer les réveils forcés des applications.

Mes questions:

  1. Que s'est-il passé dans ce genre d'appareils? Pourquoi ne permettent-ils pas que l'alarme se déclenche dans un intervalle de temps spécifique?

  2. Dans certains appareils comme Gionee s plus l'alarme se déclenche 2 à 3 minutes en retard ... pourquoi?

  3. Android.net.conn.CONNECTIVITY_CHANGE récepteur large diffusion à écouter lorsque la connectivité réseau change ... Que faire quand il ne fonctionne pas sur certains appareils comme Gionee s plus?

  4. Il existe de nombreuses variantes pour le réglage de l'optimisation de la batterie pour différents fabricants .... Est-ce que cela peut nuire aux services d'arrière-plan de notre application si c'est la solution à cela.

25
himCream

Salut, j'ai le même problème lors des tests dans Xiomi phone.leeco, je n'ai pas beaucoup d'idée. Le téléphone Xiomi a son propre système d'exploitation qui est MIUI.Lorsque nous avons effacé RAM il efface toutes les applications sauf certaines applications inscrivez-vous dans le système d'exploitation. Comme Whatsapp et facebook quelques autres applications célèbres.

J'ai essayé le service, le gestionnaire d'alarmes et le planificateur, mais sans succès.

Ils fournissent un moyen spécifique pour exécuter les services manuellement. J'ai vérifié Leeco qu'il utilisait Android OS.

Solution pour MIUI 7.0 => Sécurité => Démarrage automatique => sélectionnez les applications que vous souhaitez exécuter en arrière-plan => Redémarrer Après le redémarrage, votre appareil devrait pouvoir s'exécuter vos services d'application en arrière-plan comme les autres Android le font.

paramètres MIUI 4.

Description détaillée de MIUI AutoStart

Selon moi, vous pouvez essayer avec les services puis vérifier si cela fonctionne ou non.

Merci, j'espère que vous obtiendrez un peu d'aide.

3
Saveen

Ces téléphones chinois ont probablement désactivé le réveil de l'application pour recevoir des événements d'alarme afin de préserver la durée de vie de la batterie. Je sais que certains fabricants chinois ne réveillent pas l'application pour recevoir des notifications Push si elles sont fermées plus tôt pour économiser la batterie. Ainsi, jusqu'à ce que l'application soit rouverte manuellement, elle ne sera réveillée par le système d'exploitation pour aucun traitement d'événement.

Cependant, ce comportement peut être modifié. Vérifiez les paramètres de gestion de l'alimentation et modifiez-les en conséquence pour permettre aux applications d'être réveillées à intervalles réguliers ou en cas de besoin. Je pense que cela pourrait être Mode restreint ou quelque chose de similaire.

2
Vikram Rao

Dans mon Android, je dois réactiver l'appareil toutes les 15 minutes pour obtenir l'emplacement actuel et l'envoyer au serveur. Application flow diagram Je l'ai testé sur Xiaomi Mi 5s (Android 6.0.1). Lorsque je ferme l'application, l'application se met en veille :( AlarmManager avec setExactAndAllowWhileIdle() ne fonctionne pas ¯\_(ツ)_/¯

Oui, cela fonctionne très bien dans presque tous les appareils standard/populaires comme Samsung, LG (Nexus 5X), Sony, Motorola, Pixel ...

MA SOLUTION :

L'entrée manifeste pour chaque type d'élément composant - <activity>, <service>, <receiver>, et <provider> - prend en charge un Android:process attribut qui peut spécifier un processus dans lequel ce composant doit s'exécuter.

Vous devez ajouter cette chaîne Android:process=":service" dans votre AndroidManifest.xml

Comme ça:

... 

<receiver
    Android:name="your.full.packagename.MyWakefulReceiver"
    Android:process=":service"
    Android:enabled="true"/>

<service
    Android:name="your.full.packagename.MyLocationService"
    Android:process=":service"/>

<service
    Android:name="your.full.packagename.MySendService"
    Android:process=":service"
    Android:exported="false" />

...

J'ai testé cette solution sur Xiaomi Mi 5s. C'est du travail !!!

À mon humble avis, il semble que le firmware Xiaomi tue le processus principal chaque fois que l'utilisateur quitte l'application ...

2
Plo_Koon

Je suis d'accord avec toi. Mais je pense que vous devriez essayer avec JobScheduler une fois. Vous trouverez la documentation officielle https://developer.Android.com/reference/Android/app/job/JobScheduler.html Le meilleur exemple que je trouve https://github.com/googlesamples/Android-JobScheduler Je ne l'ai pas testé. Selon moi, vous devez essayer ceci.

[~ # ~] modifier [~ # ~]

Si vous souhaitez exécuter votre application en mode somnolence dans 6.0 ou version ultérieure, vous devez répertorier votre application dans la liste blanche

https://www.bignerdranch.com/blog/diving-into-doze-mode-for-developers/

https://developer.Android.com/training/monitoring-device-state/doze-standby.html

Imtiyaz

1
Imtiyaz Khalani