Android adds a schedule reminder event to the system calendar

Android adds a schedule reminder event to the system calendar

1. Permission application

<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />

Note: above 6.0, you need to apply for permission before you can use it.

2. Calendar related uri

if (Build.VERSION.SDK_INT >= 8) {
    calanderURL = "content://com.android.calendar/calendars";
    calanderEventURL = "content://com.android.calendar/events";
    calanderRemiderURL = "content://com.android.calendar/reminders";
} else {
    calanderURL = "content://calendar/calendars";
    calanderEventURL = "content://calendar/events";
    calanderRemiderURL = "content://calendar/reminders";
}

3. Tools

public class CalendarUtils {
    private static String calanderURL;
    private static String calanderEventURL;
    private static String calanderRemiderURL;
    private static String CALENDARS_NAME = "smartTime";
    private static String CALENDARS_ACCOUNT_NAME = "[email protected]";
    private static String CALENDARS_ACCOUNT_TYPE = "com.zg.smartTime";
    private static String CALENDARS_DISPLAY_NAME = "smartTime账号";
    /**
     * Initialize uri
     */
    static {
        if (Build.VERSION.SDK_INT >= 8) {
            calanderURL = "content://com.android.calendar/calendars";
            calanderEventURL = "content://com.android.calendar/events";
            calanderRemiderURL = "content://com.android.calendar/reminders";
        } else {
            calanderURL = "content://calendar/calendars";
            calanderEventURL = "content://calendar/events";
            calanderRemiderURL = "content://calendar/reminders";
        }
    }
    /**
     * Get calendar ID
     *
     * @param context
     * @return Calendar ID
     */
    public static int checkAndAddCalendarAccounts(Context context) {
        int oldId = checkCalendarAccounts(context);
        if (oldId >= 0) {
            return oldId;
        } else {
            long addId = addCalendarAccount(context);
            if (addId >= 0) {
                return checkCalendarAccounts(context);
            } else {
                return -1;
            }
        }
    }
    /**
     * Check if a calendar account exists
     *
     * @param context
     * @return
     */
    private static int checkCalendarAccounts(Context context) {
        Cursor userCursor = context.getContentResolver().query(Uri.parse(calanderURL), null, null, null, CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL + " ASC ");
        try {
            if (userCursor == null)//The query returns a null value
                return -1;
            int count = userCursor.getCount();
            if (count > 0) {//There is an existing account, take the id of the first account and return
                userCursor.moveToLast();
                return userCursor.getInt(userCursor.getColumnIndex(CalendarContract.Calendars._ID));
            } else {
                return -1;
            }
        } finally {
            if (userCursor != null) {
                userCursor.close();
            }
        }
    }
    /**
     * Add a calendar account
     *
     * @param context
     * @return
     */
    private static long addCalendarAccount(Context context) {
        TimeZone timeZone = TimeZone.getDefault();
        ContentValues value = new ContentValues();
        value.put(CalendarContract.Calendars.NAME, CALENDARS_NAME);
        value.put(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME);
        value.put(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE);
        value.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, CALENDARS_DISPLAY_NAME);
        value.put(CalendarContract.Calendars.VISIBLE, 1);
        value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
        value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
        value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
        value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.getID());
        value.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME);
        value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0);
        Uri calendarUri = Uri.parse(calenderURL);
        calendarUri = calendarUri.buildUpon()
                .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME)
                .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE)
                .build();
        Uri result = context.getContentResolver().insert(calendarUri, value);
        long id = result == null ? -1 : ContentUris.parseId(result);
        return id;
    }
    /**
     * Add an event to the calendar
     *
     * @param context
     * @param calendar_id (required parameter)
     * @param title
     * @param description
     * @param begintime The start time of the event, expressed in milliseconds of Coordinated Universal Time since the beginning of the epoch. (required parameter)
     * @param endtime The end time of the event, expressed in milliseconds of Coordinated Universal Time since the beginning of the epoch. (non-repeating event: required parameter)
     * @return
     */
    private static Uri insertCalendarEvent(Context context, long calendar_id, String title, String description, long begintime, long endtime) {
        ContentValues event = new ContentValues();
        event.put("title", title);
        event.put("description", description);
        // insert account id
        event.put("calendar_id", calendar_id);
        event.put(CalendarContract.Events.DTSTART, begintime);//must have
        event.put(CalendarContract.Events.DTEND, endtime);//Non-repeating event: must have
        event.put(CalendarContract.Events.HAS_ALARM, 1);//Set an alarm clock reminder
        event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//This is the time zone, must have,
        //add event
        Uri newEvent = context.getContentResolver().insert(Uri.parse(calanderEventURL), event);
        return newEvent;
    }
    /**
     * Query calendar events
     *
     * @param context
     * @param title event title
     * @return event id, if not found, return ""
     */
    public static String queryCalendarEvent(Context context, long calendar_id, String title, String description, long start_time, long end_time) {
        // Construct query based on date range
        Uri.Builder builder = CalendarContract.Instances.CONTENT_URI.buildUpon();
        ContentUris.appendId(builder, start_time);
        ContentUris.appendId(builder, end_time);
        Cursor cursor = context.getContentResolver().query(builder.build(), null, null, null, null);
        String tmp_title;
        String tmp_desc;
        long temp_calendar_id;
        if (cursor.moveToFirst()) {
            do {
                tmp_title = cursor.getString(cursor.getColumnIndex("title"));
                tmp_desc = cursor.getString(cursor.getColumnIndex("description"));
                temp_calendar_id = cursor.getLong(cursor.getColumnIndex("calendar_id"));
                long dtstart = cursor.getLong(cursor.getColumnIndex("dtstart"));
                if (TextUtils.equals(title, tmp_title) && TextUtils.equals(description, tmp_desc) && calendar_id == temp_calendar_id && dtstart == start_time) {
                    String eventId = cursor.getString(cursor.getColumnIndex("event_id"));
                    return eventId;
                }
            } while (cursor.moveToNext());
        }
        return "";
    }
    /**
     * Add calendar reminder: title, description, and start time together mark a separate reminder event
     *
     * @param context
     * @param title The title of the calendar reminder, not allowed to be empty
     * @param description The description (note) information of the calendar
     * @param begintime The start time of the event, expressed in milliseconds of Coordinated Universal Time since the beginning of the epoch.
     * @param endtime The end time of the event, expressed in milliseconds of Coordinated Universal Time since the beginning of the epoch.
     * @param reminder_minutes send a reminder remind_minutes minutes in advance
     * @param callback add reminder success result monitoring
     */
    public static void addCalendarEventRemind(Context context, @NonNull String title, String description, long begintime, long endtime, int remind_minutes, onCalendarRemindListener callback) {
        long calendar_id = checkAndAddCalendarAccounts(context);
        if (calendar_id < 0) {
            // Fail to get the calendar and return directly
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._CALENDAR_ERROR);
            }
            return;
        }
        // Check whether the reminder event already exists according to the title, description, and start time
        String event_id = queryCalendarEvent(context, calendar_id, title, description, begintime, endtime);
        //If the reminder event does not exist, create a new event
        if (TextUtils.isEmpty(event_id)) {
            Uri newEvent = insertCalendarEvent(context, calendar_id, title, description, begintime, endtime);
            if (newEvent == null) {
                // Failed to add a calendar event and return directly
                if (null != callback) {
                    callback.onFailed(onCalendarRemindListener.Status._EVENT_ERROR);
                }
                return;
            }
            event_id = ContentUris.parseId(newEvent) + "";
        }
        // set a reminder for the event
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Reminders.EVENT_ID, event_id);
        // There is a reminder remind_minutes minutes in advance
        values.put(CalendarContract.Reminders.MINUTES, remind_minutes);
        values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
        Uri uri = context.getContentResolver().insert(Uri.parse(calanderRemiderURL), values);
        if (uri == null) {
            // Fail to add a reminder and return directly
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._REMIND_ERROR);
            }
            return;
        }
        // add reminder successfully
        if (null != callback) {
            callback.onSuccess();
        }
    }
    /**
     * Add calendar reminder: title, description, and start time together mark a separate reminder event
     *
     * @param context
     * @param title The title of the calendar reminder, not allowed to be empty
     * @param description The description (note) information of the calendar
     * @param begintime The start time of the event, expressed in milliseconds of Coordinated Universal Time since the beginning of the epoch.
     * @param endtime The end time of the event, expressed in milliseconds of Coordinated Universal Time since the beginning of the epoch.
     * @param reminder_minutes send a reminder remind_minutes minutes in advance
     * @param callback add reminder success result monitoring
     */
    public static void addCalendarEventRemind(Context context, @NonNull String title, String description, long begintime, long endtime, int remind_minutes, String rules, onCalendarRemindListener callback) {
        long calendar_id = checkAndAddCalendarAccounts(context);
        if (calendar_id < 0) {
            // Fail to get the calendar and return directly
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._CALENDAR_ERROR);
            }
            return;
        }
        // Check whether the reminder event already exists according to the title, description, and start time
        String event_id = queryCalendarEvent(context, calendar_id, title, description, begintime, endtime);
        //If the reminder event does not exist, create a new event
        if (TextUtils.isEmpty(event_id)) {
            ContentValues event = new ContentValues();
            event.put("title", title);
            event.put("description", description);
            // insert account id
            event.put("calendar_id", calendar_id);
            event.put(CalendarContract.Events.RRULE, rules);
            event.put(CalendarContract.Events.DTSTART, begintime);//must have
            event.put(CalendarContract.Events.DTEND, endtime);//Non-repeating event: must have
            event.put(CalendarContract.Events.HAS_ALARM, 1);//Set an alarm clock reminder
            event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//This is the time zone, must have,
            //add event
            Uri newEvent = context.getContentResolver().insert(Uri.parse(calanderEventURL), event);
            if (newEvent == null) {
                // Failed to add a calendar event and return directly
                if (null != callback) {
                    callback.onFailed(onCalendarRemindListener.Status._EVENT_ERROR);
                }
                return;
            }
            event_id = ContentUris.parseId(newEvent) + "";
        }
        // set a reminder for the event
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Reminders.EVENT_ID, event_id);
        // There is a reminder remind_minutes minutes in advance
        values.put(CalendarContract.Reminders.MINUTES, remind_minutes);
        values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
        Uri uri = context.getContentResolver().insert(Uri.parse(calanderRemiderURL), values);
        if (uri == null) {
            // Fail to add a reminder and return directly
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._REMIND_ERROR);
            }
            return;
        }
        // add reminder successfully
        if (null != callback) {
            callback.onSuccess();
        }
    }
    /**
     * Delete calendar reminder events: Locate calendar events by title, description and start time
     *
     * @param context
     * @param title the title of the reminder
     * @param description Reminder description: deeplink URI
     * @param startTime The start time of the event
     * @param callback The listener callback for whether the deletion is successful or not
     */
    public static void deleteCalendarEventRemind(Context context, String title, String description, long startTime, onCalendarRemindListener callback) {
        Cursor eventCursor = context.getContentResolver().query(Uri.parse(calanderEventURL), null, null, null, null);
        Log.i("zxd", "deleteCalendarEventRemind: " + (eventCursor == null));
        try {
            if (eventCursor == null)//The query returns a null value
                return;
            if (eventCursor.getCount() > 0) {
                //Loop through all events and find items whose title, description, and startTime are the same as the title, description, and dtstart that need to be queried
                for (eventCursor.moveToFirst(); !eventCursor.isAfterLast(); eventCursor.moveToNext()) {
                    String eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
                    String eventDescription = eventCursor.getString(eventCursor.getColumnIndex("description"));
                    long dtstart = eventCursor.getLong(eventCursor.getColumnIndex("dtstart"));
                    if (!TextUtils.isEmpty(title) && title.equals(eventTitle) && !TextUtils.isEmpty(description) && description.equals(eventDescription) && dtstart == startTime) {
                        int id = eventCursor.getInt(eventCursor.getColumnIndex(CalendarContract.Calendars._ID));//取得id
                        Uri deleteUri = ContentUris.withAppendedId(Uri.parse(calanderEventURL), id);
                        int rows = context.getContentResolver().delete(deleteUri, null, null);
                        if (rows == -1) {
                            // Fail to delete the reminder and return directly
                            if (null != callback) {
                                callback.onFailed(onCalendarRemindListener.Status._REMIND_ERROR);
                            }
                            return;
                        }
                        //Delete the reminder successfully
                        if (null != callback) {
                            callback.onSuccess();
                        }
                    }
                }
            }
        } finally {
            if (eventCursor != null) {
                eventCursor.close();
            }
        }
    }
    /**
     * Calendar reminder added success or not monitor
     */
    public static interface onCalendarRemindListener {
        enum status
            _CALENDAR_ERROR,
            _EVENT_ERROR,
            _REMIND_ERROR
        }
        void onFailed(Status error_code);
        void onSuccess();
    }
    /**
     * Auxiliary method: Get the corresponding milliseconds of the start and end time of the set time
     *
     * @param year
     * @param month  1-12
     * @param day    1-31
     * @param hour   0-23
     * @param minute 0-59
     * @return
     */
    public static long remindTimeCalculator(int year, int month, int day, int hour, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, day, hour, minute, 0);
        calendar.set(Calendar.MILLISECOND, 0);//To keep the data consistent. If your milliseconds are different, even if the title and content of the calendar event are the same, it cannot be deleted
        return calendar.getTimeInMillis();
    }
}

