因为业务需求,需要获取系统日历的日程信息,并进行一定的增删改查操作,所以对这块进行了一些调研。这个知识点不难,但是比较冷僻,所以如果有个参考文章,研究起来比较方便点。如果有错漏的地方,欢迎指出,我们一起探讨。
本文参考的是Android原生API和对Android手机系统日历数据增删改查操作详解,相关代码写了个Demo,Demo App的地址。
日历提供程序是用户日历事件的存储区。您可以使用 Calendar Provider API,对日历、事件、参加者、提醒等执行查询、插入、更新和删除操作。
一、相关知识点:
- ContentResolver
Cursor cursor = getContentResolver().query(
uri, //指定查询某个应用程序下的某张表
projection,//指定查询的列明
selection,//指定where的约束条件
selectionArgs,//为where中的占位符提供具体的值
sortOrder);//指定查询结果的排序方式
二、系统日历基础知识点:
- 手机系统日历操作需要添加权限才能操作
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
- 系统日历相关的数据表
日历相关的数据库表有五个,每张表的侧重点不同。
Events表可以满足我们大部分要求,但是它有个明显的缺点,就是如果是重复事件,我们去 Events表查询数据的时候,重复的事件会是同一条数据,我们只能根据重复规则将这条数据手动区分成不同的事件。
Instantces表可以将重复事件直接区分开来。
- 每张表对应的URI地址:
Events:
CalendarContract.Events.CONTENT_URI
content://com.android.calendar/events
Instances:有多张表,下面是常用的表
CalendarContract.Instances.CONTENT_URI
content://com.android.calendar/instances/when
Reminders:
CalendarContract.Reminders.CONTENT_URI
content://com.android.calendar/reminders
下面我们对日历数据库表进行详解:
CalendarContract.Events
表包含各事件的详细信息。
下面介绍Events表中一些常见的字段:
_ID: 事件的_ID,是事件的唯一标识符,_id是递增的数值;
CALENDAR_ID: 这个字段对应Calendars表,标记日程的来源。
TITLE: 事件的标题;
DESCRIPTION: 事件的描述;
EVENT_LOCATION: 事件的地址;
DTSTART:事件的开始时间,单位是毫秒;
DTEND:事件的结束时间,单位是毫秒;
DURATION:事件持续的时长;
ALL_DAY:值为1表示此事件占用一整天;值为0表示它是常规日程,可在一天的任何时间开始和结束;
RRULE:事件重复发生的规则格式;
RDATE:事件重复发生的日期。RDATE和RRULE一般结合使用。
HAS_ALARM:事件是否有提醒;
duration:
如果不是重复事件,duration的值是null;
如果是重复事件(每天、每周、每月等),事件的结束时间DTEND是null,duration值为P3600S;
rrule和rdate:事件的重复规则
这个规则不复杂,但是比较繁琐,需要总结的场景比较多。
每天重复一次:
rrule=FREQ=DAILY;WKST=SU
每周重复一次:
rrule=FREQ=WEEKLY;WKST=SU;BYDAY=MO
每月重复一次:
rrule=FREQ=MONTHLY;WKST=SU;BYMONTHDAY=24
每三天重复一次:
rrule=FREQ=DAILY;INTERVAL=3;WKST=SU
每两次重复一次,重复5次:
rrule=FREQ=DAILY;COUNT=5;INTERVAL=2;WKST=SU
private String repeatRule(String rrule) {
String ruleString = "没有重复";
if (rrule != null && !rrule.equals("null") && !rrule.equals("")) {
if (rrule.contains("YEARLY")) {
ruleString = "每年重复一次";
} else if (rrule.contains("MONTHLY")) {
ruleString = "每月重复一次";
} else if (rrule.contains("WEEKLY")) {
ruleString = "每周重复一次";
} else if (rrule.contains("DAILY")) {
int interval = 1;
if (rrule.contains("INTERVAL")) {
String intervalDayNumber = intervalDayNumber(rrule);
interval = Integer.parseInt(intervalDayNumber);
}
ruleString = interval + "天重复一次";
}
if (rrule.contains("UNTIL")) {
int until = rrule.indexOf("UNTIL=") + "UNTIL=".length();
String substring = rrule.substring(until, until + 8);
ruleString = ruleString + ",截止时间到:" + substring;
}
if (rrule.contains("COUNT")) {
int count = rrule.indexOf("COUNT=") + "COUNT=".length();
String substring = rrule.substring(count);
int firstQuotationIndex = substring.indexOf(";");
ruleString = ruleString + ",重复的次数为:" + substring.substring(0, firstQuotationIndex);
}
}
return ruleString;
}
private String intervalDayNumber(String msg) {
int b1 = msg.indexOf("INTERVAL=");
int e1 = msg.indexOf(";WKST");
String dayInterval = msg.substring(b1 + "INTERVAL=".length(), e1);
return dayInterval;
}
CalendarContract.Reminders
表的每一行都表示事件的一个提醒。调用 query() 会返回事件提醒列表,且这些事件拥有给定的 EVENT_ID。
EVENT_ID:事件的ID;
可以通过ID去查找这个提醒是那个事件的提醒。
MINUTES:事件发生前的分钟数,应在达到该时间时发出提醒;
METHOD:服务器上设置的提醒方法。下列值之一:
METHOD_ALERT
METHOD_DEFAULT
METHOD_EMAIL
METHOD_SMS
CalendarContract.Instances.CONTENT_URI
表储存事件实例的开始时间和结束时间。此表中的每一行都表示一个事件实例。
EVENT_ID:该实例对应事件的 _ID;
BEGIN:事件的开始时间,单位毫秒;
END:事件的结束时间,单位毫秒;