如何设置每月重复的闹钟?

8

我目前正在开发一个可以每月设置提醒的应用程序。但是,我无法为我的alarmmanager提供正确的重复间隔。请提供相关信息。 以下是我的代码,但它不会在二月或拥有30天的月份中触发提醒。同时,请提供设置年度重复提醒的代码。

repeatTime=(AlarmManager.INTERVAL_DAY*31);
mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, when.getTimeInMillis(), repeatTime, pi);

感谢您的来信,Sharath。

请点击此链接查看每月重复闹钟的相关内容这里 - mushahid
5个回答

9

以下是如何计算今天之后一个月的间隔时间,使用此逻辑每次触发闹钟时重置闹钟。例如,将闹钟设置为您想要开始的时间点,提供一些待处理的意图,一旦闹钟触发,请使用下面的代码获取下一个触发时间,并再次设置闹钟以在那个时间触发。

private long getDuration(){
    // get todays date
    Calendar cal = Calendar.getInstance();
    // get current month
    int currentMonth = cal.get(Calendar.MONTH);

    // move month ahead
    currentMonth++;
    // check if has not exceeded threshold of december

    if(currentMonth > Calendar.DECEMBER){
        // alright, reset month to jan and forward year by 1 e.g fro 2013 to 2014
        currentMonth = Calendar.JANUARY;
        // Move year ahead as well
        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR)+1);
    }

    // reset calendar to next month
    cal.set(Calendar.MONTH, currentMonth);
    // get the maximum possible days in this month
    int maximumDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);

    // set the calendar to maximum day (e.g in case of fEB 28th, or leap 29th)
    cal.set(Calendar.DAY_OF_MONTH, maximumDay);
    long thenTime = cal.getTimeInMillis(); // this is time one month ahead



    return (thenTime); // this is what you set as trigger point time i.e one month after

}

你好,感谢您的回复。我已经测试了将日期更改为下个月,它可以正常工作。但是我还有一个问题,每当我们重新启动模拟器时,它会为所有错过的警报触发警报。请问您如何实现仅为未触发的警报触发警报?谢谢,Sharath。 - sharath reddy
你可以在意图中提供一些数据,例如触发时间戳。一旦你的闹钟响起,你会在意图中收到相同的数据,通过这个你可以编写逻辑来检查是否有之前错过的闹钟,通过比较时间来判断。 - Techfist
目前我将提醒存储在数据库中。 但不确定如何避免产生重复的警报,请问您能否提供任何代码片段来解决这个问题。 谢谢, Sharath - sharath reddy
你能在这里发布你的代码吗,无论你尝试了什么。很抱歉,我需要知道你所讨论的上下文才能提供任何帮助。 - Techfist
这正是我一直在寻找的。我不知道如何恰当地表达处理每月30日设置闹钟,然后突然到了没有这个日期的二月份。 - Neon Warge
显示剩余4条评论

2

设置每月重复的闹钟:

        Calendar calender= Calendar.getInstance(TimeZone.getDefault());
        int cDay = calender.get(Calendar.DAY_OF_MONTH);

        calender.set(Calendar.HOUR_OF_DAY, hour); //hour you have selected
        calender.set(Calendar.MINUTE, min); //min you have selected
        calender.set(Calendar.SECOND, 0);
        calender.set(Calendar.MILLISECOND, 0);

        calender.set(Calendar.DATE, cDay);
        calender.get(Calendar.MONTH);

        Calendar now = Calendar.getInstance();
        now.set(Calendar.SECOND, 0);
        now.set(Calendar.MILLISECOND, 0);

        int days = now.getActualMaximum(Calendar.DAY_OF_MONTH);

        if (calender.before(now)) {  //this condition is used for future alarm only
            calender.add(Calendar.DATE, days);
        }

        final int _id = (int) System.currentTimeMillis();

        Intent i = new Intent(activity, YourServiceClass.class);
        i.putExtra("type", "month");

        PendingIntent displayIntent = PendingIntent.getBroadcast(
                activity, _id, i, PendingIntent.FLAG_UPDATE_CURRENT);

        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calender.getTimeInMillis(), AlarmManager.INTERVAL_DAY * calender.getActualMaximum(Calendar.DAY_OF_MONTH), displayIntent);

