提前几分钟安排本地通知

Posted

技术标签:

【中文标题】提前几分钟安排本地通知【英文标题】:Scheduled a local notification some minutes early 【发布时间】:2020-11-25 05:23:55 【问题描述】:

这是祈祷时间本地通知。当它与祈祷时间相匹配时,我们会收到通知。 问题是,它总是迟到几分钟。 所以要克服想要提前一分钟通知。

StartNotificationreciever.class

for (int i=0; i<prayerNames.size(); i++)
                String prayerName = prayerNames.get(i);
                if (prayerName.equals("Fajr")) 
                    String time = prayerTimes.get(0);
                    String[] array = time.split(":");
                    int hour = Integer.parseInt(array[0]);
                    String timeMinuit = array[1];
                    String[] array2 = timeMinuit.split(" ");
                    int minuit = Integer.parseInt(array2[0]);
                    String finalNotificationText = "View namaz time in " + locality + " location - " + prayerTimes.get(0);
                    Calendar calNow = Calendar.getInstance();
                    Calendar calSet = (Calendar) calNow.clone();
                    calSet.set(Calendar.HOUR_OF_DAY, hour);
                    calSet.set(Calendar.MINUTE, minuit);
                    calSet.set(Calendar.SECOND, 0);
                    calSet.set(Calendar.MILLISECOND, 0);
                    calendars.add(calSet);
                    notificationTextArrayList.add(finalNotificationText);
                

NotificationReciever.Class

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 

                        NotificationChannel mChannelFajr = notificationManager.getNotificationChannel(FAJR_CHANNEL_ID);

                        if (mChannelFajr == null) 
                            mChannelFajr = new NotificationChannel(FAJR_CHANNEL_ID, fajrChannelName, importance);
                            mChannelFajr.setDescription(notificationText);
                            mChannelFajr.enableVibration(true);
                            mChannelFajr.enableLights(true);
                            mChannelFajr.setLockscreenVisibility(VISIBILITY_PUBLIC);
                            mChannelFajr.setSound(soundUri, audioAttributes);
                            notificationManager.createNotificationChannel(mChannelFajr);
                        

                        builder = new NotificationCompat.Builder(context, FAJR_CHANNEL_ID);

                        builder.setContentTitle("FAJR NAMAZ")  // required
                                .setSmallIcon(R.mipmap.ic_darshika_logo) // required
                                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
                                        R.mipmap.ic_darshika_logo))
                                .setContentText(notificationText) // required
                                .setDefaults(Notification.DEFAULT_ALL)
                                .setAutoCancel(true)
                                .setLights(Color.MAGENTA, 500, 500)
                                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                                .setSound(soundUri)
                                .setContentIntent(pendingIntent)
                                .setTicker(context.getString(R.string.app_name));

                     else 

                        builder = new NotificationCompat.Builder(context, FAJR_CHANNEL_ID);

                        builder.setContentTitle("FAJR NAMAZ")
                                .setSmallIcon(R.mipmap.ic_darshika_logo) // required
                                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
                                        R.mipmap.ic_darshika_logo))
                                .setContentText(notificationText)  // required
                                .setDefaults(Notification.DEFAULT_ALL)
                                .setAutoCancel(true)
                                .setSound(soundUri)
                                .setLights(Color.MAGENTA, 500, 500)
                                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                                .setContentIntent(pendingIntent)
                                .setTicker(context.getString(R.string.app_name))
                                .setPriority(Notification.PRIORITY_HIGH);
                    
                    notification = builder.build();
                    notificationManager.notify(0, notification);

这是生成通知的地方。

if (targetCal.getTimeInMillis()>System.currentTimeMillis()) 
                int requestCode = (i) * 100;
                Intent intent = new Intent(context, NotificationReceiver.class);
                intent.setAction("com.shiamomin.sjmmj.MY_NOTIFICATION");
                intent.putExtra("notificationText", finalNotificationText);
                intent.putExtra("requestCode", requestCode);
                intent.putExtra("notificationType", notificationType);
                Log.d("notificationType", String.valueOf(notificationType));
                // Loop counter `i` is used as a `requestCode`
                PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                        requestCode,
                        intent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
                AlarmManager mgrAlarm = (AlarmManager) context.getSystemService(ALARM_SERVICE);
                mgrAlarm.set(AlarmManager.RTC_WAKEUP,targetCal.getTimeInMillis(),
                        pendingIntent);
                Log.d("time", String.valueOf(mgrAlarm));


                Log.d("targetTime", String.valueOf(targetCal.getTime()));

                intentArray.add(pendingIntent);