4. use

At about 13.26, add a schedule for 13.28 minutes, cancel the schedule with a 3 minute delay.

public void cancelCalendar(View view) {
    //Set 10:00 am to 10:10 am
    long times = System.currentTimeMillis();
    final Calendar cal = Calendar.getInstance();
    cal.setTimeInMillis(times);
    cal.set(Calendar.HOUR_OF_DAY, 13);
    cal.set(Calendar.MINUTE, 28);
    Calendar cal2 = Calendar.getInstance();
    cal2.setTimeInMillis(times);
    cal2.set(Calendar.HOUR_OF_DAY, 13);
    cal2.set(Calendar.MINUTE, 30);
    CalendarUtils.addCalendarEventRemind(this, "It's today!", "10 o'clock every day",
            CalendarUtils.remindTimeCalculator(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH),
                    cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)),
            CalendarUtils.remindTimeCalculator(cal2.get(Calendar.YEAR), cal2.get(Calendar.MONTH) + 1, cal2.get(Calendar.DAY_OF_MONTH),
                    cal2.get(Calendar.HOUR_OF_DAY), cal2.get(Calendar.MINUTE)), 0, new CalendarUtils.onCalendarRemindListener() {
                @Override
                public void onFailed(Status error_code) {
                    Log.e("zxd", "onFailed: " + error_code);
                }
                @Override
                public void onSuccess() {
                    Log.i("zxd", "onSuccess: Add schedule successfully!");
                }
            });
    view.postDelayed(new Runnable() {
        @Override
        public void run() {
            CalendarUtils.deleteCalendarEventRemind(SystemCalendarActivity.this, "It's today!", "10 o'clock every day",
                    CalendarUtils.remindTimeCalculator(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH),
                            cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)), new CalendarUtils.onCalendarRemindListener() {
                        @Override
                        public void onFailed(Status error_code) {
                            Log.e("zxd", "onFailed: " + error_code);
                        }
                        @Override
                        public void onSuccess() {
                            Log.i("zxd", "onSuccess: Delete schedule successfully!");
                        }
                    });
        }
    }, 1000 * 60 * 3);
}

