前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发-API指南- Calendar Provider

Android开发-API指南- Calendar Provider

作者头像
全栈程序员站长
发布2022-09-07 11:45:20
1.4K0
发布2022-09-07 11:45:20
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

Calendar Provider

英文原文:http://developer.android.com/guide/topics/providers/calendar-provider.html 采集日期:2015-05-10

在本文中

  1. 基础知识
  2. 用户权限
  3. 日程表
    1. 查询日程
    2. 修改日程
    3. 插入日程
  4. events 表
    1. 添加 events 数据
    2. 更新 events 数据
    3. 删除 events 数据
  5. attendees 表
    1. 添加 attendees 数据
  6. reminders 表
    1. 添加 reminders 数据
  7. instances 表
    1. 查询 instances 表
  8. 日历 Intent
    1. 利用 Intent 插入事件
    2. 利用 Intent 编辑事件
    3. 利用 Intent 查看日历数据
  9. Sync Adapter

关键类

  1. CalendarContract.Calendars
  2. CalendarContract.Events
  3. CalendarContract.Attendees
  4. CalendarContract.Reminders

Calendar Provider 是用来存放用户日历事件(event)的数据库。 通过 Calendar Provider 的 API ,可以完成对 calendars、events、attendees、reminders 表的查询、插入、修改和删除等操作。

应用程序和 Sync Adapter 都可以使用 Calender Provider API。 对于这两种不同类型的程序,调用的规则也不一样。 本文的重点是介绍应用程序是如何使用 Calender Provider API 的。 Sync Adapter 的使用方式会有所不同,请参阅Sync Adapters

通常,如果要读写日历数据,应用程序必须在 Manifest 文件中声明相应的权限,这在用户权限一节中将会介绍。 为了便于完成一些常见的操作, Calender Provider 提供了一些 Intent,这将在Calendar Intent一节中介绍。 这些 Intent 可以让用户打开 Calendar 应用,并完成插入、查看、编辑事件的操作。 用户在 Calendar 应用中完成交互后,将返回初始的应用中。 这样发起方应用就不必申请相应权限,也不需要提供浏览和创建事件的用户界面了。

基础知识

Content Provider 负责存放数据并提供数据访问方式。 Android 系统内置的 Content Provider (包括 Calendar Provider)一般是以关系型数据库表的形式提供数据的, 行数据代表一条记录,列数据表示字段类型和意义。 应用程序和 Sync Adapter 通过 Calendar Provider API 来访问数据库表中的用户日历数据。

每个 Content Provider 都会公开一个公共的 URI (封装为一个 Uri 对象),它唯一标识了某部分数据。 如果 Content Provider 管理着多组数据(多张数据表),则各组数据都会有单独的 URI。 所有用于 Provider 的 URI 都以字符串 “content://” 开头,表示这些数据是由某个 Content Provider 进行管理的。 Calendar Provider 为其内部类(表)的 URI 定义了很多常量。这些 URI 的格式均为 <class>.CONTENT_URI。比如 Events.CONTENT_URI

图 1 为 Calendar Provider 数据模型的示意图,给出了主表及与其他表的关联字段。

<span role="heading" aria-level="2">Android开发-API指南- Calendar Provider
<span role="heading" aria-level="2">Android开发-API指南- Calendar Provider

图 1. Calendar Provider 数据模型

一个用户可以拥有多个 Calendar,每个 Calendar 可以与不同类型的帐号关联(Google Calendar、Exchange 等)。

CalendarContract 定义了 Calendar 和 Event 的数据模型。这些数据存放在以下数据表中。

数据表(类)

说明

CalendarContract.Calendars

该表存放日程的定义数据。每行表示一条日程的详细信息,如名称、颜色、同步信息等。

CalendarContract.Events

该表存放事件的定义数据。每行表示一个事件,内容包括 — 事件标题、位置、起始时间、结束时间等等。 事件可以是一次性的,也可以重复多次触发。 参与人员、提醒闹钟及附加属性都存放在其他表中,并通过 EVENT_ID 字段与 Events 表中的 _ID 关联。

