您的位置:首页 > 移动开发 > Android开发

Calendar Provider

2016-04-03 19:41 471 查看
The Calendar Provider is a repository for a user's calendar events. The Calendar Provider API allows you to perform query, insert, update, and delete operations on calendars, events, attendees, reminders,
and so on.
The Calender Provider API can be used by applications and sync adapters. The rules vary depending on what type of program is making the calls. This document focuses primarily on using the Calendar Provider API as
an application. For a discussion of how sync adapters are different, see Sync Adapters.
Normally, to read or write calendar data, an application's manifest must include the proper permissions, described in User
Permissions. To make performing common operations easier, the Calendar Provider offers a set of intents, as described in Calendar
Intents. These intents take users to the Calendar application to insert, view, and edit events. The user interacts with the Calendar application and then returns to the original application. Thus your application doesn't need to request permissions, nor
does it need to provide a user interface to view or create events.


Basics

Content providers store data and make it accessible to
applications. The content providers offered by the Android platform (including the Calendar Provider) typically expose data as a set of tables based on a relational database model, where each row is a record and each column is data of a particular type and
meaning. Through the Calendar Provider API, applications and sync adapters can get read/write access to the database tables that hold a user's calendar data.
Every content provider exposes a public URI (wrapped as a
Uri
object)
that uniquely identifies its data set. A content provider that controls multiple data sets (multiple tables) exposes a separate URI for each one. All URIs for providers begin with the string "content://". This identifies the data as being controlled by a content
provider. The Calendar Provider defines constants for the URIs for each of its classes (tables). These URIs have the format
<class>.CONTENT_URI
. For example,
Events.CONTENT_URI
.
Figure 1 shows a graphical representation of the Calendar Provider data model. It shows the main tables and the fields that link them to each other.



Figure 1. Calendar Provider data model.
A user can have multiple calendars, and different calendars can be associated with different types of accounts (Google Calendar, Exchange, and so on).
The
CalendarContract
defines
the data model of calendar and event related information. This data is stored in a number of tables, listed below.
Table (Class)Description
CalendarContract.Calendars

This table holds the calendar-specific information. Each row in this table contains the details for a single calendar, such as the name, color, sync information, and so on.
CalendarContract.Events
This table holds the event-specific information. Each row in this table has the information for a single event—for example, event title, location, start time, end time, and so on. The event can occur one-time or can recur multiple times. Attendees, reminders,
and extended properties are stored in separate tables. They each have an
EVENT_ID
that
references the
_ID
in the Events table.
CalendarContract.Instances
This table holds the start and end time for each occurrence of an event. Each row in this table represents a single event occurrence. For one-time events there is a 1:1 mapping of instances to events. For recurring events, multiple rows are automatically generated
that correspond to multiple occurrences of that event.
CalendarContract.Attendees
This table holds the event attendee (guest) information. Each row represents a single guest of an event. It specifies the type of guest and the guest's attendance response for the event.
CalendarContract.Reminders
This table holds the alert/notification data. Each row represents a single alert for an event. An event can have multiple reminders. The maximum number of reminders per event is specified in
MAX_REMINDERS
,
which is set by the sync adapter that owns the given calendar. Reminders are specified in minutes before the event and have a method that determines how the user will be alerted.
The Calendar Provider API is designed to be flexible and powerful. At the same time, it's important to provide a good end user experience and protect the integrity of the calendar and its data. To this end, here
are some things to keep in mind when using the API:

Inserting, updating, and viewing calendar events. To directly insert, modify, and read events from the Calendar Provider, you need the appropriate permissions.
However, if you're not building a full-fledged calendar application or sync adapter, requesting these permissions isn't necessary. You can instead use intents supported by Android's Calendar application to hand off read and write operations to that application.
When you use the intents, your application sends users to the Calendar application to perform the desired operation in a pre-filled form. After they're done, they're returned to your application. By designing your application to perform common operations through
the Calendar, you provide users with a consistent, robust user interface. This is the recommended approach. For more information, see Calendar
Intents.

Sync adapters. A sync adapter synchronizes the calendar data on a user's device with another server or data source. In the
CalendarContract.Calendars
and
CalendarContract.Events
tables,
there are columns that are reserved for the sync adapters to use. The provider and applications should not modify them. In fact, they are not visible unless they are accessed as a sync adapter. For more information about sync adapters, seeSync
Adapters.


User Permissions

To read calendar data, an application must include the
READ_CALENDAR
permission
in its manifest file. It must include the
WRITE_CALENDAR
permission
to delete, insert or update calendar data:
<?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 Table

