lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Trình cung cấp Lịch

Trình cung cấp Lịch là một kho lưu trữ các sự kiện lịch của người dùng. API Trình cung cấp Lịch cho phép bạn thực hiện truy vấn, chèn, cập nhật và xóa các thao tác trên lịch, sự kiện, người dự, nhắc nhở, v.v.

API Trình cung cấp Lịch có thể được sử dụng bởi các ứng dụng và trình điều hợp đồng bộ. Các quy tắc thay đổi tùy vào loại chương trình đang thực hiện lệnh gọi. Tài liệu này tập trung chủ yếu vào việc sử dụng API Trình cung cấp Lịch như một ứng dụng. Để bàn về việc các trình điều hợp đồng bộ khác nhau như thế nào, hãy xem phần Trình điều hợp Đồng bộ.

Thông thường, để đọc hoặc ghi dữ liệu lịch, bản kê khai của ứng dụng phải bao gồm các quyền thích hợp của người dùng, được nêu trong phần Quyền của Người dùng. Để thực hiện các thao tác chung dễ hơn, Trình cung cấp Lịch đưa ra một tập hợp ý định, như được mô tả trong phần Ý định Lịch. Những ý định này đưa người dùng tới ứng dụng Lịch để chèn, xem, và chỉnh sửa sự kiện. Người dùng tương tác với ứng dụng Lịch rồi quay lại ứng dụng ban đầu. Vì thế, ứng dụng của bạn không cần yêu cầu quyền, và cũng không cần cung cấp một giao diện người dùng để xem hoặc tạo sự kiện.

Nội dung Cơ bản

Các trình cung cấp nội dung sẽ lưu trữ dữ liệu và cho phép truy cập ứng dụng. Trình cung cấp nội dung được nền tảng Android giới thiệu (bao gồm Trình cung cấp Lịch) thường trình bày dữ liệu như một tập hợp gồm nhiều bảng dựa trên một mô hình cơ sở dữ liệu quan hệ, trong đó mỗi hàng là một bản ghi và mỗi cột là dữ liệu thuộc một loại và có ý nghĩa cụ thể. Thông qua API Trình cung cấp Lịch, các ứng dụng và trình điều hợp đồng bộ có thể nhận được quyền truy cập đọc/ghi vào các bảng trong cơ sở dữ liệu là nơi chứa dữ liệu lịch của người dùng.

Mọi trình cung cấp nội dung đều đưa ra một URI công khai (được bẻ dòng như một đối tượng Uri ) để xác định tập dữ liệu của nó một cách duy nhất. Trình cung cấp nội dung mà kiểm soát nhiều tập dữ liệu (nhiều bảng) sẽ đưa ra một URI riêng cho từng bảng. Tất cả URI cho trình cung cấp đều bắt đầu bằng xâu "content://". Điều này sẽ xác định dữ liệu là đang được kiểm soát bởi một trình cung cấp nội dung. Trình cung cấp Lịch định nghĩa các hằng số cho URI đối với từng lớp (bảng) của nó. Những URI này có định dạng <class>.CONTENT_URI. Ví dụ, Events.CONTENT_URI.

Hình 1 cho biết biểu diễn đồ họa của mô hình dữ liệu Trình cung cấp Lịch. Nó cho biết các bảng chính và các trường liên kết chúng với nhau.

Calendar Provider Data Model

Hình 1. Mô hình dữ liệu Trình cung cấp Lịch.

Một người dùng có thể có nhiều lịch, và các lịch khác nhau có thể được liên kết với các loại tài khoản khác nhau (Google Calendar, Exchange, v.v.).

CalendarContract sẽ định nghĩa mô hình dữ liệu của thông tin liên quan tới lịch và sự kiện. Dữ liệu này được lưu trữ trong nhiều bảng như liệt kê bên dưới.

Bảng (Lớp) Mô tả

CalendarContract.Calendars