CalendarContract.Instances

该表存放事件每次触发时的起始时间和结束时间。一次性事件只会1:1对应一条实例记录。 对于重复触发的事件而言,则会自动生成多条实例记录,对应每一次的触发。

CalendarContract.Attendees

该表存放事件的参与人员(来宾)信息。每行代表一位人员。 内容包括人员类型和与会反馈。

CalendarContract.Reminders

该表存放闹钟/通知数据。每行代表一次闹钟提醒。 一个事件可以拥有多个闹钟提醒。每个事件可拥有的最大提醒数在 MAX_REMINDERS 中定义,这是由拥有该日程的 sync adapter 设置的。 提醒定义了事件触发前的分钟数,以及提醒用户的方式。

Calendar Provider API 的设计初衷,是既要灵活又要功能强大。另一方面,良好的用户体验、保证日程数据的安全也非常重要。 为此,在使用这些 API 时,必须注意以下几点:

  • 插入、更新和查询日程事件。 如果要直接插入、修改和查询 Calendar Provider 中的事件数据,需要获得合适的权限。 不过,如果还未建立完整的日历应用或 Sync Adapter,就没必要申请这些权限。 这时就可以通过 Intent,把读写操作交给 Android 内置 Calendar 应用去完成。 在使用这些 Intent 时,用户会被带入 Calendar 应用,在预置的表单中进行操作。待操作完毕后,再返回调用方应用。 通过这种调用内置 Calendar 来完成常用操作的方式,可以向用户提供一种风格统一、容错性较强的界面。 这也是推荐的访问方式。详情请参阅Calendar Intent
  • Sync Adapter。 Sync Adapter 负责将用户设备上的日程数据与服务器或数据源保持同步。在 CalendarContract.CalendarsCalendarContract.Events 表中,有些字段是留给 Sync Adapter 使用的。 Provider 和应用程序都不要去修改这些字段中的数据。 实际上只有以 Sync Adapter 的方式去访问时,这些字段才是可见的。 关于 Sync Adapter 的详细信息,请参阅 Sync Adapter

用户权限

如果要读取日程数据,应用程序必须在 Manifest 文件中包含 READ_CALENDAR 权限。如果是删除、插入或修改日程数据,则必须包含 WRITE_CALENDAR 权限:

代码语言:javascript
复制
<?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>

Calendars 表

CalendarContract.Calendars 表存放着每项日程的详细信息。 以下字段均可由应用程序和 Sync Adapter 写入。 完整的字段清单请参阅手册 CalendarContract.Calendars

常量名称

说明

NAME

日程的名称。

CALENDAR_DISPLAY_NAME

向用户显示的日程名称。

VISIBLE

布尔值,标明该日程是否可见。 为 0 表示不显示与该日程关联的事件,为 1 则表示需要显示。 该值将会影响 CalendarContract.Instances 表中生成的记录。

SYNC_EVENTS

布尔值,标明该日程是否需要同步,及事件是否需要本地保存。 为 0 表示不需要同步或者不保存。为 1 则表示应该同步并在设备中保存事件。

查询日程

以下例子演示了如何读取某个用户的日程信息。 为了简化起见,查询操作是在用户界面线程(“主线程”)中进行的。 在实际应用中,这步操作不应放在主线程中,而应该在异步线程中完成。更多信息,请参阅Loaders。 如果不仅要读取数据,还要修改的话,请参阅 AsyncQueryHandler

代码语言:javascript
复制
// 映射数组。为数组建立索引,就不需要动态检索,以便提高性能。
public static final String[] EVENT_PROJECTION = new String[] {
    Calendars._ID,                           // 0
    Calendars.ACCOUNT_NAME,                  // 1
    Calendars.CALENDAR_DISPLAY_NAME,         // 2
    Calendars.OWNER_ACCOUNT                  // 3
};
  