The
CalendarContract.Calendars
table
contains details for individual calendars. The following Calendars columns are writable by both an application and a sync
adapter. For a full list of supported fields, see the
CalendarContract.Calendars
reference.
ConstantDescription
NAME
The name of the calendar.
CALENDAR_DISPLAY_NAME
The name of this calendar that is displayed to the user.
VISIBLE
A boolean indicating whether the calendar is selected to be displayed. A value of 0 indicates that events associated with this calendar should not be shown. A value of 1 indicates that events associated with this calendar should be shown. This value affects
the generation of rows in the
CalendarContract.Instances
table.
SYNC_EVENTS
A boolean indicating whether the calendar should be synced and have its events stored on the device. A value of 0 says do not sync this calendar or store its events on the device. A value of 1 says sync events for this calendar and store its events on the device.


Querying a calendar

Here is an example that shows how to get the calendars that are owned by a particular user. For simplicity's sake, in this example the query operation is shown in the user interface thread ("main thread"). In practice,
this should be done in an asynchronous thread instead of on the main thread. For more discussion, see Loaders. If you
are not just reading data but modifying it, see
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;


Why must you include ACCOUNT_TYPE?

If you query on a
Calendars.ACCOUNT_NAME
,
you must also include
Calendars.ACCOUNT_TYPE
in
the selection. That is because a given account is only considered unique given both its
ACCOUNT_NAME
and its
ACCOUNT_TYPE
. The
ACCOUNT_TYPE
is the string corresponding to the account authenticator
that was used when the account was registered with the
AccountManager
.
There is also a special type of account called
ACCOUNT_TYPE_LOCAL
for
calendars not associated with a device account.
ACCOUNT_TYPE_LOCAL
accounts
do not get synced.

In the next part of the example, you construct your query. The selection specifies the criteria for the query. In this example the query is looking for calendars that have the
ACCOUNT_NAME
"sampleuser@google.com",
the
ACCOUNT_TYPE
"com.google", and the
OWNER_ACCOUNT
"sampleuser@google.com". If you want to see all calendars that a user has viewed, not just calendars the user owns, omit the
OWNER_ACCOUNT
.
The query returns a
Cursor
object that you can use to traverse the result set returned
by the database query. For more discussion of using queries in content providers, see Content Providers.
// 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);

This next section uses the cursor to step through the result set. It uses the constants that were set up at the beginning of the example to return the values for each field.
// 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...

...
}


Modifying a calendar

To perform an update of an calendar, you can provide the
_ID
of
the calendar either as an appended ID to the Uri (
withAppendedId()
)
or as the first selection item. The selection should start with
"_id=?"
, and the first
selectionArg
should be the
_ID
of
the calendar. You can also do updates by encoding the ID in the URI. This example changes a calendar's display name using the (
withAppendedId()
)
approach:
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);


Inserting a calendar

Calendars are designed to be primarily managed by a sync adapter, so you should only insert new calendars as a sync adapter. For the most part, applications can only make superficial changes to calendars, such as
changing the display name. If an application needs to create a local calendar, it can do this by performing the calendar insertion as a sync adapter, using an
ACCOUNT_TYPE
of
ACCOUNT_TYPE_LOCAL
.
ACCOUNT_TYPE_LOCAL
is
a special account type for calendars that are not associated with a device account. Calendars of this type are not synced to a server. For a discussion of sync adapters, see Sync
Adapters.


Events Table

The
CalendarContract.Events
table
contains details for individual events. To add, update, or delete events, an application must include the
WRITE_CALENDAR
permission
in its manifest file.
The following Events columns are writable by both an application and a sync adapter. For a full list of supported fields, see the
CalendarContract.Events
reference.
ConstantDescription
CALENDAR_ID
The
_ID
of the calendar the event belongs to.
ORGANIZER
Email of the organizer (owner) of the event.
TITLE
The title of the event.
EVENT_LOCATION
Where the event takes place.
DESCRIPTION
The description of the event.
DTSTART
The time the event starts in UTC milliseconds since the epoch.
DTEND
The time the event ends in UTC milliseconds since the epoch.
EVENT_TIMEZONE
The time zone for the event.
EVENT_END_TIMEZONE
The time zone for the end time of the event.
DURATION
The duration of the event in RFC5545 format. For example, a value of
"PT1H"
states that the event should
last one hour, and a value of
"P2W"
indicates a duration of 2 weeks.
ALL_DAY
A value of 1 indicates this event occupies the entire day, as defined by the local time zone. A value of 0 indicates it is a regular event that may start and end at any time during a day.
RRULE
The recurrence rule for the event format. For example,
"FREQ=WEEKLY;COUNT=10;WKST=SU"
. You can find more examples here.
RDATE
The recurrence dates for the event. You typically use
RDATE
in
conjunction with
RRULE
to define an
aggregate set of repeating occurrences. For more discussion, see the RFC5545 spec.
AVAILABILITY
If this event counts as busy time or is free time that can be scheduled over.
GUESTS_CAN_MODIFY
Whether guests can modify the event.
GUESTS_CAN_INVITE_OTHERS
Whether guests can invite other guests.
GUESTS_CAN_SEE_GUESTS
Whether guests can see the list of attendees.