5. Repeat rule

iCalendar Recurrence Rule Specification Translation

Specification original link: RFC 5545

Recurrence Rule

Recurrence rule (Recurrence Rule) belongs to one of the icalendar attributes. Cooperating with dtstart, it can fully describe the recurrence behavior of an event and calculate the specific occurrence (Occurence) of the recurrence event.

A repetition rule contains multiple attributes, and each attribute exists in the form of NAME = VALUE pairs. The attributes are separated by a semicolon. There is no specific order requirement for the attributes. In the same repetition rule, each attribute can be at most appear once.


FREQ

The FREQ attribute indicates the type of the repetition rule, and it is an attribute that must be defined in the repetition rule. Available VALUEs are:

SECONDLY, means to repeat in seconds. MINUTELY, which means repeating in minutes. HOURLY, which means repeating at intervals of hours. DAILY, means to repeat with the interval unit of day. WEEKLY, means to repeat at intervals of weeks. MONTHLY, means to repeat at intervals of months. YEARLY, means to repeat at intervals of years.

INTERVAL

The INTERVAL attribute represents the interval of the repetition rule, which must be a positive integer. The default value is 1, which corresponds to the above-mentioned different FREQ values, representing each second, each minute, each hour, each day, each week, each month, and each year.

UNTIL