Bảng này chứa thông tin riêng của lịch. Mỗi hàng trong bảng này chứa chi tiết của một lịch duy nhất, chẳng hạn như tên, màu, thông tin đồng bộ, v.v.
CalendarContract.Events Bảng này chứa thông tin riêng theo sự kiện. Mỗi hàng trong bảng có thông tin cho một sự kiện duy nhất—ví dụ: tiêu đề sự kiện, địa điểm, thời gian bắt đầu , thời gian kết thúc, v.v. Sự kiện có thể xảy ra một lần hoặc lặp lại nhiều lần. Người dự, nhắc nhở, và các tính chất mở rộng được lưu trữ trong các bảng riêng. Mỗi mục đều có một EVENT_ID tham chiếu tới _ID trong bảng Sự kiện.
CalendarContract.Instances Bảng này chứa thời gian bắt đầu và thời gian kết thúc của mỗi lần xảy ra một sự kiện. Mỗi hàng trong bảng này đại diện cho một lần xảy ra sự kiện. Với các sự kiện xảy ra một lần thì có một ánh xạ 1:1 của thực thể tới sự kiện. Đối với các sự kiện định kỳ, nhiều hàng sẽ tự động được khởi tạo tương ứng với nhiều lần xảy ra sự kiện đó.
CalendarContract.Attendees Bảng này chứa thông tin về người dự (khách) của sự kiện. Mỗi hàng đại diện một khách duy nhất của một sự kiện. Nó quy định loại khách và phản hồi tham dự của khách cho một sự kiện.
CalendarContract.Reminders Bảng này chứa dữ liệu về cảnh báo/thông báo. Mỗi hàng đại diện một cảnh báo duy nhất cho một sự kiện. Một sự kiện có thể có nhiều nhắc nhở. Số nhắc nhở tối đa của một sự kiện được quy định trong MAX_REMINDERS, được đặt bởi trình điều hợp đồng bộ đang sở hữu lịch đã cho. Nhắc nhở được quy định bằng số phút trước khi diễn ra sự kiện và có một phương pháp để xác định cách người dùng sẽ được cảnh báo.

API Trình cung cấp Lịch được thiết kế để linh hoạt và mạnh mẽ. Đồng thời, điều quan trọng là phải cung cấp một trải nghiệm người dùng cuối tốt và bảo vệ sự toàn vẹn của lịch và dữ liệu lịch. Để làm điều này, sau đây là một số điều cần ghi nhớ khi sử dụng API này:

  • Chèn, cập nhật, và xem sự kiện lịch. Để trực tiếp chèn, sửa đổi, và đọc sự kiện từ Trình cung cấp Lịch, bạn cần các quyền phù hợp. Tuy nhiên, nếu bạn không đang xây dựng một ứng dụng lịch hoặc trình điều hợp đồng bộ chính thức, việc yêu cầu những quyền này là không cần thiết. Thay vào đó, bạn có thể sử dụng những ý định được cung cấp bởi ứng dụng Lịch của Android để chuyển giao các thao tác đọc và ghi cho ứng dụng đó. Khi bạn sử dụng ý định, ứng dụng của bạn sẽ gửi người dùng tới ứng dụng Lịch để thực hiện thao tác mong muốn trong một mẫu được điền trước. Sau khi xong, họ sẽ được trả về ứng dụng của bạn. Bằng việc thiết kế ứng dụng của bạn để thực hiện các thao tác thường gặp thông qua Lịch, bạn cung cấp cho người dùng một giao diện người dùng nhất quán, thiết thực. Đây là phương pháp được khuyến cáo nên dùng. Để biết thêm thông tin, hãy xem phần Ý định Lịch.

  • Trình điều hợp đồng bộ. Trình điều hợp đồng bộ có chức năng đồng bộ dữ liệu lịch lên thiết bị của một người dùng bằng một máy chủ hoặc nguồn dữ liệu khác. Trong bảng CalendarContract.CalendarsCalendarContract.Events, có các cột để cho trình điều hợp đồng bộ sử dụng. Trình cung cấp và ứng dụng không nên sửa đổi chúng. Trên thực tế, chúng không hiển thị trừ khi được truy cập như một trình điều hợp đồng bộ. Để biết thêm thông tin về trình điều hợp đồng bộ, hãy xem phần Trình điều hợp Đồng bộ.

