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或创建事件。
目录[隐藏] |
基础
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 是sampleuser@google.com和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、还没有添加代码
今天的文章Calendar Provider(中文版)分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/25664.html