Java 如何在Android中安排通知

Java 如何在Android中安排通知,java,android,notifications,android-notifications,Java,Android,Notifications,Android Notifications,我正在尝试为将来的某个时间设置通知。 我有创建通知的代码,但找不到安排通知的选项 如何安排通知?为此,您需要使用pendingent和BroadCastReceiver- public void scheduleNotification(Context context, long delay, int notificationId) {//delay is after how much time(in millis) from current time you want to schedule

我正在尝试为将来的某个时间设置通知。 我有创建通知的代码,但找不到安排通知的选项


如何安排通知?

为此,您需要使用
pendingent
BroadCastReceiver
-

public void scheduleNotification(Context context, long delay, int notificationId) {//delay is after how much time(in millis) from current time you want to schedule the notification
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                .setContentTitle(context.getString(R.string.title))
                .setContentText(context.getString(R.string.content))
                .setAutoCancel(true)
                .setSmallIcon(R.drawable.app_icon)
                .setLargeIcon(((BitmapDrawable) context.getResources().getDrawable(R.drawable.app_icon)).getBitmap())
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));

        Intent intent = new Intent(context, YourActivity.class);
        PendingIntent activity = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        builder.setContentIntent(activity);

        Notification notification = builder.build();

        Intent notificationIntent = new Intent(context, MyNotificationPublisher.class);
        notificationIntent.putExtra(MyNotificationPublisher.NOTIFICATION_ID, notificationId);
        notificationIntent.putExtra(MyNotificationPublisher.NOTIFICATION, notification);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        long futureInMillis = SystemClock.elapsedRealtime() + delay;
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, pendingIntent);
    }
此外,还需要在receiver类中显示通知-

public class MyNotificationPublisher extends BroadcastReceiver {

    public static String NOTIFICATION_ID = "notification_id";
    public static String NOTIFICATION = "notification";

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

        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        Notification notification = intent.getParcelableExtra(NOTIFICATION);
        int notificationId = intent.getIntExtra(NOTIFICATION_ID, 0);
        notificationManager.notify(notificationId, notification);
    }
}

最后,使用适当的参数调用
scheduleNotification()

不用于OREO+(编辑)

上面的答案是好的->强>但是不要考虑用户重新启动设备的潜力>(它清除了由ARMARM管理器调度的意图)。 您需要创建一个WakefulBroadcastReceiver,它将包含一个AlarmManager来计划交付一个PendingEvent。当WakefulBroadcastReceiver处理intent-post通知并向WakefulBroadcastReceiver发出完成的信号时

WakefulBroadcastReceiver

    /**
     * When the alarm fires, this WakefulBroadcastReceiver receives the broadcast Intent
     * and then posts the notification.
     */
    public class WakefulReceiver extends WakefulBroadcastReceiver {
        // provides access to the system alarm services.
        private AlarmManager mAlarmManager;

        public void onReceive(Context context, Intent intent) {
            //// TODO: post notification
            WakefulReceiver.completeWakefulIntent(intent);
        }

        /**
         * Sets the next alarm to run. When the alarm fires,
         * the app broadcasts an Intent to this WakefulBroadcastReceiver.
         * @param context the context of the app's Activity.
         */
        public void setAlarm(Context context) {
            mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, WakefulReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            //// TODO: use calendar.add(Calendar.SECOND,MINUTE,HOUR, int);
            //calendar.add(Calendar.SECOND, 10);

            //ALWAYS recompute the calendar after using add, set, roll
            Date date = calendar.getTime();

            mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, date.getTime(), alarmIntent);

            // Enable {@code BootReceiver} to automatically restart when the
            // device is rebooted.
            //// TODO: you may need to reference the context by ApplicationActivity.class
            ComponentName receiver = new ComponentName(context, BootReceiver.class);
            PackageManager pm = context.getPackageManager();
            pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                    PackageManager.DONT_KILL_APP);
        }

        /**
         * Cancels the next alarm from running. Removes any intents set by this
         * WakefulBroadcastReceiver.
         * @param context the context of the app's Activity
         */
        public void cancelAlarm(Context context) {
            Log.d("WakefulAlarmReceiver", "{cancelAlarm}");

            mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, WakefulReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

            mAlarmManager.cancel(alarmIntent);

            // Disable {@code BootReceiver} so that it doesn't automatically restart when the device is rebooted.
            //// TODO: you may need to reference the context by ApplicationActivity.class
            ComponentName receiver = new ComponentName(context, BootReceiver.class);
            PackageManager pm = context.getPackageManager();
            pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                    PackageManager.DONT_KILL_APP);
        }
    public class BootReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            context = ApplicationActivity.class;
            AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, WakefulReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            //// TODO: use calendar.add(Calendar.SECOND,MINUTE,HOUR, int);
            //calendar.add(Calendar.SECOND, 10);

            //ALWAYS recompute the calendar after using add, set, roll
            Date date = calendar.getTime();

            alarmManager.setExact(AlarmManager.RTC_WAKEUP, date.getTime(), alarmIntent);
            }
        }
    }