现在在你的服务类中,放置以下代码。
if (intent.getExtras() != null) {

        type = intent.getStringExtra("type");
    }

    if (type != null) {

        if (type.equals("month")) {

            Long futureTimeDifference = intent.getLongExtra("futureTimeDifference", 0); // Receive the time difference in milliseconds from currenttime in milliseconds and the future set date milliseconds
            futureTimeDifference = futureTimeDifference + System.currentTimeMillis();// get the next schedule date time inmilliseconds
            String repeatType = intent.getStringExtra("getRepeatType");// Receive the repeat type


            Date todaysDate = new Date();// initialize a new date object
            Calendar getCurrentDate = Calendar.getInstance();// Initialize a new Calendar object
            getCurrentDate.setTime(todaysDate); //Set the calendar to todays date
            int currentMonth = getCurrentDate.get(Calendar.MONTH); // Assign the current month in integer

            if (currentMonth == Calendar.JANUARY || currentMonth == Calendar.MARCH || currentMonth == Calendar.MAY || currentMonth == Calendar.JULY || currentMonth == Calendar.AUGUST || currentMonth == Calendar.OCTOBER || currentMonth == Calendar.DECEMBER) {
                futureTimeDifference = System.currentTimeMillis() + (AlarmManager.INTERVAL_DAY * 31);
            }
            if (currentMonth == Calendar.APRIL || currentMonth == Calendar.JUNE || currentMonth == Calendar.SEPTEMBER || currentMonth == Calendar.NOVEMBER) {
                futureTimeDifference = System.currentTimeMillis() + (AlarmManager.INTERVAL_DAY * 30);
            }

            if (currentMonth == Calendar.FEBRUARY) {//for february month)
                GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
                if (cal.isLeapYear(cal.get(Calendar.YEAR))) {//for leap year february month
                    futureTimeDifference = System.currentTimeMillis() + (AlarmManager.INTERVAL_DAY * 29);
                } else { //for non leap year february month
                    futureTimeDifference = System.currentTimeMillis() + (AlarmManager.INTERVAL_DAY * 28);
                }
            }

            final int monthly_id = (int) System.currentTimeMillis();

            Log.e("MonthlyNotification", futureTimeDifference + "");

            PendingIntent displayIntent = PendingIntent.getBroadcast(
                    context, monthly_id, intent, PendingIntent.FLAG_UPDATE_CURRENT);

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

            alarmManager.set(AlarmManager.RTC_WAKEUP, futureTimeDifference, displayIntent);

            //Toast.makeText(context, "Notification Set Monthly", Toast.LENGTH_SHORT).show();
        }
    }

0

感谢Techfist..例如:dateValue = "30/01/2017 11:02" ...从数据库获取id和日期...

private void getMonthlyDuration(Context context,int id,String dateValue) {
    SharedPreferences sharedPreferences = context.getSharedPreferences("ModernDiary", Context.MODE_PRIVATE);
    String dateOfMonth = sharedPreferences.getString("day"+id,DateFormat.format("dd", Calendar.getInstance()).toString());
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault());
    try {
        Date dateMain = simpleDateFormat.parse(dateValue);
        calendar.setTime(dateMain);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    Boolean isSetDate = false;
     if (sharedPreferences.getInt("monthInc"+id,-1) != -1) {
         calendar.set(Calendar.MONTH,sharedPreferences.getInt("monthInc"+id,calendar.get(Calendar.MONTH)));
         calendar.set(Calendar.YEAR,sharedPreferences.getInt("yearInc"+id,calendar.get(Calendar.YEAR)));
         if (calendar.getActualMaximum(Calendar.DAY_OF_MONTH) < Integer.parseInt(dateOfMonth)) {
             calendar.set(Calendar.DATE,calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
             Log.i("timeDay",dateOfMonth+" "+calendar.getTime()+" max");
         } else {
             calendar.set(Calendar.DATE,Integer.parseInt(dateOfMonth));
             Log.i("timeDay",dateOfMonth+" "+calendar.getTime()+"min");
         }
         if (sharedPreferences.getInt("monthInc"+id,calendar.get(Calendar.MONTH)) < calendar.get(Calendar.MONTH)){
             calendar.add(Calendar.MONTH, -1);
             isSetDate = true;
             Log.i("timeMonth","Increment "+calendar.getTime());
         } else {
             isSetDate = false;
             Log.i("timeMonth","No Change");
         }
     }
    calendar.add(Calendar.MONTH, 1);
     if (isSetDate){
         if (calendar.getActualMaximum(Calendar.DAY_OF_MONTH) < Integer.parseInt(dateOfMonth)) {
             calendar.set(Calendar.DATE,calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
         } else {
             calendar.set(Calendar.DATE,Integer.parseInt(dateOfMonth));
         }
     }
    Log.i("timeAf",calendar.getTime()+"");

    sharedPreferences.edit().putInt("monthInc"+id, calendar.get(Calendar.MONTH)).apply();
    sharedPreferences.edit().putInt("yearInc"+id, calendar.get(Calendar.YEAR)).apply();
    Intent notificationIntent = new Intent(context,AlarmBroadcastReceiver.class);
    Bundle bundle = new Bundle();
    bundle.putSerializable("alarm", id);
    notificationIntent.putExtra("bundle", bundle);
    alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    broadcast = PendingIntent.getBroadcast(context, id, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), broadcast);
}

警报触发时间: 2017年2月28日星期二11:02:00 GMT+05:30 2017年3月30日星期四11:02:00 GMT+05:30 2017年4月30日星期日11:02:00 GMT+05:30 2017年5月30日星期二11:02:00 GMT+05:30 2017年6月30日星期五11:02:00 GMT+05:30 2017年7月30日星期日11:02:00 GMT+05:30 2017年8月30日星期三11:02:00 GMT+05:30 2017年9月30日星期六11:02:00 GMT+05:30 2017年10月30日星期一11:02:00 GMT+05:30 2017年11月30日星期四11:02:00 GMT+05:30 2017年12月30日星期六11:02:00 GMT+05:30 2018年1月30日星期二11:02:00 GMT+05:30 2018年2月28日星期三11:02:00 GMT+05:30 ...


0

适用于年度重复的闹钟

GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
    if(cal.isLeapYear(year)){
      alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 366, alarmIntent);
    }else{
          alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 365, alarmIntent);
    }

0
你可以在广播接收器中使用set,然后重新设置闹钟。
在接收器中,只需简单地:
        val c = Calendar.getInstance().apply { add(Calendar.MONTH, 1) }
        // reset alarm here
        val intent = Intent(context, AlarmReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            context, 123, intent, 0
        )
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager?
        alarmManager!!.set(
            AlarmManager.RTC,
            c.timeInMillis,
            pendingIntent
        )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接