Adding Events

When your application inserts a new event, we recommend that you use an
INSERT
Intent,
as described in Using an intent to insert an event. However, if you need to,
you can insert events directly. This section describes how to do this.
Here are the rules for inserting a new event:

You must include
CALENDAR_ID
and
DTSTART
.
You must include an
EVENT_TIMEZONE
.
To get a list of the system's installed time zone IDs, use
getAvailableIDs()
.
Note that this rule does not apply if you're inserting an event through the
INSERT
Intent,
described in Using an intent to insert an event—in that scenario, a default time
zone is supplied.
For non-recurring events, you must include
DTEND
.
For recurring events, you must include a
DURATION
in
addition to
RRULE
or
RDATE
.
Note that this rule does not apply if you're inserting an event through the
INSERT
Intent,
described in Using an intent to insert an event—in that scenario, you can use
an
RRULE
in conjunction with
DTSTART
and
DTEND
,
and the Calendar application converts it to a duration automatically.

Here is an example of inserting an event. This is being performed in the UI thread for simplicity. In practice, inserts and updates should be done in an asynchronous thread to move the action into a background thread.
For more information, see
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
//
//


Note: See how this example captures the event ID after the event is created. This is the easiest way to get an event ID. You often need the event ID to perform other calendar operations—for example, to add attendees or reminders to an event.


Updating Events

When your application wants to allow the user to edit an event, we recommend that you use an
EDIT
Intent,
as described in Using an intent to edit an event. However, if you need to, you
can edit events directly. To perform an update of an Event, you can provide the
_ID
of the event either as an appended ID to the Uri (
withAppendedId()
)
or as the first selection item. The selection should start with
"_id=?"
, and the first
selectionArg
should be the
_ID
of the event. You can also do updates using a selection with no ID. Here
is an example of updating an event. It changes the title of the event using the
withAppendedId()
approach:
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);


Deleting Events

You can delete an event either by its
_ID
as
an appended ID on the URI, or by using standard selection. If you use an appended ID, you can't also do a selection. There are two versions of delete: as an application and as a sync adapter. An application delete sets the deleted column to 1. This
flag that tells the sync adapter that the row was deleted and that this deletion should be propagated to the server. A sync adapter delete removes the event from the database along with all its associated data. Here is an example of application deleting an
event through its
_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);


Attendees Table

Each row of the
CalendarContract.Attendees
table
represents a single attendee or guest of an event. Calling
)]query()
returns
a list of attendees for the event with the given
EVENT_ID
.
This
EVENT_ID
must match the
_ID
of
a particular event.
The following table lists the writable fields. When inserting a new attendee, you must include all of them except
ATTENDEE_NAME
.
ConstantDescription
EVENT_ID
The ID of the event.
ATTENDEE_NAME
The name of the attendee.
ATTENDEE_EMAIL
The email address of the attendee.
ATTENDEE_RELATIONSHIP
The relationship of the attendee to the event. One of:

RELATIONSHIP_ATTENDEE

RELATIONSHIP_NONE

RELATIONSHIP_ORGANIZER

RELATIONSHIP_PERFORMER

RELATIONSHIP_SPEAKER


ATTENDEE_TYPE
The type of attendee. One of:

TYPE_REQUIRED

TYPE_OPTIONAL


ATTENDEE_STATUS
The attendance status of the attendee. One of:

ATTENDEE_STATUS_ACCEPTED

ATTENDEE_STATUS_DECLINED

ATTENDEE_STATUS_INVITED

ATTENDEE_STATUS_NONE

ATTENDEE_STATUS_TENTATIVE



Adding Attendees

Here is an example that adds a single attendee to an event. Note that the
EVENT_ID
is
required:
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 Table

Each row of the
CalendarContract.Reminders
table
represents a single reminder for an event. Calling
)]query()
returns
a list of reminders for the event with the given
EVENT_ID
.
The following table lists the writable fields for reminders. All of them must be included when inserting a new reminder. Note that sync adapters specify the types of reminders they support in the
CalendarContract.Calendars
table.
See
ALLOWED_REMINDERS
for details.
ConstantDescription
EVENT_ID
The ID of the event.
MINUTES
The minutes prior to the event that the reminder should fire.
METHOD
The alarm method, as set on the server. One of:

METHOD_ALERT

METHOD_DEFAULT

METHOD_EMAIL

METHOD_SMS



Adding Reminders

This example adds a reminder to an event. The reminder fires 15 minutes before the event.
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 Table

The
CalendarContract.Instances
table
holds the start and end time for occurrences of an event. Each row in this table represents a single event occurrence. The instances table is not writable and only provides a way to query event occurrences.
The following table lists some of the fields you can query on for an instance. Note that time zone is defined by
KEY_TIMEZONE_TYPE
and
KEY_TIMEZONE_INSTANCES
.
ConstantDescription
BEGIN
The beginning time of the instance, in UTC milliseconds.
END
The ending time of the instance, in UTC milliseconds.
END_DAY
The Julian end day of the instance, relative to the Calendar's time zone.
END_MINUTE
The end minute of the instance measured from midnight in the Calendar's time zone.
EVENT_ID
The
_ID
of the event for this instance.
START_DAY
The Julian start day of the instance, relative to the Calendar's time zone.
START_MINUTE
The start minute of the instance measured from midnight, relative to the Calendar's time zone.


Querying the Instances table

To query the Instances table, you need to specify a range time for the query in the URI. In this example,
CalendarContract.Instances
gets
access to the
TITLE
field through its implementation of
the
CalendarContract.EventsColumns
interface. In other words,
TITLE
is
returned through a database view, not through querying the raw
CalendarContract.Instances
table.
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()));
}
}


Calendar Intents

Your application doesn't need permissions to
read and write calendar data. It can instead use intents supported by Android's Calendar application to hand off read and write operations to that application. The following table lists the intents supported by the Calendar Provider:
ActionURIDescriptionExtras
VIEW


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

You can also refer to the URI with
CalendarContract.CONTENT_URI
.
For an example of using this intent, see Using intents to view calendar
data.
Open calendar to the time specified by
<ms_since_epoch>
.
None.
VIEW

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

You can also refer to the URI with
Events.CONTENT_URI
.
For an example of using this intent, see Using intents to view calendar
data.
View the event specified by
<event_id>
.
CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT
content://com.android.calendar/events/<event_id>

You can also refer to the URI with
Events.CONTENT_URI
.
For an example of using this intent, see Using an intent to edit an event.
Edit the event specified by
<event_id>
.
CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT


INSERT
content://com.android.calendar/events

You can also refer to the URI with
Events.CONTENT_URI
.
For an example of using this intent, see Using an intent to insert an
event.
Create an event.Any of the extras listed in the table below.
The following table lists the intent extras supported by the Calendar Provider:
Intent ExtraDescription
Events.TITLE
Name for the event.
CalendarContract.EXTRA_EVENT_BEGIN_TIME
Event begin time in milliseconds from the epoch.
CalendarContract.EXTRA_EVENT_END_TIME
Event end time in milliseconds from the epoch.
CalendarContract.EXTRA_EVENT_ALL_DAY
A boolean that indicates that an event is all day. Value can be
true
or
false
.
Events.EVENT_LOCATION
Location of the event.
Events.DESCRIPTION
Event description.
Intent.EXTRA_EMAIL
Email addresses of those to invite as a comma-separated list.
Events.RRULE
The recurrence rule for the event.
Events.ACCESS_LEVEL
Whether the event is private or public.
Events.AVAILABILITY
If this event counts as busy time or is free time that can be scheduled over.
The following sections describe how to use these intents.


Using an intent to insert an event

Using the
INSERT
Intent lets
your application hand off the event insertion task to the Calendar itself. With this approach, your application doesn't even need to have the
WRITE_CALENDAR
permission
included in its manifest file.
When users run an application that uses this approach, the application sends them to the Calendar to finish adding the event. The
INSERT
Intent
uses extra fields to pre-populate a form with the details of the event in the Calendar. Users can then cancel the event, edit the form as needed, or save the event to their calendars.
Here is a code snippet that schedules an event on January 19, 2012, that runs from 7:30 a.m. to 8:30 a.m. Note the following about this code snippet:

It specifies
Events.CONTENT_URI
as
the Uri.
It uses the
CalendarContract.EXTRA_EVENT_BEGIN_TIME
and
CalendarContract.EXTRA_EVENT_END_TIME
extra
fields to pre-populate the form with the time of the event. The values for these times must be in UTC milliseconds from the epoch.
It uses the
Intent.EXTRA_EMAIL
extra field
to provide a comma-separated list of invitees, specified by email address.

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


Using an intent to edit an event