引导接收器

    /**
     * When the alarm fires, this WakefulBroadcastReceiver receives the broadcast Intent
     * and then posts the notification.
     */
    public class WakefulReceiver extends WakefulBroadcastReceiver {
        // provides access to the system alarm services.
        private AlarmManager mAlarmManager;

        public void onReceive(Context context, Intent intent) {
            //// TODO: post notification
            WakefulReceiver.completeWakefulIntent(intent);
        }

        /**
         * Sets the next alarm to run. When the alarm fires,
         * the app broadcasts an Intent to this WakefulBroadcastReceiver.
         * @param context the context of the app's Activity.
         */
        public void setAlarm(Context context) {
            mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, WakefulReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            //// TODO: use calendar.add(Calendar.SECOND,MINUTE,HOUR, int);
            //calendar.add(Calendar.SECOND, 10);

            //ALWAYS recompute the calendar after using add, set, roll
            Date date = calendar.getTime();

            mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, date.getTime(), alarmIntent);

            // Enable {@code BootReceiver} to automatically restart when the
            // device is rebooted.
            //// TODO: you may need to reference the context by ApplicationActivity.class
            ComponentName receiver = new ComponentName(context, BootReceiver.class);
            PackageManager pm = context.getPackageManager();
            pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                    PackageManager.DONT_KILL_APP);
        }

        /**
         * Cancels the next alarm from running. Removes any intents set by this
         * WakefulBroadcastReceiver.
         * @param context the context of the app's Activity
         */
        public void cancelAlarm(Context context) {
            Log.d("WakefulAlarmReceiver", "{cancelAlarm}");

            mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, WakefulReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

            mAlarmManager.cancel(alarmIntent);

            // Disable {@code BootReceiver} so that it doesn't automatically restart when the device is rebooted.
            //// TODO: you may need to reference the context by ApplicationActivity.class
            ComponentName receiver = new ComponentName(context, BootReceiver.class);
            PackageManager pm = context.getPackageManager();
            pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                    PackageManager.DONT_KILL_APP);
        }
    public class BootReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            context = ApplicationActivity.class;
            AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, WakefulReceiver.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            //// TODO: use calendar.add(Calendar.SECOND,MINUTE,HOUR, int);
            //calendar.add(Calendar.SECOND, 10);

            //ALWAYS recompute the calendar after using add, set, roll
            Date date = calendar.getTime();

            alarmManager.setExact(AlarmManager.RTC_WAKEUP, date.getTime(), alarmIntent);
            }
        }
    }
AndroidManifest.xml

<receiver android:name=".WakefulReceiver"/>

<receiver android:name=".BootReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>


例如,每天中午12点。。。这些代码是否进入主要活动?当应用程序在“最近的应用程序列表”中滑动时,此代码计划报警将被取消。你如何避免这个问题?似乎被接受的答案应该是下面阿佩尔索奇的答案。。如果手机重新启动,在没有保证在预定日期送达的情况下安排通知似乎相对无用。这个答案是不正确的,因为你是在把图像放在原意上。这是反模式的,可能会导致错误。请查看:将不起作用,除非您在AndroidManifest.xml
标记下添加以下内容。注意,MyNotificationPublisher.java在同一个文件夹中。这仍然很有用,因为另一个问题比这个问题早了3年,一些基本行为已经改变,所以谢谢!嘿,在
BootReceiver.class
上,你不应该手动键入“android.intent.action.BOOT\u COMPLETED”,而应该使用
intent.action\u BOOT\u COMPLETED
记住向清单文件中添加权限,因为android 8.0中不推荐使用此接收器。因此,此解决方案可能不适用于Android 8.0 Android 8 Oreo的解决方案似乎是扩展
BroadcastReceiver
,而不是
WakefulBroadcastReceiver
,请参见任何人是否可以编辑并解释为什么不应在SDK 26+中使用它?