Calendars表
CalendarContract.Calendars表包含了單個日曆的詳細資料。下表中Calendars表列對應用程式和同步適配器都是可寫的。對於這個表支援的完整的欄位列表,請看“CalendarContract.Calendars參考”
http://developer.android.com/reference/android/provider/CalendarContract.Calendars.html
|
常量 |
描述 |
|
NAME |
日曆的名字 |
|
CALENDAR_DISPLAY_NAME |
顯示給使用者的名字 |
|
VISIBLE |
一個指明被選擇的日曆是否顯示的布爾值。0指明跟這個日曆相關聯的不應該顯示,1指明跟這個日曆關聯的事件應該顯示。這個值會影響CalendarContract.Instances表中行的產生。 |
|
SYNC_EVENTS |
一個布爾值,指明日曆是否應該被同步並在裝置上儲存其事件。0指明不同步這個日曆並在裝置上儲存事件。1指明同步這個日曆並在裝置上儲存其事件。 |
查詢日曆
這是一個顯示怎樣為特定的使用者擷取所有日曆的例子。為了簡單明了,在這個列子中,查詢操作被寫在了使用介面執行緒中(“主線程”)。實踐中,應該用非同步線程來替代主線程做這樣的事情。
// 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
};
// 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;
接下來要構造查詢。Selection變數指定了查詢條件。在這個例子中,要尋找所有的ACCOUNT_NAME是“sampleuser@google.com”並且ACCOUNT_TYPE是“com.google”的日曆。查詢會返回一個Cursor對象,你可以用它來遍曆資料庫查詢的結果。
// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;
String selection = “((” + Calendars.ACCOUNT_NAME + " = ?) AND ("
+ Calendars.ACCOUNT_TYPE + " = ?))";
String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google"};
// 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;
// Get the field values
calID = cur.getLong(PROJECTION_ID_INDEX);
displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
// Do something with the values...
...
}
修改日曆
你能夠通過日曆的_ID來執行更新處理,這個ID既可以是附加到Uri(用withAppendedId()方法)中的ID,也可以是第一個選擇項目的ID。selection變數應用用“_id=?”開頭,並且selectionArg數組的第一個參數應該是這個日曆的_ID。也可以通過URI中的編碼ID來做更新的處理。下例使用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);
插入日曆
Calendars被設計成以同步適配器為主的方式來管理的表,因此你只應該用同步適配器來插入新的日曆。大多數情況,應用程式僅能改變日曆的外觀,如改變顯示名字。如果應用程式需要建立一個本地日曆,那麼它能使用一個ACCOUNT_TYPE_LOCAL的ACCOUNT_TYPE列,通過執行同步適配器的日曆插入處理來完成這件事情。ACCOUNT_TYPE_LOCAL是一個特殊的日曆帳號類型,它不跟裝置帳號關聯。這種類型的日曆不同步到伺服器。關於同步適配器的討論,請看“同步適配器”。
Events 表
CalendarContract.Events表包含了單個事件的詳細資料。要添加、更新、或刪除事件,應用程式必須在它的資訊清單檔中包含WRITE_CALENDAR許可權。
以下Events表列通過應用程式和同步適配器都是可寫的。對於這個表的完整的欄位列表,請看CalendarContract.Events參考。
|
常量 |
描述 |
|
CALENDAR_ID |
事件所屬的日曆的_ID |
|
ORGANIZER |
事件的召集人(所有者)的電子郵件 |
|
TITLE |
事件的標題 |
|
EVENT_LOCATION |
事件發生的地點 |
|
DESCRIPTION |
事件的描述 |
|
DTSTART |
事件的啟動時間,使用從紀元開始的UTC毫秒計時 |
|
DTEND |
事件的結束時間,使用從紀元開始的UTC毫秒計時 |
|
EVENT_TIMEZONE |
事件所針對的時區 |
|
EVENT_END_TIMEZONE |
針對事件結束時間的時區 |
|
DURATION |
用RFC5545格式表示的事件期間,例如“PT1H”表示事件持續1小時的狀態, “P2W”指明2周的期間。 |
|
ALL_DAY |
1指明這個事件會佔用整天時間(由本地時區定義的時間);0指明它是一個普通的事件,可以在一天的任何時間開始和結束 |
|
RRULE |
格式化的事件複發規則(RFC5545)。如“FREQ=WEEKLY;COUNT=10;WKST=SU”。 |
|
RDATE |
事件的複發日期。通常RDATE要聯合RRULE一起使用來定義一個重複發生的事件的合集。 |
|
AVAILABILITY |
If this event counts as busy time or is free time that can be scheduled over.???? |
|
GUESTS_CAN_MODIFY |
參與者是否能夠修改事件 |
|
GUESTS_CAN_INVITE_OTHERS |
參與者是否能夠邀請其他參與者 |
|
GUESTS_CAN_SEE_GUESTS |
參與者是否能夠看到與會者列表 |
註:RFC5545地址:http://tools.ietf.org/html/rfc5545#section-3.8.2.5
給Events表添加資料
當你的應用程式要插入一個新的事件時,我們推薦你使用INSERT類型Intent對象(在“使用Intent對象來插入事件”一節中介紹)。但是,如果需要,你能夠直接插入事件,本節介紹怎樣做這件事情。
以下是針對插入一個新的事件的一些規則:
1. 必須包含CALENDAR_ID和DTSTART欄位
2. 必須包含EVENT_TIMEZONE欄位。使用getAvailableIDs()方法獲得系統已安裝的時區ID列表。注意如果通過INSTERT類型Intent對象來插入事件,那麼這個規則不適用,因為在INSERT對象的情境中會提供一個預設的時區;
3. 對於非重複發生的事件,必須包含DTEND欄位;
4. 對重複發生的事件,必須包含一個附加了RRULE或RDATE欄位的DURATIION欄位。注意,如果通過INSERT類型的Intent對象來插入一個事件,這個規則不適用。因為在這個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);
// 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類型的Intent對象,但是如果需要,你能夠直接編輯事件。你能夠提供要編輯的事件的_ID來執行事件的更新處理,這個ID既可以是附加給Uri的ID(用withAppendedId()方法),也可以是第一個選擇項。selection變數應該用“_id=?”來開頭,並且selectionArg參數的第一個值應該是這個事件的_ID值。你也能使用沒有ID的selection變數來做更新處理。下面的例子更新了用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");
myUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);
刪除Events表的資料
你能夠使用附加在URI上的_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);
Attendees表
CalendarContract.Attendees表的每一行代表一個事件的單一參與者。用給定的EVENT_ID調用query()方法能夠這個事件對應的參與者清單。EVENT_ID必須跟一個特殊的事件匹配。
下表列出Attendees表的可寫欄位,當插入一個新的與會者時,必須包含ATTENDEE_NAME以外的其他所有欄位。
|
常量 |
描述 |
|
EVENT_ID |
事件ID |
|
ATTENDEE_NAME |
與會者的名字 |
|
ATTENDEE_EMAIL |
與會者的電子郵件地址 |
|
ATTENDEE_RELATIONSHIP |
與會者與事件的關係,下列值之一
1. RELATIONSHIP_ATTENDEE
2. RELATIONSHIP_NONE
3. RELATIONSHIP_ORGANIZER
4. RELATIONSHIP_PERFORMER
5. RELATIONSHIP_SPEAKER |
|
ATTENDEE_TYPE |
與會者的類型。下列值之一
1. TYPE_REQUIRED
2. TYPE_OPTIONAL |
|
ATTENDEE_STATUS |
與會者的與會狀態。下列值之一:
1. ATTENDEE_STATUS_ACCEPTED
2. ATTENDEE_STATUS_DECLINED
3. ATTENDEE_STATUS_INVITED
4. ATTENDEE_STATUS_NONE
5. 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);
Reminders表
CalendarContract.Reminders表的每一行代表一個事件的一個提醒。用給定的EVENT_ID調用query()方法會返回這個事件的提醒列表。
下表列出了Reminders表的可寫欄位。當插入一個新的提醒時,必須包含所有這些欄位。注意,同步適配器在CalendarContract.Calendars表中指定了支援的提醒的類型。詳細內容請看ALLOWED_REMINDERS
http://developer.android.com/reference/android/provider/CalendarContract.CalendarColumns.html#ALLOWED_REMINDERS
|
常量 |
描述 |
|
EVENT_ID |
事件的ID |
|
MINUTES |
提供應該在幾分鐘之前觸發事件。 |
|
METHOD |
在服務上設定的警示的方法,下列設定之一:
1. METHOD_ALERT
2. METHOD_DEFAULT
3. METHOD_EMAIL
4. 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);
Instances表
CalendarContract.Instances表儲存一個事件的開始和結束時間。表中每一行代表一個單一發生的事件。Instances表不是可寫的,並且只提供一個查詢發生事件的方法。
下表列出了你能夠查詢的一些欄位,注意:時區是由KEY_TIMEZONE_TYPE和KEY_TIMEZONE_INSTANCES欄位定義的。
|
常量 |
描述 |
|
BEGIN |
這個事件執行個體的開始時間。UTC毫秒 |
|
END |
這個事件執行個體的結束時間。UTC毫秒 |
|
END_DAY |
這個事件執行個體的結束日,相對與日曆的時區 |
|
END_MINUTE |
從日曆的時區的0時開始計算的事件執行個體的結束分鐘數 |
|
EVENT_ID |
這個事件執行個體的事件ID |
|
START_DAY |
相對日曆時區的事件執行個體的開始日 |
|
START_MINUTE |
相對日曆時區的從0時開始計算的執行個體事件的開始分鐘數 |
查詢Instances表
要查詢Instances表,你需要在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()));
}
}