Save the date! Android Dev Summit is coming to Sunnyvale, CA on Oct 23-24, 2019.

日曆供應程式

「日曆供應程式」是使用者日曆活動的存放庫。「日曆供應程式」API 允許您在日曆、活動、參與者、提醒等等項目中執行查詢、插入、更新以及刪除操作。

「日曆供應程式」API 可以由應用程式和同步配接器使用。規則取決於發出呼叫的程式類型。 本文件主要著重於將「日曆供應程式」API 作為應用程式使用。 如要瞭解同步配接器不一樣的資訊,請參閱同步配接器

一般而言,如要讀取或寫入日曆資料,應用程式的宣示說明必須含有適當的權限 (於使用者權限中描述)。 如要更輕鬆執行常見操作,「日曆供應程式」提供一組意圖 (於日曆意圖中描述)。 這些意圖會將使用者帶往「日曆」應用程式,以插入、檢視以及編輯活動。 使用者與「日曆」應用程式互動後,回到原來的應用程式。 因此,您的應用程式不需要要求權限,也不需要提供檢視或建立活動的使用者介面。

基本概念

內容供應程式會儲存資料,讓應用程式可以存取這些資料。 內容供應程式是由 Android 平台所提供 (包括「日曆供應程式」),通常會根據關聯式資料庫模型,以一組表格的形式公開資料。表格中的每一列都是一筆記錄,而每一欄則是特定類型和意義的資料。 透過「日曆供應程式」API,應用程式和同步配接器可以取得資料庫表格 (此資料庫表格含有使用者日曆資料) 的讀取/寫入存取權。

每個內容供應程式都會公開一個公用 URI (包裝為 Uri 物件),可唯一識別其資料集。 控制多個資料集 (多個表格) 的內容供應程式會為每個資料集公開個別的 URI。 供應程式所有 URI 的開頭字串為「content://」。 這表示資料是受到內容供應程式的控制。 「日曆供應程式」會為每個類別 (表格) 的 URI 定義常數。 這些 URI 的格式為 <class>.CONTENT_URI。 例如,Events.CONTENT_URI

「圖 1」顯示「日曆供應程式」資料模型的圖形表示。它顯示主要表格以及將每個表格連接在一起的欄位。

Calendar Provider Data Model

圖 1.「日曆供應程式」資料模型。

使用者可以有多個日曆,而且不同的日曆可以與不同類型的帳戶 (Google 日曆、Exchange 等等) 關聯。

CalendarContract 會定義日曆的資料模型和活動相關資訊。此資料儲存於一些表格,列示如下。

表格 (類別) 描述

CalendarContract.Calendars

此表格內含日曆特定的資訊。 此表格中的每一列包含單一日曆的詳細資訊,例如名稱、色彩、同步資訊等等。
CalendarContract.Events 此表格內含活動特定的資訊。 此表格中的每一列包含單一活動的資訊 — 例如,活動標題、位置、開始時間、結束時間等等。 活動可以只發生一次或發生多次。參與者、提醒以及延伸屬性儲存於個別的表格。 它們每一個都有 EVENT_ID,會參照「活動」表格中的 _ID
CalendarContract.Instances 此表格內含活動每次發生的開始和結束時間。 此表格的每一列代表單一活動發生。 單次活動執行個體和活動的對應為 1:1。 對於週期性活動,則會自動產生多個列,對應到該活動的多次發生。
CalendarContract.Attendees 此表格內含活動參與者 (邀請對象) 的資訊。 每一列代表一個活動的單一邀請對象。 其中會指出邀請對象類型,以及邀請對象是否出席該活動的回應。
CalendarContract.Reminders 此表格內含警示/通知資訊。 每一列代表一個活動的單一警示。一個活動可以設定多個提醒。 每個活動的最大數量提醒指定於 MAX_REMINDERS,此項是由擁有指定日曆的同步配接器所設定。 提醒是以分鐘數指定活動發生前的時間,而且有一個方法用於決定通知使用者的方式。

