Calendar Provider(中文版)

Calendar Provider:

英文原文:http://developer.android.com/guide/topics/providers/calendar-provider.html
版本:Android 4.0 r1
译者署名:Rongqi Fan
译者链接:
Calendar Provider

Calendar Provider是一个为用户提供日程事件的库。Calendar Provider的API允许你查询、插入、更新、删除日历、事件、会议、提醒等日程信息。
应用程序和同步适配器可以使用Calendar Provider。规则的变化依赖于程序的调用类型。本文重点讲述Calendar Provider的API使用。同步适配器的讨论在 Sync Adapters里。
通常对Calendar数据读写,应用程序需要在manifest文件里声明权限,相关信息在。为了操作更早,Calendar Provider提供了intent集,在里。这些intent帮助用户插入、查看、编辑事件。用户和calendar应用程序交互并且返回到原程序。因此,你的应用程序不需要申请权限,也不需要UI或创建事件。

目录

[隐藏]
  • 1基础
  • 2用户权限
  • 3Calendar表
    • 3.1查询一个calendar
    • 3.2修改calendar
    • 3.3插入一个calendar
  • 4事件表
    • 4.1增加事件
    • 4.2更新事件
    • 4.3删除事件
  • 5会议表
    • 5.1增加会议
  • 6提醒表
    • 6.1添加提醒
  • 7实例表
    • 7.1查询实例表
    • 7.2日历intent
    • 7.3使用一个intent来插入事件
    • 7.4使用intent来编辑事件
    • 7.5使用intent来查看calendar数据
  • 8同步适配器
  • 9译者注

基础

Calendar Provider 存储数据,应用程序可以访问这些数据。Android平台(包含Calendar Provider)的内容提供者把基于关系模型的数据集提供给程序,每行是一个记录,每列是特殊类型和意义的数据。通过Calendar Provider的API,应用程序和同步适配器读写用户的日程数据。
每个内容提供者提供一个公共的URI(包装为Uri对象),这个URI表示数据集。内容提供者控制多个数据集(多张表),这些表通过URI区分。提供者的URI是以“content://”开头的,这说明这个数据是内容提供者控制的。Calendar Provider为类(表)定义常量。这些URI的格式如:<class>.CONTENT_URI。例如: Events.CONTENT_URI。
图1 展示了Calendar Provider的数据模型。它展示了主要的表、域之间的关系。
这里有图片
用户可以有多个calendar,也可以有不同的calendar,这些calendar可以和不同的应用联系(google 日历、Exchange等等)。
CalendarContract 定义calendar的数据模型,事件信息。这些数据存储在一系列表里,如下:

表(类) 描述
CalendarContract.Calendars 这个表是特定的日历信息。每行包含单个日历的详细信息,如:名字、颜色、同步信息等等。
CalendarContract.Events 这个表存储特定的事件信息。每行包含一个事件的信息—例如:事件标题、位置、开始时间、结束时间等等。事件可以发生一次或多次。会议、提醒、扩展属性分别存储在不同的表里。它们有各自的EVENT_ID来引用表的_ID。
CalendarContract.Instances 这个表存储当前时间的开始、结束时间。表的每行表示一个单一的事件。对于发生一次的事件,有1:1映射。多次发生的事件,会自动生成多行。
CalendarContract.Attendees 这个表存储会议(来宾)事件信息。每行表示一个会议事件。它指定了来宾的类型和对应的来宾会议信息。
CalendarContract.Reminders 这个表存储闹钟/通知数据。每行表示一个闹钟事件。一个事件可以有多个提醒。提醒的数量在 MAX_REMINDERS里指定,同步适配器会设置它。提醒在事件发生前几分钟内指定,并且决定有何种发生提醒用户。

Calendar Provider的API设计的很方便有用。最重要的是它提供一个好的用户提醒,包含calendar和数据。最后,使用这些API有几点需要注意的:
插入、更新、查看calendar事件。你需要适当的权限来直接插入、修改、读取事件。然而,如果你不建立全面的calendar应用或同步适配器,这些权限是不需要的。你可以使用Android提供的intent来处理读、写calendar的操作。当你使用intent,你的应用程序发送预定义格式的操作给calendar。执行结束后,返回你的应用程序。设计你的程序来完成通常的操作,你可以为用户提供一个统一的、健壮的界面。这些是简单的建议。更多的信息在Calendar Intents里。
同步适配器。同步适配器同步calendar数据和一个服务或数据源。在CalendarContract.Calendars 和CalendarContract.Events 表里,有些列是为同步适配器预留的。这些列提供者和程序不可以修改。事实上,它们仅仅对同步适配器可见。更多关于同步适配器的信息,在Sync Adapters。