You can update an event directly, as described in Updating
events. But using the
EDIT
Intent allows an application that doesn't
have permission to hand off event editing to the Calendar application. When users finish editing their event in Calendar, they're returned to the original application.
Here is an example of an intent that sets a new title for a specified event and lets users edit the event in the 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);


Using intents to view calendar data

Calender Provider offers two different ways to use the
VIEW
Intent:

To open the Calendar to a particular date.
To view an event.

Here is an example that shows how to open the Calendar to a particular date:
// 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);

Here is an example that shows how to open an event for viewing:
long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
.setData(uri);
startActivity(intent);


Sync Adapters

There are only minor differences in how an application and a sync adapter access the Calendar Provider:

A sync adapter needs to specify that it's a sync adapter by setting
CALLER_IS_SYNCADAPTER
to
true
.
A sync adapter needs to provide an
ACCOUNT_NAME
and
an
ACCOUNT_TYPE
as query parameters in the URI.
A sync adapter has write access to more columns than an application or widget. For example, an application can only modify a few characteristics of a calendar, such as its name, display name, visibility setting, and whether the
calendar is synced. By comparison, a sync adapter can access not only those columns, but many others, such as calendar color, time zone, access level, location, and so on. However, a sync adapter is restricted to the
ACCOUNT_NAME
and
ACCOUNT_TYPE
it
specified.

Here is a helper method you can use to return a URI for use with a sync adapter:
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();
}

For a sample implementation of a sync adapter (not specifically related to Calendar), see SampleSyncAdapter.

日历提供者是用户的日历事件的存储库。日历提供API允许你进行查询,插入,更新和日历,活动参加者,提醒删除操作,等等。

该日历提供API可以通过应用程序和同步适配器配合使用。这些规则取决于什么类型的节目正在调用。本文主要关注使用日历提供程序API为应用程序。对于同步适配器如何不同的讨论,参见 同步适配器

通常情况下,要读取或写入日历数据,应用程序的清单必须包括适当的权限,所描述的用户权限。为了使执行常见的操作更容易,日历提供商提供了一组意图,如在描述日历意图。这些意图将用户带到日历应用程序中插入,查看和编辑事件。用户与日历应用程序进行交互,然后返回到原来的程序。因此,你的应用程序并不需要请求的权限,也不需要提供一个用户界面来查看或创建活动。


基础知识

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

每个内容提供商公开了一个公共的URI(包装成一个
开放的
对象)的唯一标识它的数据集。控制多个数据集(多个表),内容提供者暴露一个独立的URI的每一个。对于供应商所有的URI开始字符串“内容://”。这个标识数据作为由内容提供商所控制。日历提供者定义了URI的为每个类(表)的常数。这些URI的格式为
<类>.CONTENT_URI
。例如,
Events.CONTENT_URI


图1显示了日历Provider数据模型的图形表示。它显示了主表和其链接到彼此的字段。



图1.日历提供的数据模型。

用户可以有多个日历,以及不同的日历可以与不同类型的账户(谷歌日历,交易所等)相关联。

所述
CalendarContract
定义日历和事件相关的信息的数据模型。此数据存储在多个表中,列出如下。
表(A类)描述
CalendarContract.Calendars

该表保存特定的日历信息。此表中的每行包含一个单一的日历的细节,如名称,颜色,同步信息等。
CalendarContract.Events
该表保存特定事件的信息。此表中的每一行具有用于单个事件,例如,事件标题,位置,开始时间,结束时间,等等的信息。该事件可以发生一次性或可循环多次。与会者,提醒和扩展属性存储在单独的表。他们每个人都有一个
EVENT_ID
引用
_ID
在事件表。
CalendarContract.Instances
该表保存的开始和结束时间的事件的每次发生。在这个表中的每一行代表一个单一的事件发生。对于一次性事件有一个1:实例事件的映射。对于周期性事件,多行自动生成对应于该事件的多个实例。
CalendarContract.Attendees
该表保存事件参与者(客户)的信息。每一行代表一个事件的一个客人。它指定客人的类型和事件的来宾的出席回应。
CalendarContract.Reminders
该表保存警报/通知数据。每一行代表一个事件一个警报。一个事件可以有多个提醒。每个事件提醒的最大数量中指定
MAX_REMINDERS
,这是由拥有给定日历同步适配器设置。提醒以分钟指定的事件之前并具有确定用户将如何被警告的方法。
日历提供API的设计是灵活和强大。同时,它提供了良好的最终用户体验,保护日历和其数据的完整性是重要的。为此,这里有一些事情使用API​​时,要牢记:

插入,更新和查看日历事件。要直接插入,修改,并从日历提供商读取事件,就需要相应的权限。但是,如果你没有建立一个全面的日历应用程序或同步适配器,请求这些权限是没有必要的。您可以替代由Android的日历应用程序,手头宽裕的读写操作该应用程序支持的意图。当您使用的意图,你的应用程序发送用户的日历应用程序在一个预先填好的表格执行所需操作。他们完成后,他们返回到您的应用程序。通过设计应用程序通过日历执行常见的操作,您提供一个一致的,可靠的用户界面的用户。这是推荐的方法。欲了解更多信息,请参阅日历意图

同步适配器。一个同步适配器与另一个服务器或数据源同步用户的设备上的日历数据。在
CalendarContract.Calendars
CalendarContract.Events
表,有保留用于同步适配器中使用的列。提供者和应用程序不应该对其进行修改。事实上,他们是不可见的,除非它们被作为一个同步适配器访问。有关同步适配器的详细信息,请参阅同步适配器


用户权限

要读取日历数据,应用程序必须包括
功能(6)
在其清单文件的权限。它必须包括
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
参考。
不变描述
名称
日历的名称。
CALENDAR_DISPLAY_NAME
该日历显示给该用户的名称。
可见
要显示指示日历是否被选中的布尔值。0值表示与此日历关联的事件应该不会显示。值为1表示与此日历关联的事件应该显示。此值影响的行的产生
CalendarContract.Instances
表。
SYNC_EVENTS
一个布尔值,指示是否历应同步并存储在设备上的事件。值为0表示不同步此日历或​​在设备上存储的事件。值为1表示该日历同步事件,并在设备上存储的事件。


查询日历

下面的例子说明如何获得由某个特定用户所拥有的日历的例子。为简单起见,在这个例子中,查询操作在用户界面线程所示(“主线程”)。在实践中,这应该在异步线程,而不是在主线程进行。有关详细讨论,请参见 装载机。如果你不只是数据的读取,修改它,请参阅
AsyncQueryHandler

//投影阵列。创建这个数组,而不是做指标
//动态查找可以提高性能。
公共 静态 最终 字符串[] EVENT_PROJECTION =  新 的String []  {
日历。_ID ,                           // 0
日历。ACCOUNT_NAME ,                  // 1
日历。CALENDAR_DISPLAY_NAME ,         // 2
日历。OWNER_ACCOUNT                   // 3
};

//为突起阵列的索引


为什么你必须包括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”,并且
OWNER_ACCOUNT
“sampleuser@google.com”。如果你想看到一个用户查看所有日历,而不仅仅是日历的用户拥有,省略
OWNER_ACCOUNT
。该查询返回一个
指针
,你可以用它来
​​遍历由数据库查询返回的结果集对象。对于内容提供商使用查询的详细讨论,请参阅内容提供商
// 跑

=?)AND(“
+  日历。ACCOUNT_TYPE +  ”=?)AND(“
+  日历。OWNER_ACCOUNT +  ”=

提交查询并获得一个Cursor对象回来。
CUR = CR 。查询(URI ,EVENT_PROJECTION ,选择,selectionArgs两个, 空);


下一节使用游标来浏览结果集。它使用分别设置在实施例的开始到每个字段返回的值的常数。
//使用光标步返回

获取字段

做一些与价值观...

...
}


修改日历

要执行日历的更新,可以提供
_ID
日历无论是作为附加标识的URI(的
withAppendedId() 
),或作为第一个选择项。的选择应以启动
“_id
=?”
,并在第一
selectionArg
_ID
的日历。您也可以通过编码在URI标识做更新。这个例子改变使用(日历的显示名称
withAppendedId() 
)的方法:
新的显示名称为日历
值。把(日历。CALENDAR_DISPLAY_NAME , “特雷弗的

更新:“  + 行);


插入日历

日历被设计成一个同步适配器主要是管理,所以你应该只插入新日历作为同步适配器。在大多数情况下,应用程序只能做出粗浅更改日历,如更改显示名称。如果应用程序需要创建一个本地日历,它可以通过执行日历插入作为一个同步适配器,使用做到这一点
ACCOUNT_TYPE
ACCOUNT_TYPE_LOCAL
ACCOUNT_TYPE_LOCAL
是未与设备帐户相关联的日历专户类型。这种类型的日历未同步到服务器。对于同步适配器的讨论,请参见同步适配器


事件表

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