「日曆供應程式」API 的設計具備彈性且功能強大。提供良好的使用者體驗,以及保護日曆及其資料的完整性,兩者一樣重要。 關於這一點,使用此 API 時,請記得以下事項:

  • 插入、更新以及檢視日曆活動。如要從「日曆供應程式」直接插入、修改以及讀取活動,您需要具備適當的權限。然而,如果您不是要建置功能豐富的日曆應用程式,則不需要要求這些權限。您可以改用 Android「日曆」應用程式支援的意圖,將讀取和寫入操作交給您的應用程式。使用意圖時,您的應用程式可以將使用者傳送到「日曆」應用程式,在預先填好的表單中執行想要的操作。 完成之後,使用者會回到您的應用程式。將應用程式設計成透過「日曆」來執行常見的操作,即可為使用者提供一致且完整的使用者介面。 我們建議您採用此方式。 如需詳細資訊,請參閱日曆意圖

  • 同步配接器。同步配接器會將使用者裝置的日曆資料與另一台伺服器或資料來源進行同步。 在 CalendarContract.CalendarsCalendarContract.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);

下一節會使用游標逐步檢視結果集。它會使用範例一開始設定好的常數,傳回每個欄位的值。

// 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,可以是 URI 的附加 ID (withAppendedId()) 或以第一個選擇項目方式提供。 選項的開頭應該是 "_id=?",而且第一個 selectionArg 應該是日曆的 _ID。 您也可以透過將 ID 編碼在 URI 中,以執行更新。此範例會使用 (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_LOCALACCOUNT_TYPEACCOUNT_TYPE_LOCAL 是特殊的日曆帳戶類型,它沒有與裝置帳戶關聯。 此類型的日曆不會同步至伺服器。如需關於同步配接器的相關討論,請參閱同步配接器

活動表格

CalendarContract.Events 表格包含個人活動的詳細資訊。 如要新增、更新或刪除活動,應用程式必須在宣示說明檔案中包括 WRITE_CALENDAR權限。

下列「活動」欄可以讓應用程式和同步配接器寫入。 如需關於支援欄位的完整清單,請參閱 CalendarContract.Events 參照。

常數 描述
CALENDAR_ID 活動所屬日曆的 _ID
ORGANIZER 活動主辦人 (擁有者) 的電子郵件。
TITLE 活動的標題。
EVENT_LOCATION 舉辦活動的地點。
DESCRIPTION 活動的描述。
DTSTART 活動開始的時間,以紀元元年 1 月 1 日零時起算經過的 UTC 毫秒數為單位。
DTEND 活動結束的時間,以紀元元年 1 月 1 日零時起算經過的 UTC 毫秒數為單位。
EVENT_TIMEZONE 活動的時區。
EVENT_END_TIMEZONE 活動結束時間的時區。
DURATION 活動的持續期間,以 RFC5545 格式表示。例如,值 "PT1H" 表示活動持續一小時,而值 "P2W" 指出持續 2 週。
ALL_DAY 值 1 表示此活動需要整天,如同當地時區所定義。 值 0 表示定期活動,會在一天中的任何時間開始和結束。
RRULE 活動的週期規則。例如,"FREQ=WEEKLY;COUNT=10;WKST=SU"。 您可以在這裡查看更多範例。
RDATE 活動重複發生的日期。您通常會將 RDATERRULE 一起使用,以定義週期性活動的彙總集合。 如需更多討論,請參閱 RFC5545 規格
AVAILABILITY 活動要視為忙碌或有空 (可以安排其他活動) 的時間。
GUESTS_CAN_MODIFY 邀請對象是否可以修改活動。
GUESTS_CAN_INVITE_OTHERS 邀請對象是否可以邀請其他人。
GUESTS_CAN_SEE_GUESTS 邀請對象是否可以看到參與者清單。

新增活動

您的應用程式插入新活動時,我們建議您使用 INSERT 意圖 (如同使用意圖插入活動所述)。不過,如果需要,您也可以直接插入活動。 本節將描述如何執行此動作。

以下是插入新活動的規則:

以下是插入活動的範例。為了簡化,會在 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 意圖編輯活動 (如同使用意圖插入活動所述)。不過,如果需要,您也可以直接編輯活動。 如要執行活動的更新,您要提供活動的 _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);  