用户权限

程序需要权限来读取calendar数据。需要权限来删除、插入、更新数据。这些权限在manifest文件里声明。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"...>
   <uses-sdk android:minSdkVersion="14" />
   <uses-permission android:name="android.permission.READ_CALENDAR" />
   <uses-permission android:name="android.permission.WRITE_CALENDAR" />
   ...
</manifest>

Calendar表

CalendarContract.Calendars表包含个人calendar的详细信息。下面列出的是程序和同步适配器都可以写的。详细的域列表在CalendarContract.Calendars里。

常量 描述
NAME Calendar的名字。
CALENDAR_DISPLAY_NAME 用户看见的calendar的名字。
VISIBLE the CalendarContract.Instances table.

一个指示calendar是否可见的布尔值。0表示不可见。1表示可见。这个值影响 CalendarContract.Instances表生成行。

SYNC_EVENTS 一个指示calendar是否同步或存储数据在设备里。0表示不同步或不在设备上存储数据。1表示同步或在设备上存储数据。

查询一个calendar

下面的例子展示如何获取指定用户的calendar。在这个例子里,查询操作是在UI线程(主线程)里显示的。在实践中,这个操作应该在一个一般的线程里实现。更多的讨论,参考 Loaders。如果你不仅仅读数据,还需要修改,请读AsyncQueryHandler。
这里有代码
你为什么包含ACCOUNT_TYPE?

如果你在 Calendars.ACCOUNT_NAME上查询,你需要包含Calendars.ACCOUNT_TYPE。因为一个给定的账户给定了唯一的ACCOUNT_NAME和ACCOUNT_TYPE。ACCOUNT_TYPE是一个反映用户权限的字符串,这个权限是用户向AccountManager注册时使用的。有一个特殊的账户叫ACCOUNT_TYPE_LOCAL,它不和设备帐号联系。ACCOUNT_TYPE_LOCAL账户不是同步的。
这个例子的下一个部分,你构造查询。指定查询条件。这个例子里,查询ACCOUNT_NAME 是[email protected]和ACCOUNT_TYPE 是com.google的所有calendar。查询返回一个对象 Cursor,你可以用来转换数据库查询返回的结果集。更多关于查询的讨论,在Content Providers。
这里有代码
下一段代码,使用cursor建立结果集。使用例子一开始建立的常量来返回每个域的值。
这里有代码

修改calendar

为了更新calendar,你可以提供calendar的_ID或者作为Uri(withAppendedId())的附加ID或项的第一节。这个节应该开始于"_id=?",第一个selectionArg 应该是calendar的_ID 。你也可以编码URI的ID来更新。这个例子通过(withAppendedId())改变了calendar的显示名
这里有代码

插入一个calendar

calendar主要是由同步适配器管理,因此,你把calendar作为一个同步适配器插入。大部分的应用程序仅仅做简单的操作,如:改变显示的名字。如果程序需要创建一个本地的calendar,可以作为同步适配器插入一个calendar,使用 ACCOUNT_TYPE_LOCAL. ACCOUNT_TYPE_LOCAL 的ACCOUNT_TYPE来指定calendar的类型,这个calendar不和设备账户联系。这种类型的calendar不和服务同步。更多关于同步适配器的信息在Sync Adapters。

事件表

CalendarContract.Events表里包含所有的事件细节。增加、更新、删除事件,程序需要在manifest里包含权限WRITE_CALENDAR。
下面的事件表是对程序和同步适配器都可写的。完整的列表在CalendarContract.Events 。

常量 描述
CALENDAR_ID 包含事件的calendar的_ID。
ORGANIZER 事件的源(所有者)的Email。
TITLE 事件标题。
EVENT_LOCATION 事件发生位置。
DESCRIPTION 事件的描述。
DTSTART 事件开始的事件时间。从开始算起的毫秒(世界协调时间(Universal Time Coordinated))。
DTEND 事件结束的时间。从开始算起的毫秒(世界协调时间(Universal Time Coordinated))。
EVENT_TIMEZONE 事件的时区。
EVENT_END_TIMEZONE 事件结束事件的时区。
DURATION RFC5545 在格式的事件的事件。例如,"PT1H"的值表示事件将持续一个小时,"P2W"的值说明一个两周的时间范围。
ALL_DAY 1指示事件发生的一整天,是本地时区定义的。0指示定期事件开始和结束的时间。
RRULE 事件重复的规则。例如: "FREQ=WEEKLY;COUNT=10;WKST=SU"。你可以在here看到更多的例子。
RDATE 事件重复日期。你使用RDATE和RRULE 来定义一个合计发生的集合。更多的讨论在RFC5545 spec。
AVAILABILITY 如果这个事件忙的时间预计超过空闲的时间。
GUESTS_CAN_MODIFY 客户是否可以修改事件。
GUESTS_CAN_INVITE_OTHERS 客户是否可以邀请其它客户。
GUESTS_CAN_SEE_GUESTS 客户是否可以看到日程列表。

