首页 > 解决方案 > calender.add 在 android 中无法正常运行

问题描述

我编写此代码的目的是确保我的应用程序将在特定时间通知用户,并且应用程序将从早上 7 点开始每天重复相同的通知。

但是,我尝试使用此功能(如下所示)。但它似乎不起作用。

日历。添加(日期,1)

实际上,我想生成一个自动通知。用药信息和每日重复次数为用户输入。

所以我想做的是 if 语句,它将比较当前时间是否在上午 7 点到晚上 8 点之间。

对于 else if,语句是比较当前时间是否在晚上 8 点之后,如果是,则日历将再增加 1 天。这样应用程序将在第二天早上 7 点弹出相同的通知。

而对于 else 语句是检查当前时间是否在早上 7 点之前。如果是,应用程序将在当前时间等于上午 7 点后立即弹出通知

但是 else if 语句没有像我预期的那样工作。我的意思是,如果我现在在晚上 10 点设置通知,应用程序将不会在第二天(早上 7 点)通知我。

所以,我想问一下你们是否可以帮助我修复我的代码,如下所示。if 和 else 段工作正常。但是 else if 语句似乎不起作用。

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

Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());

//repeat on 7am
calendar.set(Calendar.HOUR_OF_DAY, 7);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 0);

//check current hour
int timeOfDay = now.get(Calendar.HOUR_OF_DAY);

//to check if current hour is after 7pm
Calendar later = Calendar.getInstance();
later.set(Calendar.HOUR_OF_DAY, 20);
later.set(Calendar.MINUTE, 00);
later.set(Calendar.SECOND, 0);

if (timeOfDay >= 7 && timeOfDay <= 20) {
    //notification's process
}

else if (now.after(later)) {
        Log.d("Hey", "Added a day");
        calendar.add(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 7);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 0);

        this.context = context;
        prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
        nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notification = new NotificationCompat.Builder(context);
        name = prefs.getString("name" + count, "");
        hours = prefs.getInt("hora" + count, 8);
        minutes = prefs.getInt("minuto" + count, 0);


        Intent newIntentKill = new Intent(context, Broadcast.class);
        Bundle saco = new Bundle();
        saco.putInt("count", count);
        saco.putBoolean("shownBefore", true);
        newIntentKill.putExtras(saco);

        PendingIntent pendingIntentKill = PendingIntent.getBroadcast(context, count, newIntentKill, PendingIntent.FLAG_UPDATE_CURRENT);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
               alarmManager.setExact(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);

         } else {
               alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);
         }

            Log.d("Alarm", "Alarms set for everyday 7 am.");
    }

else {

    this.context = context;
    prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
    nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    notification = new NotificationCompat.Builder(context);
    name = prefs.getString("name" + count, "");
    hours = prefs.getInt("hora" + count, 8);
    minutes = prefs.getInt("minuto" + count, 0);


    Intent newIntentKill = new Intent(context, Broadcast.class);
    Bundle saco = new Bundle();
    saco.putInt("count", count);
    saco.putBoolean("shownBefore", true);
    newIntentKill.putExtras(saco);

    PendingIntent pendingIntentKill = PendingIntent.getBroadcast(context, count, newIntentKill, PendingIntent.FLAG_UPDATE_CURRENT);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
           alarmManager.setExact(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);

     } 
     else {
           alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);
         }

     Log.d("Alarm", "Alarms set for everyday 7 am.");
}

所以,提前感谢您的帮助。我真的很感激。

标签: javaandroidnotificationsalarmmanager

解决方案


java.time 和 ThreeTenABP

我建议使用现代 Java 日期和时间 API java.time 来进行日期和时间工作。它比旧的和设计不佳的类好得多,Calendar而且通常不会带来太多令人不快的惊喜。例如,您的 if/else 方案可能是这样的:

    ZoneId zone = ZoneId.systemDefault();
    ZonedDateTime nowZdt = ZonedDateTime.now(zone);
    LocalTime now = nowZdt.toLocalTime();
    if (now.isBefore(LocalTime.of(20, 0))) {
        if (now.isBefore(LocalTime.of(7, 0))) {
            // Set alarm for 7 today
            long alarmTimeMillis = nowZdt.with(LocalTime.of(7, 0))
                    .toInstant()
                    .toEpochMilli();
            // Set alarm
        } else { // between 7 AM and 8 PM
            // notification's process
        }
    } else { // after 8 PM
        // Set alarm for 7 AM tomorrow
        long alarmTimeMillis = nowZdt.plusDays(1)
                .with(LocalTime.of(7, 0))
                .toInstant()
                .toEpochMilli();
        // Set alarm
    }           

编辑:代码alarmTimeMillis中的两个地方是自警报纪元以来的毫秒数。您可以使用它来代替对和calendar.getTimeInMillis()的调用。alarmManager.set()alarmManager.setExact()

你的代码出了什么问题?

我不确定发生了什么。我能够发现的可能问题在这一行:

if (timeOfDay >= 7 && timeOfDay <= 20) {

您只是在比较一天中的时间,而您正在使用<=. 这意味着当时间是 20:something 时,直到 20:59(包括 20:59),条件为真。因此,在这种情况下,您不会进入要添加 1 天的分支。我不认为这是你的本意。

问题:java.time 不需要 Android API 级别 26 吗?

java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 开始)中,现代 API 是内置的。
  • 在非 Android Java 6 和 7 中获得 ThreeTen Backport,现代类的后向端口(ThreeTen 用于 JSR 310;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从org.threeten.bp子包中导入日期和时间类。

链接


推荐阅读