// 映射数组的索引
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;

为什么查询条件中必须包含 ACCOUNT_TYPE字段 ?

如果要查询 Calendars.ACCOUNT_NAME 字段,就必须在查询语句中包含 Calendars.ACCOUNT_TYPE 字段。这是因为 ACCOUNT_NAME 及其 ACCOUNT_TYPE 合在一起才能唯一确定一个账户。 ACCOUNT_TYPE 是与认证方式(authenticator)对应的一个字符串,在使用 AccountManager 注册账户时需要用到这个认证方式。 对于那些和账户无关的日程,还有一种特殊的账户类型,叫做 ACCOUNT_TYPE_LOCALACCOUNT_TYPE_LOCAL 类型的账户不会进行同步。

接下来就是构建查询,在查询语句中指定查询条件。 这里要查询的日程,ACCOUNT_NAME为“sampleuser@google.com”, ACCOUNT_TYPE为“com.google”,OWNER_ACCOUNT为“sampleuser@google.com”。 如果要查询某用户可查看的所有日程,而不仅限于属于用户自己的日程,请去掉OWNER_ACCOUNT条件。 查询将会返回一个 Cursor 对象,通过该游标可以遍历返回的结果数据集。 关于 Content Provider 查询的更多介绍,请参阅 Content Provider

代码语言:javascript
复制
// 执行查询
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;   
String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
                        + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                        + Calendars.OWNER_ACCOUNT + " = ?))";
String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
        "sampleuser@gmail.com"}; 
// 提交查询并获取结果 Cursor 对象。
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

下面通过游标遍历查询结果。 这里用到了一开始定义的常量,返回各个字段的数据。

代码语言:javascript
复制
// 利用游标遍历结果记录集
while (cur.moveToNext()) {
    long calID = 0;
    String displayName = null;
    String accountName = null;
    String ownerName = null;
      
    // 读取各个字段的数据
    calID = cur.getLong(PROJECTION_ID_INDEX);
    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
              
    // 用这些数据进行一些操作...

   ...
}

修改日程

如果要修改日程数据,可以把该项日程的 _ID 作为 URI (withAppendedId()) 的附带 ID 参数,或者作为第一个查询条件。 作为查询条件时,应该以"_id=?"开头,第一个参数selectionArg应该是该项日程的 _ID。 还可以把 ID 加入 URI 编码中执行数据更新操作。 以下给出了通过 URI 方式 (withAppendedId()) 修改日程显示名称的例子:

代码语言:javascript
复制
private static final String DEBUG_TAG = "MyActivity";
...
long calID = 2;
ContentValues values = new ContentValues();
// 该日程的新名称
values.put(Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar");
Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);

插入日程

日程本来就设计为主要由 Sync Adapter 来维护的,因此只能由一个 Sync Adapter 来插入一项新的日程。 多数情况下,应用程序只能对日程做一些外观上的修改,比如修改显示名称。 如果应用程序需要新建一项日程,可以作为 Sync Adapter 来执行插入操作, ACCOUNT_TYPE 设为 ACCOUNT_TYPE_LOCALACCOUNT_TYPE_LOCAL 是一种专为日程设计的特殊账户,它不与实际的本地账户关联。 这种日程数据也不会与服务器同步。 关于 Sync Adapter 的介绍,请参阅 Sync Adapter

Events 表

CalendarContract.Events 表存放着每个事件的详细信息。 如果要新增、修改或删除事件,应用程序必须在 Manifest 文件 中包含 WRITE_CALENDAR 权限。

以下字段均可由应用程序和 Sync Adapter 写入。 完整的字段清单,请参阅手册 CalendarContract.Events

常量

说明

CALENDAR_ID

事件所属日程的 _ID

ORGANIZER

日程编制者(所有者)的 Email。

TITLE

事件标题。

EVENT_LOCATION

事件所在地。

DESCRIPTION

事件说明。

DTSTART