The UNTIL attribute defines a date-time value to limit the repetition rule. This date-time value indicates when the last event for this recurrence rule occurred. If the UNTIL and COUNT attributes are not included in the repetition rule, it means that the repetition rule repeats infinitely.

COUNT

The COUNT attribute limits a repeating rule by defining the number of occurrences of a repeating event. positive integer.

BYSECOND, BYMINUTE, BYHOUR

The value range of BYSECOND is 0 - 59, which can be understood as "n seconds of...". The value range of BYMINUTE is 0 - 59, which can be understood as "n points of ...". The value range of BYHOUR is 0 - 23, which can be understood as "n hours of ...".

BYDAY

BYDAY value range: MO (Monday), TU (Tuesday), WE (Wednesday), TU (Thursday), FR (Friday), SA (Saturday), SU (Sunday). There can be multiple values, separated by commas.

Each value can be preceded by a positive integer (+n) or a negative integer (-n) to represent the nth day of the week in MONTHLY or YEARLY repetition types. For example, in a recurrence rule of type MONTHLY, +1MO (or 1MO) means the first Monday of the month, and -1MO means the last Monday of the month.

If there is no number in front, it means all the days of the week in this repetition type, for example, in a MONTHLY repetition type, MO means all Mondays in this month.

BYMONTHDAY

