web-dev-qa-db-fra.com

Comment envoyer des notifications sur Android à une heure précise?

Je souhaite notifier mon application à une heure précise. Dites tous les jours que je dois donner une notification à 7 heures du matin, même si l'application est fermée.

Comment puis-je faire ceci? Un tutoriel? Merci de mentionner le lien.

23
admin 7798

vous devez d'abord utiliser un récepteur large bande. et parce qu'un récepteur de diffusion ne fonctionne que pendant une courte période

à partir du Android blog du développeur. Lors du traitement d'une diffusion, l'application dispose d'un délai fixe (actuellement de 10 secondes) pour effectuer son travail. Si elle ne se termine pas dans ce délai , l'application est considérée comme se comportant mal, et son processus est immédiatement jeté dans l'état d'arrière-plan pour être supprimé pour la mémoire si nécessaire.

c'est une meilleure pratique d'utiliser également un service intentionnel ici, vous avez un exemple comment le faire.

c'est la classe des récepteurs de diffusion.

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        Intent intent1 = new Intent(context, MyNewIntentService.class);
        context.startService(intent1);
    }
}

et l'enregistrer dans le manifeste.

<receiver
    Android:name=".MyReceiver"
    Android:enabled="true"
    Android:exported="false" >
</receiver>

c'est la classe de service intentionnelle.

public class MyNewIntentService extends IntentService {
    private static final int NOTIFICATION_ID = 3;

    public MyNewIntentService() {
        super("MyNewIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Notification.Builder builder = new Notification.Builder(this);
            builder.setContentTitle("My Title");
            builder.setContentText("This is the Body");
            builder.setSmallIcon(R.drawable.whatever);
        Intent notifyIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 2, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        //to be able to launch your activity from the notification 
        builder.setContentIntent(pendingIntent);
        Notification notificationCompat = builder.build();
        NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        managerCompat.notify(NOTIFICATION_ID, notificationCompat);
    }
}

et l'enregistrer dans le manifeste.

<service
    Android:name=".MyNewIntentService"
    Android:exported="false" >
</service>

puis dans votre activité, réglez le gestionnaire d'alarmes pour démarrer le récepteur de diffusion à une heure spécifique et utilisez la méthode setRepeating AlarmManager pour le répéter, cet exemple ci-dessous le répétera tous les jours.

 Intent notifyIntent = new Intent(this,MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast
            (context, NOTIFICATION_REMINDER_NIGHT, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,  System.currentTimeMillis(),
            1000 * 60 * 60 * 24, pendingIntent);

j'espère que cela t'aidera.

26
Shia G

Une solution de la réponse acceptée ne fonctionnera pas correctement sur Android 8 Oreo (api niveau 26) et supérieur en raison des limites de service en arrière-plan ( https : //developer.Android.com/about/versions/oreo/background.html#services ) et provoquera une exception comme celle-ci lorsque l'application est en arrière-plan:

Java.lang.IllegalStateException: Not allowed to start service Intent xxx: app is in background

L'une des solutions possibles consiste à utiliser JobIntentService :

  1. étendez votre Service à partir de JobIntentService au lieu de IntentService et utilisez la méthode onHandleWork au lieu de onHandleIntent.

  2. ajouter Android:permission="Android.permission.BIND_JOB_SERVICE" à votre Service dans AndroidManifest.xml.

15
Vasily Kabunov

Vous pouvez utiliser AlarmManager pour régler l'alarme à une heure spécifiée

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (!prefs.getBoolean("firstTime", false)) {

    Intent alarmIntent = new Intent(this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);

    AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 7);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 1);

    manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, pendingIntent);

    SharedPreferences.Editor editor = prefs.edit();
    editor.putBoolean("firstTime", true);
    editor.apply();
}

J'ai utilisé SharedPreferences pour vérifier que ce n'est pas la première fois que vous exécutez l'application et si c'est le cas, vous définissez cette alarme sinon ne faites rien au lieu de réinitialiser l'alarme chaque fois que vous démarrez votre application.
Utilisez un BroadcastReceiver pour écouter quand l'alarme se produit

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // show toast
        Toast.makeText(context, "Alarm running", Toast.LENGTH_SHORT).show();
    }
}