事件起始 UTC 时间,单位为自1970年1月1日以来的毫秒数。

DTEND

事件结束 UTC 时间,单位为自1970年1月1日以来的毫秒数。

EVENT_TIMEZONE

事件时区。

EVENT_END_TIMEZONE

事件结束时间的时区。

DURATION

事件的持续时间,格式为RFC5545。 比如,"PT1H"表示事件会持续 1 小时,"P2W"则表示持续 2 周。

ALL_DAY

为 1 表示该事件会占用全天时间,类似于时区设置中的定义。 为 0 表示其为常规事件,可以在一天中的任意时刻开始和结束。

RRULE

事件重复规则。比如:"FREQ=WEEKLY;COUNT=10;WKST=SU"。 更多示例请查看 RFC5545。

RDATE

事件重复的日期。通常是把 RDATE 与 RRULE 结合起来定义一组重复规则。详情请参阅 RFC5545 说明。

AVAILABILITY

标明该事件是在空闲时参与调度,还是在忙时参与。

GUESTS_CAN_MODIFY

来宾是否可以修改事件。

GUESTS_CAN_INVITE_OTHERS

来宾是否可以邀请其他人参加。

GUESTS_CAN_SEE_GUESTS

来宾是否能看到参加人员名单。

添加事件

推荐使用 INSERT 来插入一条新的事件,这在 利用 Intent 插入事件 一节中将会介绍。 不过在必要时,也可以直接插入一条事件记录。本节将介绍这种方式。

下面列出了插入新事件需要遵守的规则:

下面给出一个插入事件的例子。简化起见,此例运行于 UI 线程中。 在实际应用中,插入和修改操作都应该在后台的异步线程中完成。详情请参阅 AsyncQueryHandler

代码语言:javascript
复制
long calID = 3;
long startMillis = 0; 
long endMillis = 0;     
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 9, 14, 7, 30);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 9, 14, 8, 45);
endMillis = endTime.getTimeInMillis();
...

ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);
values.put(Events.TITLE, "Jazzercise");
values.put(Events.DESCRIPTION, "Group workout");
values.put(Events.CALENDAR_ID, calID);
values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
Uri uri = cr.insert(Events.CONTENT_URI, values);

// 读取事件 ID,也就是 Uri 的最后一部分
long eventID = Long.parseLong(uri.getLastPathSegment());
// 
// ... 利用 ID 完成一些处理
//
//

注意: 上述例子中,读取已创建事件 ID 的方式是一种最简单的方法。 在实际应用中,往往需要利用事件 ID 来对日程进行某些操作 — 比如:添加参与人员、增加事件提醒。

修改事件

如果需要让用户编辑事件,建议使用 EDIT Intent,这在 利用 Intent 编辑事件 一节中将会介绍。 不过在必要时,也可以直接编辑事件。 在修改事件时,给出事件 _ID 的方式可以是附在 Uri 后面( withAppendedId() ),也可以是作为查询条件的第一个参数。 查询条件应该以 "_id=?" 开头,第一个 selectionArg 应该是事件的 _ID 。 也可以使用不带 ID 的查询语句来更新数据。 下面给出一个更新事件数据的例子,这里将用 withAppendedId() 的方式修改事件的标题:

代码语言:javascript
复制
private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 188;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri updateUri = null;
// 新的标题
values.put(Events.TITLE, "Kickboxing"); 
updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);  

删除事件

可以将 _ID 附在 URI 后面进行删除操作,也可以用标准的查询语句来完成。 如果采用前一种方式,就不能再用查询语句的方式。 删除操作有两种版本:作为应用程序、作为 Sync Adapter。 应用程序版本的删除就是把 deleted 字段置为 1。这会告诉 Sync Adapter 此条记录已被删除,同时服务器上也应该完成删除操作。 Sync Adapter 版本的删除则会在数据库中删除该条事件及所有相关数据。 以下例子演示了应用程序版本的删除,用到了 _ID