刪除活動

您可以透過活動 URI 的附加 ID _ID 或使用標準選擇方式來刪除活動。 如果您使用附加 ID,就不能進行選擇。刪除有兩種方式:以應用程式和以同步配接器。 應用程式刪除會將 deleted 欄設定為 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

參與者與活動的關係。可以是以下其中一種:

ATTENDEE_TYPE

參與者的類型。可以是以下其中一種:

ATTENDEE_STATUS

參與者的出席狀態。可以是以下其中一種:

新增參與者

以下是將單一參與者新增至活動的範例。請注意, 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

鬧鐘方法 (如伺服器上所設定)。可以是以下其中一種:

新增提醒

此範例會在活動新增提醒。此提醒會在活動 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_TYPEKEY_TIMEZONE_INSTANCES 所定義。

常數 描述
BEGIN 執行個體的開始時間,以 UTC 毫秒數為單位。
END 執行個體的結束時間,以 UTC 毫秒數為單位。
END_DAY 執行個體的凱撒曆結束日,與「日曆」的時區相關。
END_MINUTE 執行個體的結束分鐘,從「日曆」時區的午夜開始計算。
EVENT_ID 此執行個體活動的 _ID
START_DAY 執行個體的凱撒曆開始日,與「日曆」的時區相關。
START_MINUTE 執行個體的開始分鐘,從午夜開始計算,與「日曆」的時區相關。

查詢執行個體表格

如要查詢「執行個體」表格,您需要在 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「日曆」應用程式支援的意圖,將讀取和寫入操作交給您的應用程式。下表列出「日曆供應程式」支援的意圖:

動作 URI 描述 Extra

VIEW

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

您也可以使用 CalendarContract.CONTENT_URI 參照 URI。如需使用此意圖的範例,請參閱使用意圖檢視日曆資料
開啟日曆到 <ms_since_epoch> 指定的時間。 無。

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。如需使用此意圖的範例,請參閱使用意圖插入活動
建立活動。 Extra 列於下表。

下表列出「日曆供應程式」支援的意圖 Extra:

意圖 Extra 描述
Events.TITLE 活動的名稱。
CalendarContract.EXTRA_EVENT_BEGIN_TIME 活動開始時間,以紀元元年 1 月 1 日零時起算經過的毫秒數為單位。
CalendarContract.EXTRA_EVENT_END_TIME 活動結束時間,以紀元元年 1 月 1 日零時起算經過的毫秒數為單位。
CalendarContract.EXTRA_EVENT_ALL_DAY 指出活動為整天的布林值。值可以是 truefalse
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。 請注意下列關於此程式碼片段的事項:

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 意圖可以讓不具備權限的應用程式將活動編輯操作交給「日曆」應用程式。使用者在「日曆」中完成活動的編輯操作時,使用者就會回到原來的應用程式。

以下的意圖範例會為指定的活動設定名稱,然後讓使用者在「日曆」中編輯此活動。

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

使用意圖檢視日曆資料

「日曆供應程式」提供兩種不同的方式來使用 VIEW 意圖:

  • 開啟「日曆」到特定的日期。
  • 檢視某個活動。

以下的範例顯示如何開啟「日曆」到特定的日期:

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

同步配接器

應用程式和同步配接器存取「日曆供應程式」的方式只有些微差異:

  • 同步配接器需要透過將 CALLER_IS_SYNCADAPTER 設定為 true,以指出這是同步配接器。
  • 同步配接器需要在 URI 中提供 ACCOUNT_NAMEACCOUNT_TYPE 作為查詢參數。
  • 同步配接器與應用程式或小工具相比,有更多欄的寫入權限。 例如,應用程式只能修改日曆的一些特性,例如名稱、顯示名稱、能見度設定,以及日曆是否同步。 相較之下,同步配接器不只能存取這些欄,還可以存取很多其他欄,例如日曆色彩、時區、存取級別、位置等等。然而,同步配接器受限於所指定的 ACCOUNT_NAMEACCOUNT_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