英文原文:http://developer.android.com/guide/topics/providers/calendar-provider.html
采集日期:2015-05-10
CalendarContract.Calendars
CalendarContract.Events
CalendarContract.Attendees
CalendarContract.Reminders
Calendar Provider 是用來存放用戶日歷事件(event)的數據庫。 通過 Calendar Provider 的 API ,可以完成對 calendars、events、attendees、reminders 表的查詢、插入、修改和刪除等操作。
應用程序和 Sync Adapter 都可以使用 Calender Provider API。 對于這兩種不同類型的程序,調用的規則也不一樣。 本文的重點是介紹應用程序是如何使用 Calender Provider API 的。 Sync Adapter 的使用方式會有所不同,請參閱Sync Adapters。
通常,如果要讀寫日歷數據,應用程序必須在 Manifest 文件中聲明相應的權限,這在用戶權限一節中將會介紹。 為了便于完成一些常見的操作, Calender Provider 提供了一些 Intent,這將在Calendar Intent一節中介紹。 這些 Intent 可以讓用戶打開 Calendar 應用,并完成插入、查看、編輯事件的操作。 用戶在 Calendar 應用中完成交互后,將返回初始的應用中。 這樣發起方應用就不必申請相應權限,也不需要提供瀏覽和創建事件的用戶界面了。
Content Provider 負責存放數據并提供數據訪問方式。 Android 系統內置的 Content Provider (包括 Calendar Provider)一般是以關系型數據庫表的形式提供數據的, 行數據代表一條記錄,列數據表示字段類型和意義。 應用程序和 Sync Adapter 通過 Calendar Provider API 來訪問數據庫表中的用戶日歷數據。
每個 Content Provider 都會公開一個公共的 URI (封裝為一個 Uri
對象),它唯一標識了某部分數據。 如果 Content Provider 管理著多組數據(多張數據表),則各組數據都會有單獨的 URI。 所有用于 Provider 的 URI 都以字符串 “content://” 開頭,表示這些數據是由某個 Content Provider 進行管理的。 Calendar Provider 為其內部類(表)的 URI 定義了很多常量。這些 URI 的格式均為 <class>.CONTENT_URI
。比如 Events.CONTENT_URI
。
圖 1 為 Calendar Provider 數據模型的示意圖,給出了主表及與其他表的關聯字段。
圖 1. Calendar Provider 數據模型
一個用戶可以擁有多個 Calendar,每個 Calendar 可以與不同類型的帳號關聯(Google Calendar、Exchange 等)。
CalendarContract
定義了 Calendar 和 Event 的數據模型。這些數據存放在以下數據表中。
數據表(類) | 說明 |
---|---|
|
該表存放日程的定義數據。每行表示一條日程的詳細信息,如名稱、顏色、同步信息等。 |
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:andro...> <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 |
該人員與事件的關系??蔀橄铝兄抵唬?/p>
|
ATTENDEE_TYPE |
參加人員的類型??蔀橄铝兄抵唬?/p>
|
ATTENDEE_STATUS |
參加人員的出席狀況??蔀橄铝兄抵唬?/p>
|
以下給出了添加一個事件參與人員的例子。 請注意必須要給出 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 |
提醒方式,這是服務器上的設置??蔀橄铝兄抵唬?/p>
|
下屬例子為某個事件添加了一條提醒。這條提醒將會在事件發生前 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 |
也可以用 | 打開日歷,時間由<ms_since_epoch> 指定。 | 無 |
VIEW |
也可以用 | 查看 <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 |
也可以用 | 創建事件。 | 本表后面列出的任何附加數據。 |
下表列出了 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。
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
塌陷命令3D MAX使用步驟?1. 折疊修改器堆棧:包括折疊到或全部折疊?!霸诙褩V姓郫B”的功能是將多個修改器命令轉換為可編輯狀態(可編輯網格、可編輯多邊形或可編輯面片)。因為修改的命令越多,模型就越復雜,3dsmax的運行速度也就越慢。這樣,使用3dsmax可以簡化模型并加快運行速度。缺點:折疊后,無法再更改原始二維圖形和三維幾何圖形的原始參數。2折疊可編輯多邊形:用于多邊形的子對象(僅在“頂點...
csv文件應該用什么打開?CSV文件本身是一個文本文件,可以被各種文本編輯器打開,如記事本、UE和windows記事本。最廣泛使用的CSV形式是通過特定分隔符以文本形式存儲表數據。這時,使用表格工具,如WPS表格、excel表格打開,向您顯示表格數據。處理CSV文件用什么編輯器比較好?方法如下:1。您可以直接在Excel中編輯,也可以在Excel中保存時選擇CSV格式。2. 如果稍加修改,建議直接...
OPPOa115與a115k的區別?A115K是A115的升級版,功能和java運行能力都強很多。比如火星文的輸入和顯示,手機內置的QQ2010*/QQ瀏覽器,圖片編輯器,后臺運行Java時支持播放音樂,軟件在線升級,最新固件和搜狗輸入法的集成等等都是A115沒有的。如何區分A115和A115K:手機型號一般會在電池倉或者后蓋上注明。去看看吧。此外,還可以在待機狀態下輸入*#6776#查看手機的所...