代码语言:javascript
复制
private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().delete(deleteUri, null, null);
Log.i(DEBUG_TAG, "Rows deleted: " + rows);  

Attendees 表

CalendarContract.Attendees 表的每行记录代表参加事件的一位人员(来宾)。以 EVENT_ID 为参数调用 query() ,将会返回该事件的参加人员清单。这里的 EVENT_ID 必须与事件的实际 _ID一致。

下表列出了 Attendees 表中可供写入的字段。在插入新的人员记录时,必须包含除ATTENDEE_NAME外的所有这些字段。

常量名称

说明

EVENT_ID

事件 ID。

ATTENDEE_NAME

参加人员的姓名。

ATTENDEE_EMAIL

参加人员的 Email 地址。

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

ATTENDEE_TYPE 参加人员的类型。可为下列值之一:

ATTENDEE_STATUS 参加人员的出席状况。可为下列值之一:

添加参加人员

以下给出了添加一个事件参与人员的例子。 请注意必须要给出 EVENT_ID

代码语言:javascript
复制
long eventID = 202;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Attendees.ATTENDEE_NAME, "Trevor");
values.put(Attendees.ATTENDEE_EMAIL, "trevor@example.com");
values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
values.put(Attendees.EVENT_ID, eventID);
Uri uri = cr.insert(Attendees.CONTENT_URI, values);

Reminders 表

CalendarContract.Reminders 表的每行记录代表针对某事件的一条系统提醒。以 EVENT_ID 为参数调用 query() 时,将会返回相关系统提醒的清单。

下表列出了 Reminders 表中可供写入的字段。 在插入一条新的提醒数据时,必须包含所有这些字段。 请注意,在 CalendarContract.Calendars 表中,定义了 Sync Adapter 支持的提醒类型。 详情请参阅 ALLOWED_REMINDERS

常量名称

说明

EVENT_ID

事件 ID。

MINUTES

在事件发生之前多少分钟进行提醒。

METHOD

提醒方式,这是服务器上的设置。可为下列值之一: METHOD_ALERT METHOD_DEFAULT METHOD_EMAIL METHOD_SMS

添加提醒

下属例子为某个事件添加了一条提醒。这条提醒将会在事件发生前 15 分钟触发。

代码语言:javascript
复制
long eventID = 221;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Reminders.MINUTES, 15);
values.put(Reminders.EVENT_ID, eventID);
values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
Uri uri = cr.insert(Reminders.CONTENT_URI, values);

Instances 表

CalendarContract.Instances 表存放着事件的起始和结束时间。 每行记录代表事件的一次实例。 Instances 是不可写的,仅用于查询事件的发生经历。

下表列出了 Instances 表中可供查询的部分字段。 请注意时区是由 KEY_TIMEZONE_TYPEKEY_TIMEZONE_INSTANCES 定义的。

常量

说明

BEGIN

事件该次实例的起始时间,单位为 UTC 毫秒数。

END

事件该次实例的结束时间,单位为 UTC 毫秒数。

END_DAY

事件该次实例的结束日期,Julian 历法,并与 Calendar 当前时区相关。

END_MINUTE

事件该次实例的结束时间,单位是自 Calendar 当前时区 0 点开始的分钟数。

EVENT_ID

该次实例的事件 _ID 。

START_DAY

事件该次实例的开始日期,Julian 历法,并与 Calendar 当前时区相关。

START_MINUTE

事件该次实例的开始时间,单位是自 Calendar 当前时区 0 点开始的分钟数。

查询 Instances 表

如果要查询 Instances 表,需要在查询 URI 中指定一个时间范围。 在以下例子中,通过实现 CalendarContract.EventsColumns 接口, CalendarContract.Instances 读取了 TITLE 字段。也就是说,通过数据库映射层返回了 TITLE ,而不是通过查询底层数据表 CalendarContract.Instances

