Android 日曆提供器(二)

Calendars表html

CalendarContract.Calendars表包含了單個日曆的詳細信息。下表中Calendars表列對應用程序和同步適配器都是可寫的。對於這個表支持的完整的字段列表,請看「CalendarContract.Calendars參考」android

http://developer.android.com/reference/android/provider/CalendarContract.Calendars.html數據庫

常量數組

描述服務器

NAMEapp

日曆的名字異步

CALENDAR_DISPLAY_NAMEide

顯示給用戶的名字ui

VISIBLEthis

一個指明被選擇的日曆是否顯示的布爾值。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");
updateUri= 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 instancesCalendar 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 tableString 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 querycur =  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()));        } }

相關文章
相關標籤/搜索