以下事件列是由双方在应用程序和同步适配器可写的。有关支持字段的完整列表,请参阅
CalendarContract.Events
参考。
不变描述
CALENDAR_ID
_ID
日历事件属于。
组织者
活动的组织者(所有者)的电子邮件。
标题
事件的标题。
EVENT_LOCATION
当事件发生。
描述
事件的描述。
DTSTART
当时的事件开始以来新纪元UTC毫秒。
DTEND
因为时代在UTC毫秒事件的结束时间。
EVENT_TIMEZONE
该事件的时区。
EVENT_END_TIMEZONE
该事件的结束时间的时区。
期限
在事件的持续时间RFC5545格式。例如,值
“PT1H”
指出事件应持续一小时,值
“P2W”
表示2周的持续时间。
整天
值为1表示该事件占据了整整一天,由当地时区的定义。0值表明它是一个可以启动,并在在一天的任何时间终止定期举行的活动。
RRULE
事件格式的重复规则。例如,
“FREQ = WEEKLY; COUNT = 10; WKST = SU”
。你可以找到更多的例子在这里
RDATE
复发日期的事件。您通常使用
RDATE
会同
RRULE
定义聚集组重复出现。有关详细讨论,请参见RFC5545规范
可用性
如果此事件计数为忙碌的时候或者是说可以实现预定的空闲时间。
GUESTS_CAN_MODIFY
无论客人可以修改该事件。
GUESTS_CAN_INVITE_OTHERS
无论客人可以邀请其他客人。
GUESTS_CAN_SEE_GUESTS
无论客人可以看到与会者列表。


添加活动

当你的应用程序插入一个新的事件,我们建议您使用
INSERT
意图,如描述的使用意图插入事件。但是,如果你需要的话,您可以直接插入事件。本节介绍了如何做到这一点。

下面是插入一个新的事件的规则:

您必须包括
CALENDAR_ID
DTSTART

您必须包括
EVENT_TIMEZONE
。为了让系统的安装时区ID列表,可使用
getAvailableIDs() 
。请注意,如果你插入通过事件这一规则不适用于
INSERT
意向书中所述,使用意图插入事件 -in的情况下,默认的时区提供。
对于非经常性事件,必须包括
DTEND

对于周期性事件,你必须包括一个
期限
,除了
RRULE
RDATE
。请注意,如果你插入通过一个事件此规则不适用
INSERT
意图,描述使用意图插入事件 -in的情况下,您可以使用
RRULE
会同
DTSTART
DTEND
和日历应用程序转换它为自动的持续时间。

这里是插入一个事件的一个例子。这是为简明起见,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 );

//得到事件的ID是URI中的最后一个元素
长EVENTID =  长。parseLong (URI 。getLastPathSegment ());
//
// ...做事件ID东西
//
//


注:参见本例中如何捕获事件ID创建活动后。这是为了获得一个事件ID的最简单的方法。你经常需要事件ID执行其他日历操作-例如,向与会者或提醒添加到事件。


更新活动

当应用程序希望允许用户编辑的事件,我们建议您使用的
编辑
意图,如描述的使用意图编辑的事件。但是,如果你需要的话,您可以直接编辑的事件。要执行事件的更新,您可以提供
_ID
事件无论是作为附加标识的URI(的
withAppendedId() 
),或作为第一个选择项。的选择应以启动
“_id
=?”
,并在第一
selectionArg
_ID
事件。你也可以用做没有ID选择更新。这里是更新的事件的一个例子。它改变了使用该事件的标题
withAppendedId()
方法:
对于新标题

更新:“  + 行);


删除事件

您可以通过它删除事件
_ID
作为对URI,附加一个ID或通过使用标准的选择。如果使用附加ID,你不能也做了选择。还有的删除两个版本:作为一个应用程序,并作为一个同步适配器。应用程序中删除集的删除列。本标记,告诉该行已被删除,此删除应当被传播到服务器的同步适配器。一个同步适配器删除与其相关联的所有数据一起从数据库中删除该事件。这里是应用删除通过其一个事件的例子
_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删除:“  + 行);


与会者表

在每行
CalendarContract.Attendees
表代表一个事件的单个与会者或客人。调用
)]查询()
返回给定的情况下参加者列表
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
表代表一个事件的单个提醒。调用
)]查询()
返回提醒与给定的事件列表
EVENT_ID


下表列出了提醒的可写域。所有的人都必须插入一个新的提醒时被包括在内。请注意,同步适配器指定提醒他们的支持类型
CalendarContract.Calendars
表。见
ALLOWED_REMINDERS
了解详情。
不变描述
EVENT_ID
事件的ID。
MINUTES
这提醒应触发事件之前分钟。
方法
报警方法,如在服务器上设置。其中之一:

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

不变描述
开始
实例的开始时间,以UTC毫秒。
结束
实例的结束时间,以UTC毫秒。
END_DAY
实例的儒略日结束,相对于日历的时区。
END_MINUTE
实例的结束分钟从午夜在日历的时间区间内测量。
EVENT_ID
_ID
此实例的事件。
START_DAY
朱利安启动实例的当天,相对日历的时区。
START_MINUTE
实例的开始分钟从午夜测量,相对于日历的时区。


