web-dev-qa-db-fra.com

Android 8.0 Oreo AlarmManager avec récepteur de diffusion et interdiction de diffusion implicite

J'ai des rappels critiques définis via le gestionnaire d'alarmes (il devrait fonctionner de la même manière qu'une application de réveil).

Auparavant, j'avais les éléments suivants dans mon Android Manifest:

    <receiver Android:name="com.example.app.AlarmReceiver" >
        <intent-filter>
            <action Android:name="${packageName}.alarm.action.trigger"/>
        </intent-filter>
    </receiver>

Le récepteur de diffusion:

public class AlarmReceiver extends BroadcastReceiver {

  @Override public void onReceive(
      final Context context,
      final Intent intent) {
// WAKE LOCK
// BUILD NOTIFICATION etc...
  }

}

Comment l'alarme est réglée:

final PendingIntent operation = PendingIntent.getBroadcast(
          mContext,
          requestCode,
          intent,
          PendingIntent.FLAG_CANCEL_CURRENT);

      if (PlatformUtils.hasMarshmallow()) {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);

      } else {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, operation);
      }
}

Avec Android 8.0 je ne peux plus utiliser une diffusion implicite telle que définie dans le manifeste. C'est bien, l'alternative donnée est de l'enregistrer manuellement comme ceci:

final BroadcastReceiver receiver = new AlarmReceiver();
final IntentFilter intentFilter = new IntentFilter(ALARM_RECEIVER_INTENT_TRIGGER);
context.registerReceiver(receiver, intentFilter);

Cela ne me semble pas logique.

  1. Le récepteur d'alarme sera lié à la durée de vie du contexte. Cela provoque un problème lorsque, par exemple, l'application est tuée en raison de la pression de la mémoire ou lorsque l'appareil est redémarré. J'ai besoin que mes alarmes se déclenchent à chaque fois car elles sont essentielles pour la santé de l'utilisateur.

  2. Même si j'écoute "Android.intent.action.BOOT_COMPLETED" et que j'enregistre mon récepteur d'alarme, l'application est tuée peu de temps après et aucune alarme n'est déclenchée. Je ne vois pas non plus mon alarme via

    adb Shell dumpsys alarm

Comment créer un récepteur de diffusion personnalisé qui reçoit une diffusion implicite pour déclencher une alarme tout en ciblant Android O (8.0)? Quelqu'un peut-il m'éclairer avec un exemple de code ou un lien vers la documentation. Comment fonctionne Timely ou toute autre fonction d'application de réveil tout en ciblant O?

12
ViciDroid

Révisez légèrement votre code pour rendre la diffusion explicite plutôt qu'implicite et tout ira bien (en supposant que this est une référence Activity ou une autre Context):

Intent intent = new Intent(ALARM_RECEIVER_INTENT_TRIGGER);
intent.setClass(this, AlarmReceiver.class);

La restriction dans Oreo est sur l'enregistrement implicite broadcast Intent, c'est-à-dire que vous lui envoyez des diffusions uniquement l'action, la catégorie ou les données spécifiées. Vous en faites une diffusion explicite en spécifiant la classe qui doit recevoir la diffusion.

25
Larry Schiefer

Si vous avez l'habitude de vérifier si l'alarme a déjà été enregistrée, n'oubliez pas de faire de même sur cette vérification:

public boolean isAlarmBroadcastRegistered(Context context, String action, Class clazz) {
    Intent intent = new Intent(action);
    intent.setClass(context, clazz);
    return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE) != null;
}
1
Cícero Moura