增加事件

当你插入一个事件的时候,我们建议你使用 INSERT intent,细节在Using an intent to insert an event。然而,你需要直接插入事件。这一节将告诉你如何实现。
插入新事件的规则:
你需要包含 CALENDAR_ID和 DTSTART。
你需要包含EVENT_TIMEZONE。 getAvailableIDs()使用获取系统安装的时区IDs的列表。注意:这个方法不适用于通过INSERT intent插入一个事件,在 Using an intent to insert an event里有详细的描述—那种情况下,选择默认时区。非循环事件,包含DTEND。
循环事件,包含一个附加RRULE或 RDATE的 DURATION。注意:这个方法不适用于通过 INSERT intent插入一个事件,在 Using an intent to insert an event里有详细的描述—你可以使用联系DTSTART和DTEND的RRULE,日历程序把它转换成自动的。
下面的例子是插入一个事件。这个程序在UI线程里实现。实际上,插入和更新应该在一个同步线程里完成并且在后台执行。更多的知识阅读 AsyncQueryHandler。
这里有代码
注意:留意这个例子是如何在事件创建后获取事件ID的。这是获取事件ID的最简单的方法了。你需要一个事件ID提供给日历操作—例如:向事件增加一个会议或提醒。

更新事件

当你允许用户编辑事件,我们建议你使用EDITintent,在 Using an intent to edit an event里有详细描述。然而,你也可以直接编辑事件。使用事件来更新,你提供事件的 _ID ,要么通过向Uri(withAppendedId())附加ID,也可以作为项的第一节。这个节以"_id=?"开始,第一个selectionArg 应该是事件ID。你可以不使用ID来更新。这个例子展示更新事件。它通过 withAppendedId()函数改变事件标题。
这里有代码

删除事件

你可以通过附加于URI后的ID来删除事件,也可以通过标准节。如果你使用附加ID,你吧可以使用节。有两种删除方法:应用程序或同步适配器。程序删除就设置列为1。这个标志告诉适配器这一行是删除了的,这个操作也广播给服务。同步适配器删除是从数据库里移除所有相关数据。下面的例子是程序通过事件ID来删除事件:
这里有代码

会议表

CalendarContract.Attendees表的每行表示一个事件的单独的会议或来宾。调用query() 返回给定 EVENT_ID事件的会议列表。EVENT_ID 必须匹配特定事件的ID。
下面的表示可写域。插入新的会议,你需要包含除ATTENDEE_NAME以外的所有。

常量 描述
EVENT_ID 事件ID。
ATTENDEE_NAME 会议名字。
ATTENDEE_EMAIL 会议eamil地址。
ATTENDEE_RELATIONSHIP 事件会议的关系。下面的一个:
RELATIONSHIP_ATTENDEE
RELATIONSHIP_NONE
RELATIONSHIP_ORGANIZER
RELATIONSHIP_PERFORMER
RELATIONSHIP_SPEAKER
ATTENDEE_TYPE 会议类型。下面一个:
TYPE_REQUIRED
TYPE_OPTIONAL
ATTENDEE_STATUS 会议状态。下面的一个:
ATTENDEE_STATUS_ACCEPTED
ATTENDEE_STATUS_DECLINED
ATTENDEE_STATUS_INVITED
ATTENDEE_STATUS_NONE
ATTENDEE_STATUS_TENTATIVE

增加会议

下面的例子是增加一个单独的会议。注意 EVENT_ID是必须的:
这里有代码

提醒表

CalendarContract.Reminders表的每行表示一个事件的单独的会议或来宾。调用query() 返回给定 EVENT_ID事件的会议列表。
下表是提醒的可写域。它们都需要包含何时插入一个提醒。注意:同步适配器指定提醒类型,支持的类型都在表 CalendarContract.Calendars里。更多信息在ALLOWED_REMINDERS。

常量 描述
EVENT_ID 事件ID。
MINUTES 提醒需要提前多少分钟告警。
METHOD 告警方式,在服务集上。下面的一个:
METHOD_ALERT
METHOD_DEFAULT
METHOD_EMAIL
METHOD_SMS

添加提醒

例子添加一个提醒。提醒在事件前15分钟告警。
这里有代码

实例表

表存储了一个事件的开始、结束时间。每行表示一个单独的事件。这个实例表示不可写的并且提供一个查询事件的方法。下表是你可以查询实例的域。注意:时区是通过KEY_TIMEZONE_TYPE和KEY_TIMEZONE_INSTANCES定义的。
表格设计:

常量 描述
BEGIN 实例开始的时间,单位是UTC毫秒。
END 实例结束时间,单位是UTC毫秒。
END_DAY 实例儒略日期结束时间,和calendar的时区联系。
END_MINUTE 实例结束时间,从午夜开始计算。
EVENT_ID 实例事件的ID。
START_DAY 实例的儒略日期的开始时间,和calendar的时区联系。
START_MINUTE 实例开始时间,从午夜开始计算。

查询实例表

查询实例表,你需要指定URI的查询时间范围。例子里: CalendarContract.Instances通过它实现的 CalendarContract.EventsColumns接口访问TITLE域。换句话说,TITLE 是通过数据库视图返回的,不通过原始的 CalendarContract.Instances表查询得到。
这里有代码

日历intent

你的程序不需要读写日历数据的权限。可以通过android系统提供的intent来完成读写操作。下表列出了calendar provider支持的intent:
这里表格
下表列出来calendar provider提供的扩展项:

行为 URI 描述 扩展
VIEW content://com.android.calendar/time/<ms_since_epoch>你可以通过CalendarContract.CONTENT_URI来引用URI。例如使用这个intent,阅读Using intents to view calendar data。 通过指定<ms_since_epoch>来打开calendar。 没有。
VIEW content://com.android.calendar/events/<event_id>你可以通过Events.CONTENT_URI引用URI。例如使用intent,阅读Using intents to view calendar data。 指定<event_id>来显示事件 CalendarContract.EXTRA_EVENT_BEGIN_TIME
CalendarContract.EXTRA_EVENT_END_TIME
EDIT content://com.android.calendar/events/<event_id>你可以通过Events.CONTENT_URI引用URI。例如使用intent,阅读Using an intent to edit an event。 指定<event_id>来编辑事件。 CalendarContract.EXTRA_EVENT_BEGIN_TIME
CalendarContract.EXTRA_EVENT_END_TIME
EDIT
INSERT
content://com.android.calendar/events你可以通过Events.CONTENT_URI引用URI。例如使用intent,阅读 Using an intent to insert an event。 创建一个事件。 下表里的任何扩展项。

下面描述如何使用这些intent。

使用一个intent来插入事件

使用INSERT intent来处理事件插入任务。通过这种方法,程序不需要在manifest文件里声明WRITE_CALENDAR 权限。但用户使用这个方法运行程序,程序发送它们到一个calendar来结束添加事件。 INSERT Intent使用扩展域来预填充事件的细节格式。用户可以取消事件,按需编辑格式,保存事件。
这段代码是一个事件的日程,在2012年1月19号,从7:30am执行到8:30am。注意下面代码:
它把 Events.CONTENT_URI作为了Uri。
使用CalendarContract.EXTRA_EVENT_BEGIN_TIME和CalendarContract.EXTRA_EVENT_END_TIME扩展域来预填充事件的时间格式。这些时间值单位是UTC毫秒。
它使用Intent.EXTRA_EMAIL扩展域提供以逗号分隔的与会者列表,通过email地址指定。
这里有代码

使用intent来编辑事件

你可以直接更新事件,详细的内容在Updating events。但是使用 VIEW intent可以让程序在没有权限的情况下编辑calendar。当用户完成编辑,返回到原来的程序。
这个例子展示设置一个新的标题,并且用户编辑calendar的事件。
这里有代码

使用intent来查看calendar数据

Calendar provider提供两种方法来使用VIEWintent:
打开calendar的特定日期。
查看事件。
这个例子展示如何打开一个特定的日期;
这里有代码
这个例子展示如何以视图打开一个事件:
这里有代码

同步适配器

访问calendar,程序和同步适配器仅仅有一小点不同:
同步适配器设置CALLER_IS_SYNCADAPTER 为ture。
同步适配器需要在URI里提供ACCOUNT_NAME 和 ACCOUNT_TYPE作为查询参数。
同步适配器比查询或组件有更多的读写权限。例如,程序仅仅可以修改calendar的属性,如:名字、显示名、可见性、calendar是否同步。但是同步适配器还可以修改其它,如:颜色、时区、访问级别、位置等等。然而,同步适配器可以通过设置 ACCOUNT_NAME和 ACCOUNT_TYPE来限制。
你可以使用一个帮助函数通过使用同步适配器来返回URI:
这里有代码
实现同步适配器的例子(不专门是和calendar联系)在SampleSyncAdapter。

译者注

1、格式还没有严格调整
2、还没有添加代码

你可能感兴趣的:(android,timezone,calendar,存储,insert,日历)