Quyền của Người dùng

Để đọc dữ liệu lịch, một ứng dụng phải bao gồm quyền READ_CALENDAR trong tệp bản kê khai của mình. Nó phải bao gồm quyền WRITE_CALENDAR để xóa, chèn hoặc cập nhật dữ liệu lịch:

<?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>

Bảng Lịch

Bảng CalendarContract.Calendars chứa thông tin chi tiết cho từng lịch. Các cột Lịch sau có thể ghi được bởi cả ứng dụng và trình điều hợp đồng bộ. Để xem danh sách đầy đủ về các trường được hỗ trợ, hãy xem tài liệu tham khảo CalendarContract.Calendars.

Hằng số Mô tả
NAME Tên của lịch.
CALENDAR_DISPLAY_NAME Tên của lịch này mà được hiển thị cho người dùng.
VISIBLE Một boolean cho biết lịch có được chọn để hiển thị hay không. Giá trị bằng 0 cho biết các sự kiện liên kết với lịch này sẽ không được hiển thị. Giá trị bằng 1 cho biết các sự kiện liên kết với lịch này sẽ được hiển thị. Giá trị này ảnh hưởng tới việc khởi tạo hàng trong bảng CalendarContract.Instances.
SYNC_EVENTS Một boolean cho biết lịch sẽ được đồng bộ và có các sự kiện của mình được lưu trữ trên thiết bị hay không. Giá trị bằng 0 tức là không đồng bộ lịch này hay lưu giữ các sự kiện của nó lên thiết bị. Giá trị bằng 1 tức là đồng bộ các sự kiện cho lịch này và lưu trữ các sự kiện của nó lên thiết bị.

Truy vấn một lịch

Sau đây là một ví dụ về cách nhận được lịch do một người dùng cụ thể sở hữu. Để đơn giản, trong ví dụ này, thao tác truy vấn được thể hiện trong luồng giao diện người dùng ("luồng chính"). Trong thực hành, nên làm điều này trong một luồng không đồng bộ thay vì trên luồng chính. Để bàn thêm, hãy xem phần Trình tải. Nếu bạn đang không chỉ đọc dữ liệu mà còn sửa đổi nó, hãy xem AsyncQueryHandler.

// 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
    Calendars.OWNER_ACCOUNT                  // 3
};

// 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;
private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;

Trong phần tiếp theo của ví dụ, bạn sẽ xây dựng truy vấn của mình. Lựa chọn này sẽ quy định các tiêu chí cho truy vấn. Trong ví dụ này, truy vấn đang tìm các lịch có ACCOUNT_NAME "sampleuser@google.com", ACCOUNT_TYPE "com.google", và OWNER_ACCOUNT "sampleuser@google.com". Nếu bạn muốn xem tất cả lịch mà một người dùng đã xem, không chỉ các lịch mà người dùng sở hữu, hãy bỏ qua OWNER_ACCOUNT. Truy vấn sẽ trả về đối tượng Cursor mà bạn có thể sử dụng để xem xét tập kết quả được trả về bởi truy vấn cơ sở dữ liệu. Để bàn thêm về việc sử dụng các truy vấn trong trình cung cấp nội dung, hãy xem phần Trình cung cấp Nội dung.

// Run query
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"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