我应该做些什么改变。

【问题讨论】:

不知道你为什么打电话给prayerTimes.get(0);,我想应该是prayerTimes.get(i); 我有一个祷告列表。我有 5 集 5 祈祷。所以我正在使用 for 循环。 for (int i=0; i @HB。嘿,我已经编辑了这个问题以便更好地理解。 String time = prayerTimes.get(0);的值是多少? @HB 字符串时间值 = 祈祷时间.get(0);在这种情况下是祈祷的时间是早上 5:44 【参考方案1】:

避免Calendar

好吧,我不做 android 编程,看来你没有真正提供足够的信息,但我可以告诉你这么多:可怕的 Calendar 类在几年前被现代 java 所取代。时间课。

要获取 JVM 当前默认时区的当前时刻,请使用 ZonedDateTime 并调用 now()

ZonedDateTime nowZdt = ZonedDateTime.now() ;  // Current moment as seen in the JVM’s current default time zone.

LocalTime 对象而不是文本形式跟踪您的时间值。

LocalTime localTime = LocalTime.of( 15 , 00 ) ;

将当前时刻调整为一天中的那个时间。

ZonedDateTime nextPrayerZdt = nowZdt.with( localTime ) ;

注意 java.time 使用immutable objects。我们不是更改(改变)原始对象,而是生成一个新对象,其值基于原始对象。

确保这个新的时刻在未来。

boolean isFuture = nextPrayerZdt.isAfter( nowZdt ) ;

如果您想提前几分钟,请减去。

ZonedDateTime beforeNextPrayerZdt = nextPrayerZdt.minusMinutes( 3 ) ;

并再次检查这是在未来。

boolean isFuture = beforeNextPrayerZdt.isAfter( nowZdt ) ;

在您必须与尚未更新到java.time 的旧代码交互的地方,您可以在旧类和现代类之间来回转换。寻找添加到旧类中的新 to…from… 方法——至少在常规 Java 中,我不了解 Android。见:

GregorianCalendar::toZonedDateTime GregorianCalendar.fromZonedDateTime

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time

从哪里获取 java.time 类?

Java SE 8Java SE 9Java SE 10Java SE 11 和更高版本 - 具有捆绑实现的标准 Java API 的一部分。 Java 9 带来了一些小功能和修复。 Java SE 6Java SE 7 大部分 java.time 功能在ThreeTen-Backport 中向后移植到 Java 6 和 7。 Android java.time 类的更高版本的 Android (26+) 捆绑实现。 对于早期的 Android (API desugaring 的进程带来了最初未内置于 Android 中的 subset of the java.time 功能。 如果脱糖不能满足您的需求,ThreeTenABP 项目会将ThreeTen-Backport(如上所述)适配到 Android。见How to use ThreeTenABP…

【讨论】:

谢谢您,非常感谢您教给我这个概念的方式。问题是应用程序处于最后阶段,因此很难在整个项目中将 Calendar 更改为 ZonedDateTime。 @MukhtarAli 在您必须与尚未更新到 java.time 的旧代码交互的地方,您可以在旧类和现代类之间来回转换。寻找添加到旧类中的新 to…from… 方法——至少在常规 Java 中,我不了解 Android。请参阅GregorianCalendar::toZonedDateTimeGregorianCalendar.fromZonedDateTime 哦。我得到了它 。我已经改变了事情。真的很高兴这个解决方案。谢谢先生。@Basil Bourque

以上是关于提前几分钟安排本地通知的主要内容,如果未能解决你的问题,请参考以下文章

如何安排本地通知不同的时间段?

如何安排本地通知

如何在 Flutter 中多次安排单个本地通知

如何为以下场景安排本地通知?

重复本地通知 iOS 10

如何在 Windows Phone 应用程序 8.1 rt 中安排本地通知?