Android官方文档—APP组件(Content Providers)(Calendar Provider)

日历提供商

Calendar Provider是用户日历事件的存储库。 Calendar Provider API允许您对日历,事件,与会者,提醒等执行查询,插入,更新和删除操作。

应用程序和同步适配器可以使用Calender Provider API。规则取决于拨打电话的程序类型。本文档主要侧重于将Calendar Provider API用作应用程序。有关同步适配器的不同之处的讨论,请参阅同步适配器。

通常,要读取或写入日历数据,应用程序的清单必须包含用户权限中描述的适当权限。为了简化常见操作,Calendar Provider提供了一组意图,如Calendar Intents中所述。这些意图将用户带到日历应用程序以插入,查看和编辑事件。用户与日历应用程序交互,然后返回到原始应用程序。因此,您的应用程序不需要请求权限,也不需要提供用户界面来查看或创建事件。

基础知识


内容提供商存储数据并使其可供应用程序访问。 Android平台(包括日历提供程序)提供的内容提供程序通常基于关系数据库模型将数据公开为一组表,其中每行是记录,每列是特定类型和含义的数据。通过Calendar Provider API,应用程序和同步适配器可以对包含用户日历数据的数据库表进行读/写访问。

每个内容提供者都公开一个唯一标识其数据集的公共URI(包装为Uri对象)。控制多个数据集(多个表)的内容提供程序为每个数据集公开一个单独的URI。提供者的所有URI都以字符串“content://”开头。这将数据标识为由内容提供商控制。 Calendar Provider为每个类(表)定义URI的常量。这些URI的格式为<class> .CONTENT_URI。例如,Events.CONTENT_URI。

图1显示了Calendar Provider数据模型的图形表示。它显示了主表和将它们相互链接的字段。

图1. Calendar Provider数据模型。

用户可以拥有多个日历,不同的日历可以与不同类型的帐户相关联(Google日历,Exchange等)。

CalendarContract定义日历和事件相关信息的数据模型。该数据存储在下面列出的许多表中。

表(类)描述
CalendarContract.Calendars此表包含特定于日历的信息。此表中的每一行都包含单个日历的详细信息,例如名称,颜色,同步信息等。
CalendarContract.Events此表包含特定于事件的信息。此表中的每一行都包含单个事件的信息 - 例如,事件标题,位置,开始时间,结束时间等。该事件可以一次发生或可以多次重复发生。与会者,提醒和扩展属性存储在单独的表中。它们每个都有一个EVENT_ID,它引用了Events表中的_ID。
CalendarContract.Instances此表包含每次事件发生的开始和结束时间。此表中的每一行代表一个事件发生。对于一次性事件,实例与事件的映射为1:1。对于重复发生的事件,将自动生成多个行,这些行对应于该事件的多次出现。
CalendarContract.Attendees此表包含事件参加者(访客)信息。每行代表一个事件的单个访客。它指定了客人的类型和客人对活动的出席响应。
CalendarContract.Reminders此表包含警报/通知数据。每行代表一个事件的单个警报。一个事件可以有多个提醒。每个事件的最大提醒数在MAX_REMINDERS中指定,该值由拥有给定日历的同步适配器设置。提醒在事件发生前的几分钟内指定,并具有确定如何提醒用户的方法。

Calendar Provider API设计灵活且功能强大。同时,提供良好的最终用户体验并保护日历及其数据的完整性非常重要。为此,在使用API​​时需要注意以下事项:

  • 插入,更新和查看日历事件。要从日历提供程序直接插入,修改和读取事件,您需要适当的权限。但是,如果您没有构建完整的日历应用程序或同步适配器,则无需请求这些权限。您可以使用Android的日历应用程序支持的意图来切换对该应用程序的读写操作。当您使用意图时,您的应用程序会将用户发送到日历应用程序,以便以预先填写的形式执行所需的操作。完成后,它们将返回您的应用程序。通过设计应用程序以通过日历执行常见操作,您可以为用户提供一致,强大的用户界面。这是推荐的方法。有关更多信息,请参阅日历意图。
  • 同步适配器。同步适配器将用户设备上的日历数据与另一个服务器或数据源同步。在CalendarContract.Calendars和CalendarContract.Events表中,有一些列保留供同步适配器使用。提供者和应用程序不应修改它们。实际上,除非将它们作为同步适配器访问,否则它们不可见。有关同步适配器的详细信息,请参阅同步适配器。