代码语言:javascript
复制
private static final String DEBUG_TAG = "MyActivity";
public static final String[] INSTANCE_PROJECTION = new String[] {
    Instances.EVENT_ID,      // 0
    Instances.BEGIN,         // 1
    Instances.TITLE          // 2
  };
  
// 为上面的映射数组定义索引常量
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_BEGIN_INDEX = 1;
private static final int PROJECTION_TITLE_INDEX = 2;
...

// 定义要查询的事件实例的日期范围
Calendar beginTime = Calendar.getInstance();
beginTime.set(2011, 9, 23, 8, 0);
long startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2011, 10, 24, 8, 0);
long endMillis = endTime.getTimeInMillis();
  
Cursor cur = null;
ContentResolver cr = getContentResolver();

// 要在 Instances 表中查询的事件 ID 
String selection = Instances.EVENT_ID + " = ?";
String[] selectionArgs = new String[] {"207"};

// 根据日期范围构造查询
Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMillis);
ContentUris.appendId(builder, endMillis);

// 提交查询
cur =  cr.query(builder.build(), 
    INSTANCE_PROJECTION, 
    selection, 
    selectionArgs, 
    null);
   
while (cur.moveToNext()) {
    String title = null;
    long eventID = 0;
    long beginVal = 0;    
    
    // 读取各字段的值
    eventID = cur.getLong(PROJECTION_ID_INDEX);
    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
    title = cur.getString(PROJECTION_TITLE_INDEX);
              
    // 利用这些数据完成一些操作
    Log.i(DEBUG_TAG, "Event:  " + title); 
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(beginVal);  
    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
    Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));    
    }
 }

日程相关的 Intent

读写日程数据时,应用程序并不需要申请权限。 也可以利用 Android 内置 Calendar 应用的 Intent 来完成读写操作。 下表列出了 Calendar Provider 支持的 Intent:

Action

URI

说明

附加数据

VIEW

content://com.android.calendar/time/<ms_since_epoch> 也可以用 CalendarContract.CONTENT_URI 来引用该 URI。关于该 Intent 的使用实例,请参阅 使用 Intent 查看日程数据。

打开日历,时间由<ms_since_epoch>指定。

VIEW

content://com.android.calendar/events/<event_id> 也可以用 Events.CONTENT_URI 来引用该 URI。关于该 Intent 的使用实例,请参阅 使用 Intent 查看日程数据。

查看 <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 的使用实例,请参阅 使用 Intent 编辑日程数据。

编辑 <event_id> 指定的事件。

CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME

EDIT INSERT

content://com.android.calendar/events 也可以用 Events.CONTENT_URI 来引用该 URI。关于该 Intent 的使用实例,请参阅 使用 Intent 插入日程数据.

创建事件。

本表后面列出的任何附加数据。

下表列出了 Calendar Provider 支持的 Intent 附加数据:

Intent Extra

说明

Events.TITLE

事件名称。

CalendarContract.EXTRA_EVENT_BEGIN_TIME

事件的起始时间,单位是1970年1月1日以来的毫秒数。

CalendarContract.EXTRA_EVENT_END_TIME

事件的结束时间,单位是1970年1月1日以来的毫秒数。

CalendarContract.EXTRA_EVENT_ALL_DAY

布尔值,标明事件是否占用一整天。值为true或false。

Events.EVENT_LOCATION

事件所在地区。

Events.DESCRIPTION

事件描述信息。

Intent.EXTRA_EMAIL

被邀请参加人员的 Email 地址,中间以逗号分隔。

Events.RRULE

事件重复执行的规则。

Events.ACCESS_LEVEL

事件是私有的还是公开的。

Events.AVAILABILITY

事件是在忙时计时,还是空闲时计时。

下一节将介绍这些 Intent 的使用。

利用 Intent 插入事件

利用 INSERT Intent ,应用程序可以将事件插入工作交给 Calendar 来完成。 这样,就不需要在Manifest 文件中包含 WRITE_CALENDAR 权限。

