Android 向系统日历添加日程提醒事件

Android 向系统日历添加日程提醒事件

1.权限申请

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

注意:6.0 以上需要申请权限才可以使用哦

2.日历相关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.工具类

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账号";
​
    /**
     * 初始化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";
        }
    }
​
    /**
     * 获取日历ID
     *
     * @param context
     * @return 日历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;
            }
        }
    }
​
    /**
     * 检查是否存在日历账户
     *
     * @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)//查询返回空值
                return -1;
            int count = userCursor.getCount();
            if (count > 0) {//存在现有账户,取第一个账户的id返回
                userCursor.moveToLast();
                return userCursor.getInt(userCursor.getColumnIndex(CalendarContract.Calendars._ID));
            } else {
                return -1;
            }
        } finally {
            if (userCursor != null) {
                userCursor.close();
            }
        }
    }
​
    /**
     * 添加一个日历账户
     *
     * @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(calanderURL);
        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;
    }
​
    /**
     * 向日历中添加一个事件
     *
     * @param context
     * @param calendar_id (必须参数)
     * @param title
     * @param description
     * @param begintime   事件开始时间,以从公元纪年开始计算的协调世界时毫秒数表示。 (必须参数)
     * @param endtime     事件结束时间,以从公元纪年开始计算的协调世界时毫秒数表示。(非重复事件:必须参数)
     * @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);
        // 插入账户的id
        event.put("calendar_id", calendar_id);
        event.put(CalendarContract.Events.DTSTART, begintime);//必须有
        event.put(CalendarContract.Events.DTEND, endtime);//非重复事件:必须有
        event.put(CalendarContract.Events.HAS_ALARM, 1);//设置有闹钟提醒
        event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//这个是时区,必须有,
        //添加事件
        Uri newEvent = context.getContentResolver().insert(Uri.parse(calanderEventURL), event);
        return newEvent;
    }
​
    /**
     * 查询日历事件
     *
     * @param context
     * @param title   事件标题
     * @return 事件id, 查询不到则返回""
     */
    public static String queryCalendarEvent(Context context, long calendar_id, String title, String description, long start_time, long end_time) {
        // 根据日期范围构造查询
        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 "";
    }
​
    /**
     * 添加日历提醒:标题、描述、开始时间共同标定一个单独的提醒事件
     *
     * @param context
     * @param title          日历提醒的标题,不允许为空
     * @param description    日历的描述(备注)信息
     * @param begintime      事件开始时间,以从公元纪年开始计算的协调世界时毫秒数表示。
     * @param endtime        事件结束时间,以从公元纪年开始计算的协调世界时毫秒数表示。
     * @param remind_minutes 提前remind_minutes分钟发出提醒
     * @param callback       添加提醒是否成功结果监听
     */
    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) {
            // 获取日历失败直接返回
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._CALENDAR_ERROR);
            }
            return;
        }
        //根据标题、描述、开始时间查看提醒事件是否已经存在
        String event_id = queryCalendarEvent(context, calendar_id, title, description, begintime, endtime);
        //如果提醒事件不存在,则新建事件
        if (TextUtils.isEmpty(event_id)) {
            Uri newEvent = insertCalendarEvent(context, calendar_id, title, description, begintime, endtime);
            if (newEvent == null) {
                // 添加日历事件失败直接返回
                if (null != callback) {
                    callback.onFailed(onCalendarRemindListener.Status._EVENT_ERROR);
                }
                return;
            }
            event_id = ContentUris.parseId(newEvent) + "";
        }
        //为事件设定提醒
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Reminders.EVENT_ID, event_id);
        // 提前remind_minutes分钟有提醒
        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) {
            // 添加提醒失败直接返回
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._REMIND_ERROR);
            }
            return;
        }
​
        //添加提醒成功
        if (null != callback) {
            callback.onSuccess();
        }
    }