用户权限


要读取日历数据,应用程序必须在其清单文件中包含READ_CALENDAR权限。它必须包含WRITE_CALENDAR权限才能删除,插入或更新日历数据:

<?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>

日历表


CalendarContract.Calendars表包含各个日历的详细信息。以下日历列可由应用程序和同步适配器写入。有关支持的字段的完整列表,请参阅CalendarContract.Calendars参考。

常量描述
NAME日历的名称。
CALENDAR_DISPLAY_NAME显示给用户的此日历的名称。
VISIBLE一个布尔值,指示是否选择显示日历。值为0表示不应显示与此日历关联的事件。值为1表示应显示与此日历关联的事件。此值会影响CalendarContract.Instances表中的行的生成。
SYNC_EVENTS一个布尔值,指示是否应同步日历并将其事件存储在设备上。值为0表示不同步此日历或​​将其事件存储在设备上。值为1表示此日历的同步事件,并将其事件存储在设备上。

查询日历

以下是一个示例,说明如何获取特定用户拥有的日历。为简单起见,在此示例中,查询操作显示在用户界面线程(“主线程”)中。实际上,这应该在异步线程中而不是在主线程上完成。有关更多讨论,请参阅装载程序。如果您不只是读取数据而是修改数据,请参阅AsyncQueryHandler。

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
public static final String[] EVENT_PROJECTION = new String[] {
    Calendars._ID,                           // 0
    Calendars.ACCOUNT_NAME,                  // 1
    Calendars.CALENDAR_DISPLAY_NAME,         // 2
    Calendars.OWNER_ACCOUNT                  // 3
};

// The indices for the projection array above.
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_NAME“sampleuser@google.com”,ACCOUNT_TYPE“com.google”和OWNER_ACCOUNT“sampleuser@google.com”的日历。如果要查看用户查看过的所有日历,而不仅仅是用户拥有的日历,请忽略OWNER_ACCOUNT。该查询返回一个Cursor对象,您可以使用该对象遍历数据库查询返回的结果集。有关在内容提供程序中使用查询的更多讨论,请参阅内容提供程序。

// Run query
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"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

为什么必须包含ACCOUNT_TYPE?

如果您在Calendars.ACCOUNT_NAME上进行查询,则还必须在选择中包含Calendars.ACCOUNT_TYPE。这是因为,只有ACCOUNT_NAME及其ACCOUNT_TYPE才会将特定帐户视为唯一帐户。 ACCOUNT_TYPE是与帐户在AccountManager中注册时使用的帐户身份验证器对应的字符串。对于与设备帐户无关的日历,还有一种名为ACCOUNT_TYPE_LOCAL的特殊帐户。 ACCOUNT_TYPE_LOCAL帐户无法同步。

下一节将使用光标逐步执行结果集。它使用在示例开头设置的常量来返回每个字段的值。

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    long calID = 0;
    String displayName = null;
    String accountName = null;
    String ownerName = null;

    // Get the field values
    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);

    // Do something with the values...

   ...
}

修改日历

要执行日历更新,您可以将日历的_ID作为附加ID提供给Uri(withAppendedId())或作为第一个选择项。选择应以“_id =?”开头,第一个selectionArg应为日历的_ID。您还可以通过在URI中对ID进行编码来执行更新。此示例使用(withAppendedId())方法更改日历的显示名称:

private static final String DEBUG_TAG = "MyActivity";
...
long calID = 2;
ContentValues values = new ContentValues();
// The new display name for the calendar
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);

插入日历

日历主要由同步适配器管理,因此您只应插入新的日历作为同步适配器。在大多数情况下,应用程序只能对日历进行表面更改,例如更改显示名称。如果应用程序需要创建本地日历,则可以使用ACCOUNT_TYPE ACCOUNT_TYPE_LOCAL将日历插入作为同步适配器执行此操作。 ACCOUNT_TYPE_LOCAL是与设备帐户无关的日历的特殊帐户类型。此类日历未同步到服务器。有关同步适配器的讨论,请参阅同步适配器。