BYMONTHDAY ranges from 1 - 31 or -31 - -1, indicating the day of the month. For example, -10 means the last 10th day of a month. There can be multiple values, separated by commas.

BYYEARDAY

The value range of BYYEARDAY is 1 - 366 or -366 - -1, indicating the day of the year. For example, -1 means the last day of the year, and 306 means the 306th day of the year. There can be multiple values, separated by commas.

BYWEEKNO

The value range of BYWEEKNO is 1 - 53 or -53 - -1, indicating the week of the year, and it is only valid in the YEARLY type of recurrence rule. For example, 3 indicates the 3rd week of the year. There can be multiple values, separated by commas. (Note: The first week of a year refers to the first week that contains at least 4 days of the year)

BYMONTY

BYMONTH ranges from 1 to 12, indicating the first month of the year. There can be multiple values, separated by commas.

WKST

WKST value range MO, TU, WE, TH, FR, SA, SU. The default is MO. When a repetition rule of WEEKLY type, INTERVAL is greater than 1, and has BYDAY attribute, it must have WKST attribute. When a recurrence rule of type YEARLY has BYWEEKNO attribute, it must also have WKST attribute.

BYSETPOS

The value range of BYSETPOS is 1 - 366 or -366 - -1, indicating the nth event in the event set specified by the rule, and must be used together with other BYxxx attributes. For example, the last group of working days of each month can be expressed as: RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1


If the value of a BYxxx attribute exceeds its corresponding range, the attribute will be ignored.

When there are multiple BYxxx attributes, after substituting the FREQ and INTEVAL attributes, substitute them into the existing rules in the following order: BYMONTH, BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY, BYHOUR, BYMINUTE, BYSECOND, BYSETPOS

例如: RRULE:FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9; BYMINUTE=30

