申请动态权限
日历的content Provider的uri
private static String CALENDER_URL = "content://com.android.calendar/calendars";
private static String CALENDER_EVENT_URL = "content://com.android.calendar/events";
private static String CALENDER_REMINDER_URL = "content://com.android.calendar/reminders";
添加日历行程
解题思路:通过ContentProvider向系统日历中添加数据
日历提供程序是用户日历事件的存储区。您可以利用 Calendar Provider API 对日历、事件、参加者、提醒等执行查询、插入、更新和删除操作。
我们先来看一下Android jar包有关于日历提供的Provider
CalendarContract定义了日历和日程事件相关的数据模型:
CalendarContract.Calendars :此表储存日历特定信息。 此表中的每一行都包含一个日历的详细信息,例如名称、颜色、同步信息等。
CalendarContract.Events :此表储存事件特定信息。 此表中的每一行都包含一个事件的信息 — 例如事件标题、地点、开始时间、结束时间等。 事件可一次性发生,也可多次重复发生。参加者、提醒和扩展属性存储在单独的表内。它们各自具有一个 EVENT_ID,用于引用 Events 表中的 _ID。
CalendarContract.Instances : 此表储存每个事件实例的开始时间和结束时间。 此表中的每一行都表示一个事件实例。 对于一次性事件,实例与事件为 1:1 映射。对于重复事件,会自动生成多个行,分别对应多个事件实例。
CalendarContract.Attendees : 此表储存事件参加者(来宾)信息。 每一行都表示事件的一位来宾。 它指定来宾的类型以及事件的来宾出席响应。
CalendarContract.Reminders :此表储存提醒/通知数据。 每一行都表示事件的一个提醒。一个事件可以有多个提醒。 每个事件的最大提醒数量在 MAX_REMINDERS 中指定,后者由拥有给定日历的同步适配器设置。 提醒以事件发生前的分钟数形式指定,其具有一个可决定用户提醒方式的方法。
Claendar常量:(日历表)
Calendar的必须添加常量:
ACCOUNT_NAME :The account that was used to sync the entry to the device.
ACCOUNT_TYPE :The type of the account that was used to sync the entry to the device.
NAME:The name of the calendar. Column name.
CALENDAR_DISPLAY_NAME :The display name of the calendar. Column name.
CALENDAR_COLOR :The color of the calendar. This should only be updated by the sync adapter, not other apps, as changing a calendar's color can adversely affect its display.
CALENDAR_ACCESS_LEVEL :The level of access that the user has for the calendar
OWNER_ACCOUNT:The owner account for this calendar, based on the calendar feed. This will be different from the _SYNC_ACCOUNT for delegated calendars. Column name.
对于给定账户,只有在同时指定account_name和account_type时才能将其视为唯一账户,account_type字符串对应于AccountManager出注册账户时的账户验证器。
Calendar的建议添加常量:
SYNC_EVENTS :Is this calendar synced and are its events stored on the device? 0 - Do not sync this calendar or store events for this calendar. 1 - Sync down events for this calendar.
CALENDAR_TIME_ZONE:The time zone the calendar is associated with.
ALLOWED_REMINDERS :A comma separated list of reminder methods supported for this calendar in the format "#,#,#".
ALLOWED_AVAILABILITY :A comma separated list of availability types supported for this calendar in the format "#,#,#".
ALLOWED_ATTENDEE_TYPES :A comma separated list of attendee types supported for this calendar in the format "#,#,#".
Event常量:(事件表,所属日历表)
CALENDAR_ID:事件所属日历的id
ORGANIZER:事件组织者(所有者)的电子邮件。
TITLE:事件的标题。
EVENT_LOCATION:事件的发生地点。
DESCRIPTION:事件的描述
DTSTART:事件开始时间,以从公元纪年开始计算的协调世界时毫秒数表示。
DTEND:事件结束时间,以从公元纪年开始计算的协调世界时毫秒数表示。
EVENT_TIMEZONE:事件的时区。
EVENT_END_TIMEZONE:事件结束时间的时区。
DURATION:RFC5545式的事件持续时间。例如,值为 "PT1H" 表示事件应持续一小时,值为 "P2W" 表示持续 2 周。
ALL_DAY:值为 1 表示此事件占用一整天(按照本地时区的定义)。 值为 0 表示它是常规事件,可在一天内的任何时间开始和结束。
RRULE: 事件的重复发生规则格式。例如,"FREQ=WEEKLY;COUNT=10;WKST=SU"。
RDATE:事件的重复发生日期,RRULE和RDATE通常联合用于定义一组聚合重复实例,具体参考RFC5545规范
AVAILABILITY:将此事件视为忙碌时间还是可调度的空闲时间。
GUESTS_CAN_MODIFY :来宾是否可修改事件。
GUESTS_CAN_INVITE_OTHERS :来宾是否可邀请其他来宾。
GUESTS_CAN_SEE_GUESTS:来宾是否可查看参加者列表。
Reminder常量 :(提醒表,所属事件表)
- EVENT_ID: 事件id
- MINUTES: 事件发生前的分钟数,应在达到该时间时发出提醒
- METHOD: 提醒方式,有:
METHOD_ALERT, METHOD_DEFAULT,
METHOD_EMAIL, METHOD_SMS
Instances常量:(实例表,所属事件表,与事件一对一映射关系,详细解析见上文)
- BEGIN: 实例的开始时间,以协调世界时毫秒数表示。
- END: 实例的结束时间,以协调世界时毫秒数表示。
- START_DAY: 与日历时区相应的实例儒略历开始日。
- END_DAY: 与日历时区相应的实例儒略历结束日。
- START_MINUTE: 从日历时区午夜开始计算的实例开始时间(分钟)。
- END_MINUTE: 从日历时区午夜开始计算的实例结束时间(分钟)。
- EVENT_ID: 该实例对应事件的 _ID。
向系统Calendar中添加Event
public class CalendarProviderUtil {
// ContentProvider的uri
private static Uri calendarUri = CalendarContract.Calendars.CONTENT_URI;
private static Uri eventUri = CalendarContract.Events.CONTENT_URI;
private static Uri reminderUri = CalendarContract.Reminders.CONTENT_URI;
private static ContentResolver contentResolver;
/**
* 检查是否有日历表,有返回日历id,没有-1
* */
private static int isHaveCalender(){
// 查询日历表的cursor
Cursor cursor = contentResolver.query(calendarUri,null,null,null,null);
if (cursor == null || cursor.getCount() == 0){
return -1;
}else {
// 如果有日历表
try {
cursor.moveToFirst();
// 通过cursor返回日历表的第一行的属性值 第一个日历的id
return cursor.getInt(cursor.getColumnIndex(CalendarContract.Calendars._ID));
}finally {
cursor.close();
}
}
}
/**
* 添加日历表
* */
private static long addCalendar(){
// 时区
TimeZone timeZone = TimeZone.getDefault();
// 配置Calendar
ContentValues value = new ContentValues();
value.put(CalendarContract.Calendars.NAME, "我的日历表");
value.put(CalendarContract.Calendars.ACCOUNT_NAME, "myAccount");
value.put(CalendarContract.Calendars.ACCOUNT_TYPE, "myType");
value.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "myDisplayName");
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, "myAccount");
value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0);
value.put(CalendarContract.CALLER_IS_SYNCADAPTER,true);
// 插入calendar
Uri insertCalendarUri = contentResolver.insert(calendarUri,value);
if (insertCalendarUri == null){
return -1;
}else {
// return Integer.parseInt(insertCalendarUri.toString());
return ContentUris.parseId(insertCalendarUri);
}
}
/**
* 添加日历事件
* */
public static void addEvent(Context context){
// 创建contentResolver
contentResolver = context.getContentResolver();
// 日历表id
int calendarId = isHaveCalender();
if (calendarId == -1){
addCalendar();
calendarId = isHaveCalender();
}
// startMillis
Calendar beginTime = Calendar.getInstance();
beginTime.set(2019,8,15);
long startMillis = beginTime.getTimeInMillis();
// endMillis
Calendar endTime = Calendar.getInstance();
endTime.set(2019,8,15);
long endMillis = endTime.getTimeInMillis();
// 准备event
ContentValues valueEvent = new ContentValues();
valueEvent.put(CalendarContract.Events.DTSTART,startMillis);
valueEvent.put(CalendarContract.Events.DTEND,endMillis);
valueEvent.put(CalendarContract.Events.TITLE,"事件标题");
valueEvent.put(CalendarContract.Events.DESCRIPTION,"事件描述");
valueEvent.put(CalendarContract.Events.CALENDAR_ID,calendarId);
valueEvent.put(CalendarContract.Events.EVENT_TIMEZONE,"Asia/Shanghai");
// 添加event
Uri insertEventUri = contentResolver.insert(eventUri,valueEvent);
if (insertEventUri == null){
Toast.makeText(context,"添加event失败",Toast.LENGTH_SHORT).show();
}
// 添加提醒
long eventId = ContentUris.parseId(insertEventUri);
ContentValues valueReminder = new ContentValues();
valueReminder.put(CalendarContract.Reminders.EVENT_ID,eventId);
valueReminder.put(CalendarContract.Reminders.MINUTES,15);
valueReminder.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALARM);
Uri insertReminderUri = contentResolver.insert(reminderUri,valueReminder);
if (insertReminderUri == null){
Toast.makeText(context,"添加reminder失败",Toast.LENGTH_SHORT).show();
}
}
}
只测试了一下,有用,可能有bug