Utilisez un autre récepteur pour écouter le démarrage de l'appareil afin de pouvoir réinitialiser l'alarme

public class DeviceBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("Android.intent.action.BOOT_COMPLETED")) {
            // on device boot compelete, reset the alarm
            Intent alarmIntent = new Intent(context, AlarmReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);

            AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            calendar.set(Calendar.HOUR_OF_DAY, 7);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 1);

            manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                    AlarmManager.INTERVAL_DAY, pendingIntent);
        }
    }
}

ajouter l'autorisation au manifeste

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

puis enregistrez vos récepteurs

<receiver Android:name=".DeviceBootReceiver">
    <intent-filter>
        <action Android:name="Android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
<receiver Android:name=".AlarmReceiver" />
10
SaNtoRiaN
  • Obtenez le service d'alarme du système.
  • Faites une intention en attente en passant le nom de la classe de récepteur de diffusion.
  • Créez un objet calendrier et réglez-le également à 8 h.
  • Vérifiez si l'heure actuelle est passée 8. Si oui, ajoutez-y un autre jour.
  • Appelez la méthode de répétition définie de la classe AlarmManager.

Exemple de code pour le même:

alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);   
alarmIntent = new Intent(context of current file, AlarmReceiver1.class); 
AlarmReceiver1 = broadcast receiver

    pendingIntent = PendingIntent.getBroadcast(  Menu.this, 0, alarmIntent, 
PendingIntent.FLAG_UPDATE_CURRENT);
    alarmIntent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
    alarmManager.cancel(pendingIntent);

    Calendar alarmStartTime = Calendar.getInstance();
    Calendar now = Calendar.getInstance();
    alarmStartTime.set(Calendar.HOUR_OF_DAY, 8);
    alarmStartTime.set(Calendar.MINUTE, 00);
    alarmStartTime.set(Calendar.SECOND, 0);
    if (now.after(alarmStartTime)) {
        Log.d("Hey","Added a day");
        alarmStartTime.add(Calendar.DATE, 1);
    }

     alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
alarmStartTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
     Log.d("Alarm","Alarms set for everyday 8 am.");

Venir à la classe de récepteur de diffusion. Vous devez enregistrer votre récepteur de diffusion dans le manifeste. Cela vous fera recevoir des événements d'horloge. Remplacez la méthode onReceive de ce récepteur de diffusion et faites-y une notification lui-même ou effectuez un service de création de notification distinct et créez et affichez votre notification là-bas.

L'extrait de code manifeste:

L'extrait de code du récepteur de diffusion:

public class AlarmReceiver1 extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
  Intent service1 = new Intent(context, NotificationService1.class);
service1.setData((Uri.parse("custom://"+System.currentTimeMillis())));
          context.startService(service1);
}

Extrait de code du service de création de notifications:

public class NotificationService1 extends IntentService{

private NotificationManager notificationManager;
private PendingIntent pendingIntent;
private static int NOTIFICATION_ID = 1;
Notification notification;
@Override
protected void onHandleIntent(Intent intent) {
Context context = this.getApplicationContext();
       notificationManager = 
(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent mIntent = new Intent(this, Activity to be opened after clicking on the 
notif);
        Bundle bundle = new Bundle(); 
        bundle.putString("test", "test");
        mIntent.putExtras(bundle);
        pendingIntent = PendingIntent.getActivity(context, 0, mIntent, 
PendingIntent.FLAG_UPDATE_CURRENT);     

        Resources res = this.getResources();
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
        notification = new NotificationCompat.Builder(this)
                    .setContentIntent(pendingIntent)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
                    .setTicker("ticker value")
                    .setAutoCancel(true)
                    .setPriority(8)
                    .setSound(soundUri)
                    .setContentTitle("Notif title")
                    .setContentText("Text").build();
        notification.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
        notification.defaults |= Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE;
        notification.ledARGB = 0xFFFFA500;
        notification.ledOnMS = 800;
        notification.ledOffMS = 1000;
        notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        notificationManager.notify(NOTIFICATION_ID, notification);
        Log.i("notif","Notifications sent.");

}

}
1
Vaibhav Rai