英文原文:http://developer.android.com/guide/topics/providers/calendar-provider.htmlhtml
Calendar Provider 是用來存放用戶日曆事件(event)的數據庫。 經過 Calendar Provider 的 API ,能夠完成對 calendars、events、attendees、reminders 表的查詢、插入、修改和刪除等操做。java
應用程序和 Sync Adapter 均可以使用 Calender Provider API。 對於這兩種不一樣類型的程序,調用的規則也不同。 本文的重點是介紹應用程序是如何使用 Calender Provider API 的。 Sync Adapter 的使用方式會有所不一樣,請參閱Sync Adapters。android
一般,若是要讀寫日曆數據,應用程序必須在 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 數據模型的示意圖,給出了主表及與其餘表的關聯字段。服務器
一個用戶能夠擁有多個 Calendar,每一個 Calendar 能夠與不一樣類型的賬號關聯(Google Calendar、Exchange 等)。異步
CalendarContract
定義了 Calendar 和 Event 的數據模型。這些數據存放在如下數據表中。ide
數據表(類) | 說明 |
---|---|
該表存放日程的定義數據。每行表示一條日程的詳細信息,如名稱、顏色、同步信息等。 | |
CalendarContract.Events |
該表存放事件的定義數據。每行表示一個事件,內容包括 — 事件標題、位置、起始時間、結束時間等等。 事件能夠是一次性的,也能夠重複屢次觸發。 參與人員、提醒鬧鐘及附加屬性都存放在其餘表中,並經過 EVENT_ID 字段與 Events 表中的 _ID 關聯。 |
CalendarContract.Instances |
該表存放事件每次觸發時的起始時間和結束時間。一次性事件只會1:1對應一條實例記錄。 對於重複觸發的事件而言,則會自動生成多條實例記錄,對應每一次的觸發。 |
CalendarContract.Attendees |
該表存放事件的參與人員(來賓)信息。每行表明一位人員。 內容包括人員類型和與會反饋。 |
CalendarContract.Reminders |
該表存放鬧鐘/通知數據。每行表明一次鬧鐘提醒。 一個事件能夠擁有多個鬧鐘提醒。每一個事件可擁有的最大提醒數在 MAX_REMINDERS 中定義,這是由擁有該日程的 sync adapter 設置的。 提醒定義了事件觸發前的分鐘數,以及提醒用戶的方式。 |
Calendar Provider API 的設計初衷,是既要靈活又要功能強大。另外一方面,良好的用戶體驗、保證日程數據的安全也很是重要。 爲此,在使用這些 API 時,必須注意如下幾點:
CalendarContract.Calendars
和 CalendarContract.Events
表中,有些字段是留給 Sync Adapter 使用的。 Provider 和應用程序都不要去修改這些字段中的數據。 實際上只有以 Sync Adapter 的方式去訪問時,這些字段纔是可見的。 關於 Sync Adapter 的詳細信息,請參閱 Sync Adapter若是要讀取日程數據,應用程序必須在 Manifest 文件中包含 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
表存放着每項日程的詳細信息。 如下字段都可由應用程序和 Sync Adapter 寫入。 完整的字段清單請參閱手冊 CalendarContract.Calendars
常量名稱 | 說明 |
---|---|
NAME |
日程的名稱。 |
CALENDAR_DISPLAY_NAME |
向用戶顯示的日程名稱。 |
VISIBLE |
布爾值,標明該日程是否可見。 爲 0 表示不顯示與該日程關聯的事件,爲 1 則表示須要顯示。 該值將會影響 CalendarContract.Instances 表中生成的記錄。 |
SYNC_EVENTS |
布爾值,標明該日程是否須要同步,及事件是否須要本地保存。 爲 0 表示不須要同步或者不保存。爲 1 則表示應該同步並在設備中保存事件。 |
如下例子演示瞭如何讀取某個用戶的日程信息。 爲了簡化起見,查詢操做是在用戶界面線程(「主線程」)中進行的。 在實際應用中,這步操做不該放在主線程中,而應該在異步線程中完成。更多信息,請參閱Loaders。 若是不只要讀取數據,還要修改的話,請參閱 AsyncQueryHandler
。
// 映射數組。爲數組創建索引,就不須要動態檢索,以便提升性能。 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;
若是要查詢 Calendars.ACCOUNT_NAME
字段,就必須在查詢語句中包含 Calendars.ACCOUNT_TYPE
字段。這是由於 ACCOUNT_NAME
及其 ACCOUNT_TYPE
合在一塊兒才能惟一肯定一個帳戶。 ACCOUNT_TYPE
是與認證方式(authenticator)對應的一個字符串,在使用 AccountManager
註冊帳戶時須要用到這個認證方式。 對於那些和帳戶無關的日程,還有一種特殊的帳戶類型,叫作 ACCOUNT_TYPE_LOCAL
。 ACCOUNT_TYPE_LOCAL
類型的帳戶不會進行同步。
接下來就是構建查詢,在查詢語句中指定查詢條件。 這裏要查詢的日程,ACCOUNT_NAME
爲「sampleuser@google.com」, ACCOUNT_TYPE
爲「com.google」,OWNER_ACCOUNT
爲「sampleuser@google.com」。 若是要查詢某用戶可查看的全部日程,而不只限於屬於用戶本身的日程,請去掉OWNER_ACCOUNT
條件。 查詢將會返回一個 Cursor
對象,經過該遊標能夠遍歷返回的結果數據集。 關於 Content Provider 查詢的更多介紹,請參閱 Content Provider。
// 執行查詢 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);
下面經過遊標遍歷查詢結果。 這裏用到了一開始定義的常量,返回各個字段的數據。
// 利用遊標遍歷結果記錄集 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()
) 修改日程顯示名稱的例子:
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_LOCAL
。 ACCOUNT_TYPE_LOCAL
是一種專爲日程設計的特殊帳戶,它不與實際的本地帳戶關聯。 這種日程數據也不會與服務器同步。 關於 Sync Adapter 的介紹,請參閱 Sync Adapter。
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 插入事件 一節中將會介紹。 不過在必要時,也能夠直接插入一條事件記錄。本節將介紹這種方式。
下面列出了插入新事件須要遵照的規則:
CALENDAR_ID
和 DTSTART
。EVENT_TIMEZONE
。 利用 getAvailableIDs()
能夠讀取系統已有時區的所有 ID。 請注意,若是是經過 INSERT
來插入事件的,則本條規則不適用。 正如 利用 Intent 插入事件 一節所述,這時會使用默認的時區。DTEND
。DURATION
及 RRULE
,或者是 RDATE
。 請注意,若是是經過 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); // 讀取事件 ID,也就是 Uri 的最後一部分 long eventID = Long.parseLong(uri.getLastPathSegment()); // // ... 利用 ID 完成一些處理 // //
注意: 上述例子中,讀取已建立事件 ID 的方式是一種最簡單的方法。 在實際應用中,每每須要利用事件 ID 來對日程進行某些操做 — 好比:添加參與人員、增長事件提醒。
若是須要讓用戶編輯事件,建議使用 EDIT
Intent,這在 利用 Intent 編輯事件 一節中將會介紹。 不過在必要時,也能夠直接編輯事件。 在修改事件時,給出事件 _ID
的方式能夠是附在 Uri 後面( 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; // 新的標題 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
:
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
表的每行記錄表明參加事件的一位人員(來賓)。以 EVENT_ID
爲參數調用 query()
,將會返回該事件的參加人員清單。這裏的 EVENT_ID
必須與事件的實際 _ID
一致。
下表列出了 Attendees 表中可供寫入的字段。在插入新的人員記錄時,必須包含除ATTENDEE_NAME
外的全部這些字段。
常量名稱 | 說明 |
---|---|
EVENT_ID |
事件 ID。 |
ATTENDEE_NAME |
參加人員的姓名。 |
ATTENDEE_EMAIL |
參加人員的 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
表的每行記錄表明針對某事件的一條系統提醒。以 EVENT_ID
爲參數調用 query()
時,將會返回相關係統提醒的清單。
下表列出了 Reminders 表中可供寫入的字段。 在插入一條新的提醒數據時,必須包含全部這些字段。 請注意,在 CalendarContract.Calendars
表中,定義了 Sync Adapter 支持的提醒類型。 詳情請參閱 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
表存放着事件的起始和結束時間。 每行記錄表明事件的一次實例。 Instances 是不可寫的,僅用於查詢事件的發生經歷。
下表列出了 Instances 表中可供查詢的部分字段。 請注意時區是由 KEY_TIMEZONE_TYPE
和 KEY_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 表,須要在查詢 URI 中指定一個時間範圍。 在如下例子中,經過實現 CalendarContract.EventsColumns
接口, CalendarContract.Instances
讀取了 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 }; // 爲上面的映射數組定義索引常量 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())); } }
讀寫日程數據時,應用程序並不須要申請權限。 也能夠利用 Android 內置 Calendar 應用的 Intent 來完成讀寫操做。 下表列出了 Calendar Provider 支持的 Intent:
Action | URI | 說明 | 附加數據 |
---|---|---|---|
VIEW |
CalendarContract.CONTENT_URI 來引用該 URI。關於該 Intent 的使用實例,請參閱 使用 Intent 查看日程數據。 |
打開日曆,時間由<ms_since_epoch> 指定。 |
無 |
VIEW |
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 |
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 的使用。
利用 INSERT
Intent ,應用程序能夠將事件插入工做交給 Calendar 來完成。 這樣,就不須要在Manifest 文件中包含 WRITE_CALENDAR
權限。
當用戶運行這類應用程序時,應用將會向 Calendar 發送 Intent 來完成事件添加操做。 INSERT
Intent 利用其附加數據將事件信息填充到 Calendar 的表單中。 而後,用戶能夠根據須要取消事件、編輯表單數據,或者把事件保存到日曆中。
下面給出了一段代碼,在2012年1月1日安排一個事件,時間是上午7:30到8:30。 請留意代碼中的如下內容:
Events.CONTENT_URI
定義了 Uri。CalendarContract.EXTRA_EVENT_BEGIN_TIME
and CalendarContract.EXTRA_EVENT_END_TIME
預置了事件的事件。單位必須是 UTC 1970年1月1日以來的毫秒數。Intent.EXTRA_EMAIL
給出了逗號分割的參加人員列表,形式爲 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 應用來完成。 用戶在 Calendar 中完成事件編輯以後,能夠返回調用方應用。
下面的例子經過 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);
Calender Provider 提供了兩種方式來使用 VIEW
Intent:
下面的例子演示了以指定日期打開 Calendar 的方式:
// 日期和時間以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);
如下是查看某個事件的例子:
long eventID = 208; ... Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); Intent intent = new Intent(Intent.ACTION_VIEW) .setData(uri); startActivity(intent);
應用程序和 Sync Adapter 在訪問 Calendar Provider 時存在些許微小的差異:
CALLER_IS_SYNCADAPTER
設爲 true
便可。ACCOUNT_NAME
和ACCOUNT_TYPE
ACCOUNT_NAME
和 ACCOUNT_TYPE
是受限的。下面是 Sync Adapter 可用於返回 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(); }
關於 Sync Adapter 的實例(與 Calendar 無關),請參閱 SampleSyncAdapter。