Phần tiếp theo sử dụng con chạy để duyệt qua tập kết quả. Nó sử dụng các hằng số được thiết lập ngay từ đầu ví dụ để trả về các giá trị cho mỗi trường.

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    long calID = 0;
    String displayName = null;
    String accountName = null;
    String ownerName = 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);
    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);

    // Do something with the values...

   ...
}

Sửa đổi một lịch

Để thực hiện cập nhật một lịch, bạn có thể cung cấp _ID của lịch hoặc dưới dạng ID được nối vào cho Uri (withAppendedId()) hoặc dưới dạng mục chọn đầu tiên. Lựa chọn nên bắt đầu bằng "_id=?", và selectionArg đầu tiên sẽ là _ID của lịch. Bạn cũng có thể thực hiện cập nhật bằng cách mã hóa ID trong URI. Ví dụ này thay đổi tên hiển thị của một lịch bằng cách sử dụng phương pháp (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);

Chèn một lịch

Lịch được thiết kế để được quản lý chủ yếu bởi một trình điều hợp đồng bộ, vì vậy bạn chỉ nên chèn các lịch mới như một trình điều hợp đồng bộ. Phần lớn thì các ứng dụng chỉ có thể thực hiện những thay đổi bề mặt về lịch chẳng hạn như thay đổi tên hiển thị. Nếu một ứng dụng cần tạo một lịch cục bộ, nó có thể làm điều này bằng cách thực hiện chèn lịch dưới dạng một trình điều hợp đồng bộ, sử dụng ACCOUNT_TYPE của ACCOUNT_TYPE_LOCAL. ACCOUNT_TYPE_LOCAL là một loại tài khoản đặc biệt dành cho các lịch không liên kết với một tài khoản thiết bị. Các lịch loại này không được đồng bộ với một máy chủ. Để bàn về trình điều hợp đồng bộ, hãy xem phần Trình điều hợp Đồng bộ.

Bảng Sự kiện

Bảng CalendarContract.Events chứa thông tin chi tiết cho các sự kiện riêng lẻ. Để thêm, cập nhật hoặc xóa sự kiện, ứng dụng phải bao gồm quyền WRITE_CALENDAR trong tệp bản kê khai của mình.

Các cột Sự kiện sau có thể ghi được bởi cả ứng dụng và trình điều hợp đồng bộ. Để xem danh sách đầy đủ về các trường được hỗ trợ, hãy xem tài liệu tham khảo CalendarContract.Events.

Hằng số Mô tả
CALENDAR_ID _ID của lịch mà chứa sự kiện.
ORGANIZER E-mail của người tổ chức (người chủ) của sự kiện.
TITLE Tiêu đề của sự kiện.
EVENT_LOCATION Nơi sự kiện diễn ra.
DESCRIPTION Mô tả sự kiện.
DTSTART Thời gian sự kiện bắt đầu tính bằng mili giây UTC trôi qua kể từ giờ epoch.
DTEND Thời gian sự kiện kết thúc tính bằng mili giây UTC trôi qua kể từ giờ epoch.
EVENT_TIMEZONE Múi giờ của sự kiện.
EVENT_END_TIMEZONE Múi giờ của thời điểm kết thúc sự kiện.
DURATION Thời lượng của sự kiện theo định dạng RFC5545. Ví dụ, giá trị bằng "PT1H" cho biết sự kiện sẽ kéo dài một giờ và giá trị bằng "P2W" cho biết thời lượng là 2 tuần.
ALL_DAY Giá trị bằng 1 cho biết sự kiện này chiếm cả ngày, được xác định bởi múi giờ tại địa phương. Giá trị bằng 0 cho biết đó là một sự kiện thường xuyên mà có thể bắt đầu và kết thúc vào bất cứ lúc nào trong một ngày.
RRULE Quy tắc lặp lại đối với định dạng sự kiện. Ví dụ, "FREQ=WEEKLY;COUNT=10;WKST=SU". Bạn có thể tìm thêm nhiều ví dụ hơn ở đây.
RDATE Ngày lặp lại đối với sự kiện. Bạn thường sử dụng RDATE cùng với RRULE để định nghĩa một tập tổng hợp các trường hợp xảy ra lặp lại. Để bàn thêm, hãy xem phần RFC5545 spec.
AVAILABILITY Xem sự kiện này được tính là thời gian bận hay là thời gian rảnh có thể được xếp lại lịch.
GUESTS_CAN_MODIFY Khách có thể sửa đổi sự kiện được hay không.
GUESTS_CAN_INVITE_OTHERS Khách có thể mời khách khác được hay không.
GUESTS_CAN_SEE_GUESTS Khách có thể xem danh sách người dự được hay không.