事件表


CalendarContract.Events表包含单个事件的详细信息。要添加,更新或删除事件,应用程序必须在其清单文件中包含WRITE_CALENDAR权限。

以下事件列可由应用程序和同步适配器写入。有关支持的字段的完整列表,请参阅CalendarContract.Events参考。

常量描述
CALENDAR_ID事件所属日历的_ID。
ORGANIZER活动主办方(所有者)的电子邮件。
TITLE活动的标题。
EVENT_LOCATION事件发生的地方。
DESCRIPTION事件的描述。
DTSTART自纪元以来事件以UTC毫秒开始的时间。
DTEND自纪元以来事件以UTC毫秒结束的时间。
EVENT_TIMEZONE活动的时区。
EVENT_END_TIMEZONE

事件结束时间的时区。

DURATIONRFC5545格式的事件持续时间。例如,值“PT1H”表示事件应持续一小时,值“P2W”表示持续时间为2周。
ALL_DAY值为1表示此事件占用整个一天,由本地时区定义。值为0表示它是一个常规事件,可以在一天中的任何时间开始和结束。
RRULE事件格式的重复规则。例如,“FREQ = WEEKLY; COUNT = 10; WKST = SU”。你可以在这里找到更多的例子。
RDATE事件的重复日期。您通常将RDATE与RRULE结合使用来定义重复出现的聚合集。有关更多讨论,请参阅RFC5545规范。
AVAILABILITY如果此事件计为忙碌时间或可以安排的空闲时间。
GUESTS_CAN_MODIFY客人是否可以修改活动。
GUESTS_CAN_INVITE_OTHERS是否可以邀请其他客人。

GUESTS_CAN_SEE_GUESTS

客人是否可以看到与会者名单。

添加事件

当您的应用程序插入新事件时,我们建议您使用INSERT Intent,如使用intent插入事件中所述。但是,如果需要,可以直接插入事件。本节介绍如何执行此操作。

以下是插入新事件的规则:

  • 您必须包含CALENDAR_ID和DTSTART。
  • 您必须包含EVENT_TIMEZONE。要获取系统安装的时区ID列表,请使用getAvailableIDs()。请注意,如果您通过INSERT Intent插入事件,则此规则不适用,如使用意图插入事件中所述 - 在该方案中,提供了默认时区。
  • 对于非经常性事件,您必须包含DTEND。
  • 对于重复活动,除了RRULE或RDATE之外,您还必须包含DURATION。请注意,如果您通过INSERT Intent插入事件(在使用意图插入事件中描述),则该规则不适用 - 在该场景中,您可以将RRULE与DTSTART和DTEND一起使用,并且Calendar应用程序转换它自动到一个持续时间。

以下是插入事件的示例。为简单起见,这是在UI线程中执行的。实际上,插入和更新应该在异步线程中完成,以将操作移动到后台线程中。有关更多信息,请参阅AsyncQueryHandler

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);

// get the event ID that is the last element in the Uri
long eventID = Long.parseLong(uri.getLastPathSegment());
//
// ... do something with event ID
//
//

注意:请参阅此示例在创建事件后如何捕获事件ID。这是获取事件ID的最简单方法。您经常需要事件ID来执行其他日历操作 - 例如,向活动添加与会者或提醒。

更新事件

当您的应用程序想要允许用户编辑事件时,我们建议您使用EDIT Intent,如使用intent编辑事件中所述。但是,如果需要,您可以直接编辑事件。要执行事件更新,您可以将事件的_ID作为Uri的附加ID(withAppendedId())或作为第一个选择项。选择应以“_id =?”开头,第一个selectionArg应该是事件的_ID。您还可以使用没有ID的选项进行更新。以下是更新活动的示例。它使用withAppendedId()方法更改事件的标题:

private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 188;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri updateUri = null;
// The new title for the event
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上的附加ID或使用标准选择来删除事件。如果使用附加的ID,则不能进行选择。删除有两个版本:作为应用程序和同步适配器。应用程序删除将已删除的列设置为1.此标志告诉同步适配器该行已被删除,并且此删除应传播到服务器。同步适配器删除会从数据库中删除该事件及其所有关联数据。以下是通过_ID删除事件的应用程序示例:

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);