First, substitute INTERVAL=2 into FREQ=YEARLY to get "every 2 years", then substitute BYMONTH=1 to get "every 2 years in January", and then substitute BYDAY=SU to get "every 2 years All Sundays in January", and then substitute BYHOUR=8,9 to get "8:00 and 9:00 on all Sundays in January every 2 years" (note that it is 8:00 and 9:00, not 8:00 to 9 point), and finally substitute BYMINUTE=30 to get "8:30 and 9:30 on all Sundays in January every two years".

For time information not specified in the rules, the start time (dtstart) shall prevail.


Examples

Occurs once a day and repeats 10 times: RRULE:FREQ=DAILY;COUNT=10

Occurs once a day until December 24, 1997: RRULE:FREQ=DAILY;UNTIL=19971224T000000Z

Happens every 2 days forever: RRULE:FREQ=DAILY;INTERVAL=2

Occurs every 10 days and repeats 5 times: RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5

The current date is 9:00:00 on January 1, 1998, and it will happen every day in January every year for the next 3 years: RRULE:FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU ,WE,TH,FR,SA Or: RRULE:FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1

Once a week, 10 occurrences in total: RRULE:FREQ=WEEKLY;COUNT=10

Once a week until December 24, 1997: RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z

Every 2 weeks, forever: RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU

The current time is September 2, 1997 at 09:00:00, which happens every Tuesday and Thursday for 5 weeks: RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH Or: RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH

Once every Monday, Wednesday, and Friday until December 24, 1997: RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR

Occurs once on Tuesday and Thursday every 2 weeks, a total of 8 occurrences: RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH

Occurs once on the first Friday of each month, a total of 10 occurrences: RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR

Occurs on the first Friday of every month until December 24, 1997: RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR

Occurs every 2 months on the first and last Sunday, 10 times in total: RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU

Occurs once on the penultimate Monday of each month, a total of 6 occurrences: RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO

Occurs on the third last day of every month forever: RRULE:FREQ=MONTHLY;BYMONTHDAY=-3

Occurs once on the 2nd day and 15th day of each month, a total of 10 occurrences: RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15

Occurs once on the first and last day of each month, totaling 10 occurrences: RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1

Occurs once a day from the 1st to the 15th of every 18 months, a total of 10 occurrences: RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15

Occurs daily on all Tuesdays every 2 months: RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU

Occurs once a year in June and July, a total of 10 occurrences: RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7

Every 2 years in January, February and March, 10 times in total: RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3

Every 3 years, the first day, the 100th day and the 200th day each occur, a total of 10 times: RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200

Occurs every year on the 20th Monday forever: RRULE:FREQ=YEARLY;BYDAY=20MO

Occurs once a year on Monday of the 20th week (with Monday as the start day of the week) forever: RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO

Every Thursday in March, forever: RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH

Every Thursday in June, July, August, forever: RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8

Happens every Black Friday (Friday the 13th) forever: RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13

Occurs once a month on the Saturday of the week following the first Sunday, forever: RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13

Occurs every 4 years on the Tuesday after the first Monday in November, forever RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6, 7,8

The 3rd instance into the month of one of Tuesday, Wednesday or Thursday, for the next 3 months(没法翻译,自己理解): RRULE:FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3

Second-to-last business day of every month, forever: RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2


how to use? Where is it used?

FREQ=DAILY;INTERVAL=1

Use when creating ContentValues ​​data

ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
// insert account id
event.put("calendar_id", calendar_id);
event.put(CalendarContract.Events.RRULE, rules);
event.put(CalendarContract.Events.DTSTART, begintime);//must have
event.put(CalendarContract.Events.DTEND, endtime);//Non-repeating event: must have
event.put(CalendarContract.Events.HAS_ALARM, 1);//Set an alarm clock reminder
event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//This is the time zone, must have,
//add event
Uri newEvent = context.getContentResolver().insert(Uri.parse(calanderEventURL), event);

6. Reference

Android adds a schedule reminder event to the system calendar

Android--Calendar event view, add, delete

Android adds system calendar reminders, and view added events from the project calendar <Calendar 111> (with renderings)

Guess you like

Origin blog.csdn.net/fromVillageCoolBoy/article/details/132066184