Thêm Sự kiện

Khi ứng dụng của bạn chèn một sự kiện mới, chúng tôi khuyến cáo bạn nên sử dụng một Ý định INSERT, như được mô tả trong Sử dụng ý định để chèn một sự kiện. Tuy nhiên, nếu cần, bạn có thể chèn sự kiện trực tiếp. Phần này mô tả cách làm điều này.

Sau đây là các quy tắc để chèn một sự kiện mới:

  • Bạn phải đưa vào CALENDAR_IDDTSTART.
  • Bạn phải đưa vào một EVENT_TIMEZONE. Để nhận một danh sách các ID múi giờ được cài đặt của hệ thống, hãy sử dụng getAvailableIDs(). Lưu ý rằng quy tắc này không áp dụng nếu bạn đang chèn một sự kiện thông qua Ý định INSERT như được mô tả trong Sử dụng ý định để chèn một sự kiện—trong kịch bản đó, một múi giờ mặc định sẽ được cung cấp.
  • Đối với các sự kiện không định kỳ, bạn phải đưa vào DTEND.
  • Đối với các sự kiện định kỳ, bạn phải đưa vào một DURATION bên cạnh RRULE hay RDATE. Lưu ý rằng quy tắc này không áp dụng nếu bạn đang chèn một sự kiện thông qua Ý định INSERT như được mô tả trong Sử dụng ý định để chèn một sự kiện—trong kịch bản đó, bạn có thể sử dụng một RRULE cùng với DTSTARTDTEND, và ứng dụng Lịch sẽ tự động chuyển nó thành một thời lượng.

Sau đây là một ví dụ về cách chèn một sự kiện. Ví dụ này đang được thực hiện trong luồng UI để cho đơn giản. Trong thực hành, chèn và cập nhật nên được thực hiện trong một luồng không đồng bộ để di chuyển hành động vào một luồng chạy ngầm. Để biết thêm thông tin, hãy xem phần 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
//
//

Lưu ý: Xem cách mà ví dụ này bắt được ID sự kiện sau khi sự kiện được tạo. Đây là cách dễ nhất để nhận được một ID sự kiện. Bạn thường cần ID sự kiện để thực hiện các thao tác lịch khác—ví dụ: để thêm người dự hoặc nhắc nhở vào một sự kiện.

Cập nhật Sự kiện

Khi ứng dụng của bạn muốn cho phép người dùng chỉnh sửa một sự kiện, chúng tôi khuyến cáo bạn nên sử dụng một Ý định EDIT như được mô tả trong Sử dụng ý định để chỉnh sửa một sự kiện. Tuy nhiên, nếu cần, bạn có thể chỉnh sửa sự kiện trực tiếp. Để thực hiện cập nhật một Sự kiện, bạn có thể cung cấp _ID của sự kiện hoặc dưới dạng ID được nối vào cho Uri (withAppendedId()) hoặc dưới dạng mục chọn đầu tiên. Lựa chọn nên bắt đầu bằng "_id=?", và selectionArg đầu tiên nên là _ID của sự kiện. Bạn cũng có thể thực hiện cập nhật bằng cách sử dụng một lựa chọn không có ID. Sau đây là một ví dụ về cách cập nhật một sự kiện. Nó thay đổi tiêu đề của sự kiện bằng cách sử dụng phương pháp 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);  