当用户运行这类应用程序时,应用将会向 Calendar 发送 Intent 来完成事件添加操作。 INSERT Intent 利用其附加数据将事件信息填充到 Calendar 的表单中。 然后,用户可以根据需要取消事件、编辑表单数据,或者把事件保存到日历中。

下面给出了一段代码,在2012年1月1日安排一个事件,时间是上午7:30到8:30。 请留意代码中的以下内容:

代码语言:javascript
复制
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 0, 19, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 0, 19, 8, 30);
Intent intent = new Intent(Intent.ACTION_INSERT)
        .setData(Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
        .putExtra(Events.TITLE, "Yoga")
        .putExtra(Events.DESCRIPTION, "Group class")
        .putExtra(Events.EVENT_LOCATION, "The gym")
        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com");
startActivity(intent);

利用 Intent 编辑事件

正如 修改事件 一节所述,事件可以直接进行更新。但利用 EDIT Intent ,可以让不具备权限的应用将事件编辑工作交给 Calendar 应用来完成。 用户在 Calendar 中完成事件编辑之后,可以返回调用方应用。

下面的例子通过 Intent 设置某个事件的标题,并且用户可以在 Calendar 中编辑该事件。

代码语言:javascript
复制
long eventID = 208;
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_EDIT)
    .setData(uri)
    .putExtra(Events.TITLE, "My New Title");
startActivity(intent);

利用 Intent 查看日程数据

Calender Provider 提供了两种方式来使用 VIEW Intent:

  • 以指定日期打开 Calendar 应用
  • 查看事件

下面的例子演示了以指定日期打开 Calendar 的方式:

代码语言:javascript
复制
// 日期和时间以1970年1月1日以来的毫秒数给出
long startMillis;
...
Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
builder.appendPath("time");
ContentUris.appendId(builder, startMillis);
Intent intent = new Intent(Intent.ACTION_VIEW)
    .setData(builder.build());
startActivity(intent);

以下是查看某个事件的例子:

代码语言:javascript
复制
long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
   .setData(uri);
startActivity(intent);

Sync Adapter

应用程序和 Sync Adapter 在访问 Calendar Provider 时存在些许微小的差别:

  • Sync Adapter 需要声明其为 Sync Adapter 身份,把 CALLER_IS_SYNCADAPTER 设为 true 即可。
  • Sync Adapter 需要以 URI 参数的方式指定 ACCOUNT_NAMEACCOUNT_TYPE
  • Sync Adapter 有权限访问的字段比应用程序或 Widget 都要多一些。 例如,应用程序只能修改日程数据的一些表面性的属性,诸如名称、显示名称、是否可见、是否需要同步等。 相比之下,Sync Adapter 不仅能访问这些字段,还能访问诸如日历配色、时区、访问级别、地区等其他很多字段。 当然, Sync Adapter 访问 ACCOUNT_NAMEACCOUNT_TYPE 是受限的。

下面是 Sync Adapter 可用于返回 URI 的助手方法:

代码语言:javascript
复制
static Uri asSyncAdapter(Uri uri, String account, String accountType) {
    return uri.buildUpon()
        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true")
        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
}

关于 Sync Adapter 的实例(与 Calendar 无关),请参阅 SampleSyncAdapter

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/154807.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Calendar Provider
    • 在本文中
      • 关键类
        • 基础知识
          • 用户权限
            • Calendars 表
              • 查询日程
              • 为什么查询条件中必须包含 ACCOUNT_TYPE字段 ?
              • 修改日程
              • 插入日程
            • Events 表
              • 添加事件
              • 修改事件
              • 删除事件
            • Attendees 表
              • 添加参加人员
            • Reminders 表
              • 添加提醒
            • Instances 表
              • 查询 Instances 表
            • 日程相关的 Intent
              • 利用 Intent 插入事件
              • 利用 Intent 编辑事件
              • 利用 Intent 查看日程数据
            • Sync Adapter
            相关产品与服务
            关系型数据库
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档