与会者表


CalendarContract.Attendees表的每一行代表一个事件的参与者或访客。调用query()会返回具有给定EVENT_ID的事件的与会者列表。此EVENT_ID必须与特定事件的_ID匹配。

下表列出了可写字段。插入新与会者时,除了ATTENDEE_NAME之外,您必须包含所有与会者。

常量描述
EVENT_ID事件的ID。
ATTENDEE_NAME与会者的姓名。
ATTENDEE_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

添加与会者

以下是向事件添加单个与会者的示例。请注意,EVENT_ID是必需的:

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);

提醒表


CalendarContract.Reminders表的每一行代表一个事件的提醒。调用query()返回具有给定EVENT_ID的事件的提醒列表。

下表列出了提醒的可写字段。插入新提醒时必须包含所有提醒。请注意,同步适配器在CalendarContract.Calendars表中指定它们支持的提醒类型。有关详细信息,请参阅ALLOWED_REMINDERS。

常量描述
EVENT_ID事件的ID。
MINUTES提醒应该触发事件之前的分钟。
METHOD

警报方法,在服务器上设置。之一:

  • METHOD_ALERT
  • METHOD_DEFAULT
  • METHOD_EMAIL
  • METHOD_SMS

添加提醒

此示例为事件添加提醒。提醒在事件发生前15分钟。

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);

实例表


CalendarContract.Instances表保存事件发生的开始和结束时间。此表中的每一行代表一个事件发生。实例表不可写,只提供查询事件发生的方法。

下表列出了可以查询实例的一些字段。请注意,时区由KEY_TIMEZONE_TYPE和KEY_TIMEZONE_INSTANCES定义。

常量描述
BEGIN实例的开始时间,以UTC毫秒为单位。
END实例的结束时间,以UTC毫秒为单位。
END_DAY实例的Julian结束日,相对于Calendar的时区。
END_MINUTE实例的结束分钟是从日历时区的午夜测量的。
EVENT_ID此实例的事件的_ID。
START_DAY实例的Julian开始日期,相对于Calendar的时区。

START_MINUTE

实例的开始分钟是从午夜开始测量的,相对于日历的时区。

查询Instances表

要查询Instances表,您需要在URI中指定查询的范围时间。在此示例中,CalendarContract.Instances通过其CalendarContract.EventsColumns接口的实现来访问TITLE字段。换句话说,TITLE是通过数据库视图返回的,而不是通过查询原始CalendarContract.Instances表。

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
  };

// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_BEGIN_INDEX = 1;
private static final int PROJECTION_TITLE_INDEX = 2;
...

// Specify the date range you want to search for recurring
// event instances
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();

// The ID of the recurring event whose instances you are searching
// for in the Instances table
String selection = Instances.EVENT_ID + " = ?";
String[] selectionArgs = new String[] {"207"};

// Construct the query with the desired date range.
Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMillis);
ContentUris.appendId(builder, endMillis);

// Submit the query
cur =  cr.query(builder.build(),
    INSTANCE_PROJECTION,
    selection,
    selectionArgs,
    null);

while (cur.moveToNext()) {
    String title = null;
    long eventID = 0;
    long beginVal = 0;

    // Get the field values
    eventID = cur.getLong(PROJECTION_ID_INDEX);
    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
    title = cur.getString(PROJECTION_TITLE_INDEX);

    // Do something with the values.
    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()));
    }
 }

日历意图


您的应用程序不需要读取和写入日历数据的权限。它可以改为使用Android的Calendar应用程序支持的意图来对该应用程序进行读写操作。下表列出了Calendar Provider支持的意图:

ActionURI描述Extras
VIEW

content://com.android.calendar/time/<ms_since_epoch>

您还可以使用CalendarContract.CONTENT_URI引用URI。有关使用此意图的示例,请参阅使用意图查看日历数据。

打开日历到<ms_since_epoch>指定的时间。None.
VIEW

content://com.android.calendar/events/<event_id>