Xóa Sự kiện

Bạn có thể xóa một sự kiện hoặc theo _ID của nó như một ID được nối trên URI, hoặc bằng cách sử dụng lựa chọn tiêu chuẩn. Nếu sử dụng một ID được nối, bạn không thể lựa chọn đồng thời. Có hai kiểu xóa: như một ứng dụng và như một trình điều hợp đồng bộ. Xóa như một ứng dụng sẽ đặt cột đã xóa thành 1. Cờ này sẽ báo cho trình điều hợp đồng bộ rằng hàng đó đã được xóa và rằng việc xóa này nên được truyền tới máy chủ. Xóa trình điều hợp đồng bộ sẽ gỡ bỏ sự kiện khỏi cơ sở dữ liệu cùng với tất cả dữ liệu được liên kết của nó. Sau đây là một ví dụ về ứng dụng xóa một sự kiện thông qua _ID của nó:

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

Bảng Người dự

Mỗi hàng của bảng CalendarContract.Attendees đại diện cho một người dự hoặc khách duy nhất của một sự kiện. Gọi query() sẽ trả về một danh sách người dự cho sự kiện với EVENT_ID đã cho. EVENT_ID này phải khớp với _ID của một sự kiện cụ thể.

Bảng sau liệt kê các trường có thể ghi được. Khi chèn một người dự mới, bạn phải điền tất cả ngoại trừ ATTENDEE_NAME.

Hằng số Mô tả
EVENT_ID ID của sự kiện.
ATTENDEE_NAME Tên của người dự.
ATTENDEE_EMAIL Địa chỉ e-mail của người dự.
ATTENDEE_RELATIONSHIP

Mối quan hệ của người dự với sự kiện. Một trong:

ATTENDEE_TYPE

Loại người dự. Một trong:

ATTENDEE_STATUS

Trạng thái tham dự của người dự. Một trong:

Thêm Người dự

Sau đây là một ví dụ về cách thêm một người dự vào một sự kiện. Lưu ý rằng EVENT_ID là bắt buộc:

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

Bảng Nhắc nhở

Mỗi hàng của bảng CalendarContract.Reminders đại diện cho một nhắc nhở của một sự kiện. Gọi query() sẽ trả về một danh sách nhắc nhở cho sự kiện với EVENT_ID đã cho.

Bảng sau liệt kê các trường ghi được đối với nhắc nhở. Tất cả đều phải được đưa vào khi chèn một nhắc nhở mới. Lưu ý rằng các trình điều hợp đồng bộ quy định các loại nhắc nhở chúng hỗ trợ trong bảng CalendarContract.Calendars. Xem ALLOWED_REMINDERS để biết chi tiết.

Hằng số Mô tả
EVENT_ID ID của sự kiện.
MINUTES Số phút trước khi diễn ra sự kiện mà nhắc nhở cần báo.
METHOD

Phương pháp báo thức, như được đặt trên máy chủ. Một trong:

Thêm Nhắc nhở

Ví dụ này thêm nhắc nhở vào một sự kiện. Nhắc nhở sẽ báo 15 phút trước khi xảy ra sự kiện.

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

Bảng Thực thể

Bảng CalendarContract.Instances chứa thời gian bắt đầu và thời gian kết thúc của các lần xảy ra một sự kiện. Mỗi hàng trong bảng này đại diện cho một lần xảy ra sự kiện. Bảng thực thể không ghi được và chỉ đưa ra một cách để truy vấn các lần xảy ra sự kiện.

Bảng sau liệt kê một số trường mà bạn có thể truy vấn đối với một thực thể. Lưu ý rằng múi giờ được định nghĩa bởi KEY_TIMEZONE_TYPEKEY_TIMEZONE_INSTANCES.