​
    /**
     * 添加日历提醒:标题、描述、开始时间共同标定一个单独的提醒事件
     *
     * @param context
     * @param title          日历提醒的标题,不允许为空
     * @param description    日历的描述(备注)信息
     * @param begintime      事件开始时间,以从公元纪年开始计算的协调世界时毫秒数表示。
     * @param endtime        事件结束时间,以从公元纪年开始计算的协调世界时毫秒数表示。
     * @param remind_minutes 提前remind_minutes分钟发出提醒
     * @param callback       添加提醒是否成功结果监听
     */
    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) {
            // 获取日历失败直接返回
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._CALENDAR_ERROR);
            }
            return;
        }
        //根据标题、描述、开始时间查看提醒事件是否已经存在
        String event_id = queryCalendarEvent(context, calendar_id, title, description, begintime, endtime);
        //如果提醒事件不存在,则新建事件
        if (TextUtils.isEmpty(event_id)) {
            ContentValues event = new ContentValues();
            event.put("title", title);
            event.put("description", description);
            // 插入账户的id
            event.put("calendar_id", calendar_id);
            event.put(CalendarContract.Events.RRULE, rules);
            event.put(CalendarContract.Events.DTSTART, begintime);//必须有
            event.put(CalendarContract.Events.DTEND, endtime);//非重复事件:必须有
            event.put(CalendarContract.Events.HAS_ALARM, 1);//设置有闹钟提醒
            event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//这个是时区,必须有,
            //添加事件
            Uri newEvent = context.getContentResolver().insert(Uri.parse(calanderEventURL), event);
            if (newEvent == null) {
                // 添加日历事件失败直接返回
                if (null != callback) {
                    callback.onFailed(onCalendarRemindListener.Status._EVENT_ERROR);
                }
                return;
            }
            event_id = ContentUris.parseId(newEvent) + "";
        }
        //为事件设定提醒
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Reminders.EVENT_ID, event_id);
        // 提前remind_minutes分钟有提醒
        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) {
            // 添加提醒失败直接返回
            if (null != callback) {
                callback.onFailed(onCalendarRemindListener.Status._REMIND_ERROR);
            }
            return;
        }
​
        //添加提醒成功
        if (null != callback) {
            callback.onSuccess();
        }
    }
​
    /**
     * 删除日历提醒事件:根据标题、描述和开始时间来定位日历事件
     *
     * @param context
     * @param title       提醒的标题
     * @param description 提醒的描述:deeplink URI
     * @param startTime   事件的开始时间
     * @param callback    删除成功与否的监听回调
     */
    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)//查询返回空值
                return;
            if (eventCursor.getCount() > 0) {
                //遍历所有事件,找到title、description、startTime跟需要查询的title、descriptio、dtstart一样的项
                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) {
                            // 删除提醒失败直接返回
                            if (null != callback) {
                                callback.onFailed(onCalendarRemindListener.Status._REMIND_ERROR);
                            }
                            return;
                        }
                        //删除提醒成功
                        if (null != callback) {
                            callback.onSuccess();
                        }
                    }
                }
            }
        } finally {
            if (eventCursor != null) {
                eventCursor.close();
            }
        }
    }
​
    /**
     * 日历提醒添加成功与否监控器
     */
    public static interface onCalendarRemindListener {
        enum Status {
            _CALENDAR_ERROR,
            _EVENT_ERROR,
            _REMIND_ERROR
        }
​
        void onFailed(Status error_code);
​
        void onSuccess();
    }
