Calendar Provider

英文原文: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 Adaptersandroid

一般,若是要讀寫日曆數據,應用程序必須在 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 數據模型app

一個用戶能夠擁有多個 Calendar,每一個 Calendar 能夠與不一樣類型的賬號關聯(Google Calendar、Exchange 等)。異步

CalendarContract 定義了 Calendar 和 Event 的數據模型。這些數據存放在如下數據表中。ide

數據表(類) 說明

CalendarContract.Calendars

該表存放日程的定義數據。每行表示一條日程的詳細信息,如名稱、顏色、同步信息等。
CalendarContract.Events 該表存放事件的定義數據。每行表示一個事件,內容包括 — 事件標題、位置、起始時間、結束時間等等。 事件能夠是一次性的,也能夠重複屢次觸發。 參與人員、提醒鬧鐘及附加屬性都存放在其餘表中,並經過 EVENT_ID 字段與 Events 表中的 _ID 關聯。
CalendarContract.Instances 該表存放事件每次觸發時的起始時間和結束時間。一次性事件只會1:1對應一條實例記錄。 對於重複觸發的事件而言,則會自動生成多條實例記錄,對應每一次的觸發。
CalendarContract.Attendees 該表存放事件的參與人員(來賓)信息。每行表明一位人員。 內容包括人員類型和與會反饋。
CalendarContract.Reminders 該表存放鬧鐘/通知數據。每行表明一次鬧鐘提醒。 一個事件能夠擁有多個鬧鐘提醒。每一個事件可擁有的最大提醒數在 MAX_REMINDERS 中定義,這是由擁有該日程的 sync adapter 設置的。 提醒定義了事件觸發前的分鐘數,以及提醒用戶的方式。

Calendar Provider API 的設計初衷,是既要靈活又要功能強大。另外一方面,良好的用戶體驗、保證日程數據的安全也很是重要。 爲此,在使用這些 API 時,必須注意如下幾點:

  • 插入、更新和查詢日程事件。 若是要直接插入、修改和查詢 Calendar Provider 中的事件數據,須要得到合適的權限。 不過,若是還未創建完整的日曆應用或 Sync Adapter,就不必申請這些權限。 這時就能夠經過 Intent,把讀寫操做交給 Android 內置 Calendar 應用去完成。 在使用這些 Intent 時,用戶會被帶入 Calendar 應用,在預置的表單中進行操做。待操做完畢後,再返回調用方應用。 經過這種調用內置 Calendar 來完成經常使用操做的方式,能夠向用戶提供一種風格統1、容錯性較強的界面。 這也是推薦的訪問方式。詳情請參閱Calendar Intent
  • Sync Adapter。 Sync Adapter 負責將用戶設備上的日程數據與服務器或數據源保持同步。在 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>

Calendars 表

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;

接下來就是構建查詢,在查詢語句中指定查詢條件。 這裏要查詢的日程,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

Events 表

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 插入事件 一節中將會介紹。 不過在必要時,也能夠直接插入一條事件記錄。本節將介紹這種方式。

下面列出了插入新事件須要遵照的規則:

下面給出一個插入事件的例子。簡化起見,此例運行於 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);  

Attendees 表

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

Reminders 表

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

Instances 表

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 表

若是要查詢 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()));    
    }
 }

日程相關的 Intent

讀寫日程數據時,應用程序並不須要申請權限。 也能夠利用 Android 內置 Calendar 應用的 Intent 來完成讀寫操做。 下表列出了 Calendar Provider 支持的 Intent:

Action URI 說明 附加數據
VIEW

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

也能夠用 CalendarContract.CONTENT_URI 來引用該 URI。關於該 Intent 的使用實例,請參閱 使用 Intent 查看日程數據
打開日曆,時間由<ms_since_epoch>指定。
VIEW

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

也能夠用 Events.CONTENT_URI 來引用該 URI。關於該 Intent 的使用實例,請參閱 使用 Intent 查看日程數據
查看 <event_id> 指定的事件。 CalendarContract.EXTRA_EVENT_BEGIN_TIMECalendarContract.EXTRA_EVENT_END_TIME
EDIT content://com.android.calendar/events/<event_id> 也能夠用 Events.CONTENT_URI. 來引用該 URI。關於該 Intent 的使用實例,請參閱 使用 Intent 編輯日程數據 編輯 <event_id> 指定的事件。 CalendarContract.EXTRA_EVENT_BEGIN_TIMECalendarContract.EXTRA_EVENT_END_TIME
EDITINSERT

content://com.android.calendar/events

也能夠用 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 布爾值,標明事件是否佔用一成天。值爲truefalse
Events.EVENT_LOCATION 事件所在地區。
Events.DESCRIPTION 事件描述信息。
Intent.EXTRA_EMAIL 被邀請參加人員的 Email 地址,中間以逗號分隔。
Events.RRULE 事件重複執行的規則。
Events.ACCESS_LEVEL 事件是私有的仍是公開的。
Events.AVAILABILITY 事件是在忙時計時,仍是空閒時計時。

下一節將介紹這些 Intent 的使用。

利用 Intent 插入事件

利用 INSERT Intent ,應用程序能夠將事件插入工做交給 Calendar 來完成。 這樣,就不須要在Manifest 文件中包含 WRITE_CALENDAR 權限。

當用戶運行這類應用程序時,應用將會向 Calendar 發送 Intent 來完成事件添加操做。 INSERT Intent 利用其附加數據將事件信息填充到 Calendar 的表單中。 而後,用戶能夠根據須要取消事件、編輯表單數據,或者把事件保存到日曆中。

下面給出了一段代碼,在2012年1月1日安排一個事件,時間是上午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);

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

利用 Intent 查看日程數據

Calender Provider 提供了兩種方式來使用 VIEW Intent:

  • 以指定日期打開 Calendar 應用
  • 查看事件

下面的例子演示了以指定日期打開 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

應用程序和 Sync Adapter 在訪問 Calendar Provider 時存在些許微小的差異:

  • Sync Adapter 須要聲明其爲 Sync Adapter 身份,把 CALLER_IS_SYNCADAPTER 設爲 true 便可。
  • Sync Adapter 須要以 URI 參數的方式指定 ACCOUNT_NAME 和ACCOUNT_TYPE
  • Sync Adapter 有權限訪問的字段比應用程序或 Widget 都要多一些。 例如,應用程序只能修改日程數據的一些表面性的屬性,諸如名稱、顯示名稱、是否可見、是否須要同步等。 相比之下,Sync Adapter 不只能訪問這些字段,還能訪問諸如日曆配色、時區、訪問級別、地區等其餘不少字段。 固然, Sync Adapter 訪問 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

相關文章
相關標籤/搜索