Hằng số Mô tả
BEGIN Thời gian bắt đầu của thực thể, tính bằng mili giây UTC.
END Thời gian kết thúc của thực thể, tính bằng mili giây UTC.
END_DAY Ngày kết thúc theo lịch Julian của thực thể theo múi giờ của Lịch.
END_MINUTE Phút kết thúc của thực thể được xác định từ nửa đêm theo múi giờ của Lịch.
EVENT_ID _ID của sự kiện đối với thực thể này.
START_DAY Ngày bắt đầu theo lịch Julian của thực thể theo múi giờ của Lịch.
START_MINUTE Phút bắt đầu của thực thể được xác định từ nửa đêm theo múi giờ của Lịch.

Truy vấn bảng Thực thể

Để truy vấn bảng Thực thể, bạn cần chỉ định một khoảng thời gian cho truy vấn trong URI. Trong ví dụ này, CalendarContract.Instances có quyền truy cập trường TITLE thông qua việc triển khai giao diện CalendarContract.EventsColumns của nó. Nói cách khác, TITLE được trả về qua một chế độ xem cơ sở dữ liệu, chứ không qua việc truy vấn bảng CalendarContract.Instances thô.

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

Ý định Lịch

Ứng dụng của bạn không cần quyền để ghi và đọc dữ liệu lịch. Thay vào đó, nó có thể sử dụng những ý định được cung cấp bởi ứng dụng Lịch của Android để chuyển giao các thao tác đọc và ghi cho ứng dụng đó. Bảng sau đây liệt kê các ý định được Trình cung cấp Lịch hỗ trợ:

Hành động URI Mô tả Phụ thêm

VIEW

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

Bạn cũng có thể tham khảo tới URI bằng CalendarContract.CONTENT_URI. Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để xem dữ liệu lịch.
Mở lịch đến thời gian được chỉ định bởi <ms_since_epoch>. Không có.

VIEW

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

Bạn cũng có thể tham khảo tới URI bằng Events.CONTENT_URI. Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để xem dữ liệu lịch.
Xem sự kiện được chỉ định bởi <event_id>. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

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

Bạn cũng có thể tham khảo tới URI bằng Events.CONTENT_URI. Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để chỉnh sửa một sự kiện.
Chỉnh sửa sự kiện được chỉ định bởi <event_id>. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

Bạn cũng có thể tham khảo tới URI bằng Events.CONTENT_URI. Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để chèn một sự kiện.
Tạo một sự kiện. Bất kỳ phụ thêm nào được liệt kê trong bảng bên dưới.

Bảng sau đây liệt kê các phụ thêm ý định được Trình cung cấp Lịch hỗ trợ:

Phụ thêm Ý định Mô tả
Events.TITLE Tên cho sự kiện.
CalendarContract.EXTRA_EVENT_BEGIN_TIME Thời gian bắt đầu sự kiện tính bằng mili giây trôi qua kể từ giờ epoch.
CalendarContract.EXTRA_EVENT_END_TIME Thời gian kết thúc sự kiện tính bằng mili giây trôi qua kể từ giờ epoch.
CalendarContract.EXTRA_EVENT_ALL_DAY Một boolean cho biết đó là một sự kiện cả ngày. Giá trị có thể bằng true hoặc false.
Events.EVENT_LOCATION Địa điểm của sự kiện.
Events.DESCRIPTION Mô tả sự kiện.
Intent.EXTRA_EMAIL Địa chỉ e-mail của những người cần mời dưới dạng một danh sách phân cách bởi dấu phẩy.
Events.RRULE Quy tắc lặp lại đối với sự kiện.
Events.ACCESS_LEVEL Sự kiện là riêng tư hay công khai.
Events.AVAILABILITY Xem sự kiện này tính là thời gian bận hay là thời gian rảnh có thể được xếp lại lịch.

Các phần sau mô tả cách sử dụng những ý định này.

Sử dụng ý định để chèn một sự kiện