​
    /**
     * 辅助方法:获取设置时间起止时间的对应毫秒数
     *
     * @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);//要保持数据一致。如果你的毫秒数不一样,即使日历事件的标题和内容一样也是不能删除的
        return calendar.getTimeInMillis();
    }
}

4.使用

在大约13.26的时候,添加一个13.28分的日程,延迟3分钟取消日程。

public void cancelCalendar(View view) {
    //设置上午10点0分到10点10分
    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, "今天啦!", "每日10点",
            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: 添加日程成功!");
                }
            });
​
    view.postDelayed(new Runnable() {
        @Override
        public void run() {
            CalendarUtils.deleteCalendarEventRemind(SystemCalendarActivity.this, "今天啦!", "每日10点",
                    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: 删除日程成功!");
                        }
                    });
        }
    }, 1000 * 60 * 3);
}

5.重复规则

iCalendar Recurrence Rule 规范翻译

规范原文链接:RFC 5545

Recurrence Rule

重复规则 rrule(Recurrence Rule) 属于 icalendar 属性中的一个,配合 dtstart 可以完整描述一个事件的重复行为并计算出重复事件的具体发生 (Occurence)。

重复规则包含多个属性, 每个属性以 NAME = VALUE 对的形式存在, 属性与属性之间用分号区分, 属性之间没有特定的顺序要求,在同一个重复规则中每个属性最多只能出现一次。


FREQ

FREQ 属性表示重复规则的类型, 是重复规则中必须定义的一条属性。 可选的 VALUE 有:

SECONDLY, 表示以秒为间隔单位进行重复。 MINUTELY, 表示以分钟为间隔单位进行重复。 HOURLY, 表示以小时为间隔单位进行重复。 DAILY, 表示以天为间隔单位进行重复。 WEEKLY, 表示以周为间隔单位进行重复。 MONTHLY, 表示以月为间隔单位进行重复。 YEARLY, 表示以年为间隔单位进行重复。

INTERVAL

INTERVAL 属性表示重复规则的间隔, 必须为正整数。 默认值为1, 对应上述不同的 FREQ 值分别表示每一秒,每一分钟, 每一小时, 每一天, 每一周, 每一月, 每一年。

UNTIL

UNTIL 属性定义了一个日期-时间值,用以限制重复规则。 这个日期-时间值表示这个重复规则的最后一次事件的发生时间。 如果重复规则中未包含 UNTIL 和 COUNT 属性, 则表示该重复规则无限重复。

COUNT

COUNT 属性通过定义重复事件的发生次数来限制重复规则。 正整数。

BYSECOND, BYMINUTE, BYHOUR

BYSECOND 取值范围 0 - 59, 可以理解为 “…… 的 n 秒”。 BYMINUTE 取值范围 0 - 59, 可以理解为 “…… 的 n 分”。 BYHOUR 取值范围 0 - 23, 可以理解为 “…… 的 n 时”。

BYDAY

BYDAY 取值范围: MO(周一), TU(周二), WE(周三), TU(周四), FR(周五), SA(周六), SU(周日)。可以有多个值,用逗号分隔。

每个值可以在前面加上一个正整数(+n)或者负整数(-n),用以在 MONTHLY 或者 YEARLY 的重复类型中表示第 n 个周几。 例如,在一个 MONTHLY 类型的重复规则中, +1MO(或者1MO)表示这个月的第1个周一,如果是 -1MO 则表示这个月的最后1个周一。

如果前面没有数字,则表示在这个重复类型中的所有的周几, 比如在一个 MONTHLY 的重复类型中, MO 表示这个月里所有的周一。

BYMONTHDAY

BYMONTHDAY 取值范围 1 - 31 或者 -31 - -1,表示一个月的第几天。 比如, -10 表示一个月的倒数第10天。可以有多个值,用逗号分隔。

BYYEARDAY

BYYEARDAY 取值范围 1 - 366 或者 -366 - -1, 表示一年的第几天。 比如, -1 表示一年的最后一天, 306 表示一年的第306天。可以有多个值,用逗号分隔。

BYWEEKNO

BYWEEKNO 取值范围 1 - 53 或者 -53 - -1, 表示一年的第几周, 只在 YEARLY 类型的重复规则中有效。 比如, 3 表示一年的第 3 周。可以有多个值,用逗号分隔。(注:一年的第一周是指第一个至少包含该年4天时间的那一周)

BYMONTY

BYMONTH 取值范围 1 - 12, 表示一年的第几个月。可以有多个值,用逗号分隔。

WKST

WKST 取值范围 MO, TU, WE, TH, FR, SA, SU。 默认值为 MO。 当一个 WEEKLY 类型的重复规则, INTERVAL 大于 1, 且带有 BYDAY 属性时, 则必须带有 WKST 属性。 当一个 YEARLY 类型的重复规则带有 BYWEEKNO 属性时, 也必须带有 WKST 属性。

BYSETPOS

BYSETPOS 取值范围 1 - 366 或者 -366 - -1, 表示规则指定的事件集合中的第n个事件, 必须与另外的 BYxxx 属性共同使用。 比如,每月的最后一组工作日可以表示为: RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1


如果一个 BYxxx 属性的值超过了它对应的范围,则该属性会被忽略。

当有多个 BYxxx 属性存在的时候, 在代入了 FREQ 和 INTEVAL 属性后,按照以下顺序代入到已有规则上:BYMONTH, BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY, BYHOUR, BYMINUTE, BYSECOND,BYSETPOS

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

首先,将 INTERVAL=2 代入到 FREQ=YEARLY 上,得到“每2年”, 然后在这基础上代入 BYMONTH=1 得到 “每2年的1月”, 再代入 BYDAY=SU, 得到“每2年的1月的所有周日”, 再代入 BYHOUR=8,9, 得到 “每2年的1月的所有周日的8点9点”(注意是8点和9点,不是8点到9点), 最后代入 BYMINUTE=30, 得到“每2年的1月的所有周日的8点30分9点30分”。

规则中未注明的时间信息,以开始时间(dtstart)为准。


Examples

每天发生一次,重复10次: RRULE:FREQ=DAILY;COUNT=10

每天发生一次,直到1997年12月24日: RRULE:FREQ=DAILY;UNTIL=19971224T000000Z

每2天发生一次,直到永远: RRULE:FREQ=DAILY;INTERVAL=2

每10天发生一次,重复5次: RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5

当前日期为1998年1月1日9点0分0秒,之后的3年里每年的1月每天发生一次: RRULE:FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA 或者: RRULE:FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1

每周一次,共发生10次: RRULE:FREQ=WEEKLY;COUNT=10

每周一次,直到1997年12月24日: RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z

每2周一次, 直到永远: RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU

当前时间为1997年9月2日9点0分0秒,每周二和周四各发生一次,持续5周: RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH 或者: RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH

每周一, 周三, 周五各一次,直到1997年12月24日: RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR

每2周的周二和周四各发生一次,共发生8次: RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH

每月的第一个周五发生一次,共发生10次: RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR

每月的第一个周五发生一次,直到1997年12月24日: RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR

每2个月的第一个周日和最后一个周日个发生一次,共发生10次: RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU

每月的倒数第二个周一发生一次,共发生6次: RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO

每月的倒数第三天发生一次,直到永远: RRULE:FREQ=MONTHLY;BYMONTHDAY=-3

每月的第2天和第15天各发生一次,共发生10次: RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15

每月的第1天和最后1天各发生一次,共发生10次: RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1

每个18个月的1号至15号每天发生一次,共发生10次: RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15

每2个月的所有周二每天发生一次: RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU

每年6月和7月各发生一次,共发生10次: RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7

每2年的一月,二月,三月各发生一次,共10次: RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3

每3年的第一天,第100天和第200天各发生一次,共10次: RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200

每年的第20个周一发生一次,直到永远: RRULE:FREQ=YEARLY;BYDAY=20MO

每年的第20周的周一(以周一为一周起始日)发生一次,直到永远: RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO

每年3月的所有周四,直到永远: RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH

每年6月,7月,8月的所有周四,直到永远: RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8

每一个黑色星期五(13号那天为周五)发生一次,直到永远: RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13

每月第一个周日之后那一周的周六发生一次,直到永远: RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13

每4年的11月的第一个周一之后的那个周二发生一次,直到永远 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

每月的倒数第2个工作日,直到永远: RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2


怎么使用?在哪使用?

FREQ=DAILY;INTERVAL=1

创建ContentValues数据的时候使用

ContentValues event = new ContentValues();
event.put("title", title);
event.put("description", description);
// 插入账户的id
event.put("calendar_id", calendar_id);
event.put(CalendarContract.Events.RRULE, rules);
event.put(CalendarContract.Events.DTSTART, begintime);//必须有
event.put(CalendarContract.Events.DTEND, endtime);//非重复事件:必须有
event.put(CalendarContract.Events.HAS_ALARM, 1);//设置有闹钟提醒
event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//这个是时区,必须有,
//添加事件
Uri newEvent = context.getContentResolver().insert(Uri.parse(calanderEventURL), event);

6.参考

Android向系统日历添加日程提醒事件

Android--日历事件查看、添加、删除

Android添加系统日历提醒,并从项目日历查看添加的事件<日历 111>(带效果图)

猜你喜欢

转载自blog.csdn.net/fromVillageCoolBoy/article/details/132066184