您还可以使用Events.CONTENT_URI来引用URI。有关使用此意图的示例,请参阅使用意图查看日历数据。

查看<event_id>指定的事件。CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

content://com.android.calendar/events/<event_id>

您还可以使用Events.CONTENT_URI来引用URI。有关使用此意图的示例,请参阅使用意图编辑事件。

编辑<event_id>指定的事件。CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

您还可以使用Events.CONTENT_URI来引用URI。有关使用此意图的示例,请参阅使用意图插入事件。

Create an event.下表中列出的任何附加内容。

下表列出了Calendar Provider支持的intent附加内容:

Intent Extra描述
Events.TITLE活动名称。
CalendarContract.EXTRA_EVENT_BEGIN_TIME事件开始时间以纪元为单位,以毫秒为单位。
CalendarContract.EXTRA_EVENT_END_TIME从纪元开始的事件结束时间(以毫秒为单位)。
CalendarContract.EXTRA_EVENT_ALL_DAY一个布尔值,表示事件是全天。价值可以是真或假。
Events.EVENT_LOCATION活动地点。
Events.DESCRIPTION活动描述。
Intent.EXTRA_EMAIL要以逗号分隔列表的形式邀请的电子邮件地址。
Events.RRULE事件的重复规则。
Events.ACCESS_LEVEL无论是私人活动还是公开活动。
Events.AVAILABILITY如果此事件计为忙碌时间或可以安排的空闲时间。

以下部分描述了如何使用这些意图。

使用意图插入事件

使用INSERT Intent可以让您的应用程序将事件插入任务移交给Calendar本身。使用此方法,您的应用程序甚至不需要在其清单文件中包含WRITE_CALENDAR权限。

当用户运行使用此方法的应用程序时,应用程序会将它们发送到日历以完成添加事件。 INSERT Intent使用额外字段来预填充表单,其中包含日历中事件的详细信息。然后,用户可以取消事件,根据需要编辑表单,或将事件保存到日历中。

这是一个代码片段,用于安排2012年1月19日上午7:30至8:30运行的事件。请注意以下有关此代码段的信息:

  • 它将Events.CONTENT_URI指定为Uri。
  • 它使用CalendarContract.EXTRA_EVENT_BEGIN_TIME和CalendarContract.EXTRA_EVENT_END_TIME额外字段来预先填充表单以及事件的时间。这些时间的值必须是从纪元开始的UTC毫秒。
  • 它使用Intent.EXTRA_EMAIL额外字段提供以逗号分隔的受邀者列表,由电子邮件地址指定。
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);

使用意图编辑事件

您可以直接更新事件,如更新事件中所述。但是使用EDIT Intent允许没有权限的应用程序将事件编辑移交给Calendar应用程序。当用户在日历中完成他们的事件编辑时,他们将返回到原始应用程序。

以下是为特定事件设置新标题并允许用户在日历中编辑事件的意图示例。

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);

使用意图查看日历数据

Calendar Provider提供了两种使用VIEW Intent的方法:

  • 将日历打开到特定日期。
  • 查看活动。

以下示例显示如何将日历打开到特定日期:

// A date-time specified in milliseconds since the epoch.
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);

以下示例显示如何打开要查看的事件:

long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
   .setData(uri);
startActivity(intent);

同步适配器


应用程序和同步适配器访问Calendar Provider的方式只有细微差别:

  • 同步适配器需要通过将CALLER_IS_SYNCADAPTER设置为true来指定它是同步适配器。
  • 同步适配器需要在URI中提供ACCOUNT_NAME和ACCOUNT_TYPE作为查询参数。
  • 同步适配器对应用程序或窗口小部件具有更多列的写访问权限。例如,应用程序只能修改日历的一些特征,例如其名称,显示名称,可见性设置以及日历是否已同步。相比之下,同步适配器不仅可以访问那些列,还可以访问许多其他列,例如日历颜色,时区,访问级别,位置等。但是,同步适配器仅限于指定的ACCOUNT_NAME和ACCOUNT_TYPE。

这是一个帮助方法,可用于返回用于同步适配器的URI:

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();
 }

有关同步适配器(与日历无关)的示例实现,请参阅SampleSyncAdapter。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值