Sử dụng Ý định INSERT cho phép ứng dụng của bạn chuyển giao tác vụ chèn sự kiện cho bản thân Lịch. Bằng cách này, ứng dụng của bạn thậm chí không cần phải có quyền WRITE_CALENDAR được bao gồm trong tệp bản kê khai của mình.

Khi người dùng chạy một ứng dụng mà sử dụng cách này, ứng dụng sẽ gửi chúng tới Lịch để hoàn thành việc thêm một sự kiện. Ý định INSERT sử dụng các trường phụ thêm để điền trước vào một mẫu bằng các chi tiết của sự kiện trong Lịch. Khi đó, người dùng có thể hủy bỏ sự kiện, chỉnh sửa mẫu nếu cần, hoặc lưu sự kiện vào lịch của mình.

Sau đây là một đoạn mã HTML lập biểu một sự kiện vào ngày 19/1/2012, diễn ra từ 7:30 sáng đến 8:30 sáng. Lưu ý điều sau đây về đoạn mã HTML này:

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

Sử dụng ý định để chỉnh sửa một sự kiện

Bạn có thể cập nhật một sự kiện trực tiếp như được mô tả trong phần Cập nhật sự kiện. Nhưng việc sử dụng Ý định EDIT cho phép một ứng dụng không có quyền được chuyển giao chỉnh sửa sự kiện cho ứng dụng Lịch. Khi người dùng hoàn thành chỉnh sửa sự kiện của mình trong Lịch, họ được trả về ứng dụng ban đầu.

Sau đây là một ví dụ về ý định đặt một tiêu đề mới cho một sự kiện được quy định và cho phép người dùng chỉnh sửa sự kiện trong Lịch.

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

Sử dụng ý định để xem dữ liệu lịch

Trình cung cấp Lịch giới thiệu hai cách khác nhau để sử dụng Ý định VIEW:

  • Để mở Lịch tới một ngày cụ thể.
  • Để xem một sự kiện.

Sau đây là một ví dụ cho biết cách mở Lịch tới một ngày cụ thể:

// A date-time specified in milliseconds since the epoch.
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);

Sau đây là một ví dụ cho biết cách mở một sự kiện để xem:

long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
   .setData(uri);
startActivity(intent);

Trình điều hợp Đồng bộ

Chỉ có vài điểm khác nhau nhỏ giữa cách một ứng dụng và cách một trình điều hợp đồng bộ truy cập Trình cung cấp Lịch:

  • Trình điều hợp đồng bộ cần chỉ định rằng nó là một trình điều hợp đồng bộ bằng cách đặt CALLER_IS_SYNCADAPTER thành true.
  • Trình điều hợp đồng bộ cần cung cấp một ACCOUNT_NAME và một ACCOUNT_TYPE làm tham số truy vấn trong URI.
  • Trình điều hợp đồng bộ có quyền truy nhập ghi vào nhiều cột hơn ứng dụng hay widget. Ví dụ, một ứng dụng chỉ có thể sửa đổi một vài đặc điểm của một lịch, chẳng hạn như tên lịch, tên hiển thị, thiết đặt hiển thị, và lịch có được đồng bộ hay không. Nếu so sánh, một trình điều hợp đồng bộ có thể truy cập không chỉ những cột đó, mà còn nhiều cột khác, chẳng hạn như màu lịch, múi giờ, mức truy nhập, địa điểm, v.v. Tuy nhiên, trình điều hợp đồng bộ bị hạn chế đối với ACCOUNT_NAMEACCOUNT_TYPE mà nó quy định.

Sau đây là một phương pháp hữu ích hơn mà bạn có thể sử dụng để trả về một URI để dùng với một trình điều hợp đồng bộ:

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

Để biết việc triển khai mẫu trình điều hợp đồng bộ (không liên quan cụ thể tới Lịch), hãy xem phần SampleSyncAdapter.