查询实例表

要查询实例表,你需要指定一个时间范围在URI查询。在这个例子中,
CalendarContract.Instances
获取访问
TITLE
通过其执行的字段
CalendarContract.EventsColumns
接口。换句话说,
标题
是通过数据库视图返回,而不是通过查询原始
CalendarContract.Instances
表。
0
实例。BEGIN ,         // 1
实例。TITLE           // 2
};

//用于投影数组索引

指定要搜索的经常性的日期范围
//事件

定期事件的情况下,您正在搜索的ID
//在实例表
字符串选择=  实例。EVENT_ID +  “=?” ;
的String [] selectionArgs两个=  新 的String []  { “207” };

//构造查询与所需的日期

提交

获取字段

做的东西值。
登录。我(DEBUG_TAG , “事件:

“  + 格式。格式(日历。的getTime ()));
}
}


日历意图

您的应用程序并不需要权限读取和写入日历数据。它可以替代由Android的日历应用程序,手头宽裕的读写操作该应用程序支持的意图。下表列出了日历提供支持的意图:
行动URI描述附加功能
视图


内容://com.android.calendar/time/ <ms_since_epoch>

您也可以参考与URI
CalendarContract.CONTENT_URI
。对于使用这种意图的一个示例,请参阅使用意图,查看日历数据
打开日历由指定的时间
<ms_since_epoch>
没有。
视图

内容://com.android.calendar/events/ <事项标识>

您也可以参考与URI
Events.CONTENT_URI
。对于使用这种意图的一个示例,请参阅使用意图,查看日历数据
查看由指定的事件
<事项标识>
CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
编辑
内容://com.android.calendar/events/ <事项标识>

您也可以参考与URI
Events.CONTENT_URI
。对于使用这种意图的一个例子,请参阅使用意图编辑的事件
编辑由指定的事件
<事项标识>
CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
编辑


INSERT
内容://com.android.calendar/events

您也可以参考与URI
Events.CONTENT_URI
。对于使用这种意图的一个例子,请参阅使用意图插入事件
创建活动。任何下表中列出的临时演员。
下表列出了日历提供程序支持的意图演员:
额外的意向描述
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
意图让你的应用手离开事件插入任务日历本身。通过这种方法,您的应用程序甚至不需要有
WRITE_CALENDAR
包含在其权限清单文件

当用户运行使用这种方法的应用程序,该应用程序将他们的日历完成添加事件。该
INSERT
意图使用额外的字段来预填充形式在日历事件的细节。然后,用户可以取消该事件,根据需要编辑的形式,或者事件保存到他们的日历。

下面是一个代码段时间表于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类“ )
。putExtra (活动。EVENT_LOCATION , ”中gym" )
. putExtra ( Events . AVAILABILITY ,  Events . AVAILABILITY_BUSY )
. putExtra ( Intent . EXTRA_EMAIL ,  "rowan@example.com,trevor@example.com" );
startActivity ( intent );


使用意图编辑事件

您可以直接更新的事件,如中所述更新的事件。但使用
编辑
意图允许没有权限来编辑事件移交给日历应用程序的应用程序。当用户完成编辑他们的日历事件,他们回到了原来的应用程序。

这里是设置一个新的标题为指定的事件,并允许用户在日历编辑事件的意图的一个例子。
long eventID =  208 ;
Uri uri =  ContentUris . withAppendedId ( Events . CONTENT_URI , eventID );
Intent intent =  new  Intent ( Intent . ACTION_EDIT )
. setData ( uri )
. putExtra ( Events . TITLE ,  "My新标题“ );
startActivity (意向);


使用意图,查看日历数据

日历提供商提供了两种不同的方式使用
VIEW
意图:

要打开日历到一个特定的日期。
要查看事件。

下面的例子说明如何打开日历特定日期的例子:
//由于在以毫秒为单位指定的日期-时间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 );


同步适配器

有在如何在应用程序和同步适配器访问日历提供商只有轻微的差异:

一个同步适配器需要指定它是通过设置同步适配器
CALLER_IS_SYNCADAPTER

一个同步适配器需要提供
ACCOUNT_NAME
ACCOUNT_TYPE
作为URI查询参数。
一个同步适配器有写权限比应用程序或窗口小部件多个列。例如,一个应用程序只能修改一个日历的一些特点,比如它的名称,显示名称,可见性设置和日历是否同步。相比之下,同步适配器不仅可以访问这些列,但许多其他国家,如日历颜色,时区,访问级别,位置等。然而,同步适配器被限制在
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息