Tổng quan về 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 trên lịch của người dùng. API Nhà cung cấp Lịch cho phép bạn thực hiện các thao tác truy vấn, chèn, cập nhật và xoá trên lịch, sự kiện, người tham dự, lời nhắc, v.v.

Các ứng dụng và bộ điều hợp đồng bộ hoá có thể sử dụng Calendar Provider API. Các quy tắc này còn tuỳ thuộc vào loại chương trình đang thực hiện lệnh gọi. Tài liệu này chủ yếu tập trung vào việc sử dụng Calendar Provider API dưới dạng một ứng dụng. Để thảo luận về sự khác biệt của các bộ chuyển đổi đồng bộ hoá, hãy xem bài viết Bộ điều hợp đồng bộ hoá.

Thông thường, để đọc hoặc ghi dữ liệu lịch, tệp kê khai của ứng dụng phải bao gồm các quyền thích hợp, được mô tả trong phần Quyền của người dùng. Để thực hiện các thao tác phổ biến dễ dàng hơn, Nhà cung cấp lịch cung cấp một tập hợp ý định như mô tả trong phần Ý định lịch. Các ý định này đưa người dùng đến ứ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, sau đó quay lại ứng dụng ban đầu. Do đó, ứng dụng của bạn không cần yêu cầu quyền mà cũng không cần cung cấp giao diện người dùng để xem hoặc tạo sự kiện.

Thông tin cơ bản

Trình cung cấp nội dung lưu trữ dữ liệu và giúp ứng dụng truy cập vào dữ liệu đó. Các trình cung cấp nội dung do nền tảng Android cung cấp (bao gồm cả Nhà cung cấp lịch) thường hiển thị dữ liệu dưới dạng một tập hợp bảng dựa trên 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 kiểu và ý nghĩa cụ thể. Thông qua Calendar Provider API, các ứng dụng và bộ điều hợp đồng bộ hoá có thể truy cập đọc/ghi vào các bảng cơ sở dữ liệu lưu giữ dữ liệu lịch của người dùng.

Mỗi trình cung cấp nội dung sẽ hiển thị một URI công khai (được bao bọc dưới dạng đối tượng Uri) giúp xác định duy nhất tập dữ liệu của nó. Một trình cung cấp nội dung kiểm soát nhiều tập dữ liệu (nhiều bảng) sẽ hiển thị một URI riêng cho từng tập. Tất cả các URI cho nhà cung cấp đều bắt đầu bằng chuỗi "content://". Trường hợp này xác định dữ liệu do một trình cung cấp nội dung kiểm soát. Nhà cung cấp lịch xác định các hằng số cho các URI cho từng lớp (bảng). Các URI này có định dạng <class>.CONTENT_URI. Ví dụ: Events.CONTENT_URI.

Hình 1 cho thấy bản trình bày dạng đồ hoạ của mô hình dữ liệu của Nhà cung cấp lịch. Nó cho thấy các bảng chính và các trường liên kết chúng với nhau.

Mô hình dữ liệu của nhà cung cấp lịch

Hình 1. Mô hình dữ liệu của 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 (Lịch Google, Exchange, v.v.).

CalendarContract xác định mô hình dữ liệu của thông tin liên quan đến lịch và sự kiện. Dữ liệu này được lưu trữ trong một số bảng, được liệt kê dưới đây.

Bảng (Lớp) Nội dung mô tả

CalendarContract.Calendars

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

Calendar Provider API được thiết kế để linh hoạt và mạnh mẽ. Đồng thời, việc cung cấp trải nghiệm tốt cho người dùng cuối và bảo vệ tính toàn vẹn của lịch cũng như dữ liệu của lịch cũng rất quan trọng. Do đó, sau đây là một số điều cần lưu ý khi sử dụng API:

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

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

Để đọc dữ liệu lịch, ứng dụng phải đưa quyền READ_CALENDAR vào tệp kê khai. Lịch này phải bao gồm quyền WRITE_CALENDAR để xoá, 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ả ứng dụng và bộ chuyển đổi đồng bộ hoá đều có thể ghi các cột Lịch sau đây. Để biết danh sách đầy đủ các trường được hỗ trợ, hãy xem tài liệu tham khảo CalendarContract.Calendars.

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

Bao gồm một loại tài khoản cho tất cả các hoạt động

Nếu truy vấn trên Calendars.ACCOUNT_NAME, bạn cũng phải đưa Calendars.ACCOUNT_TYPE vào lựa chọn. Lý do là một tài khoản nhất định chỉ được coi là duy nhất khi có cả ACCOUNT_NAMEACCOUNT_TYPE. ACCOUNT_TYPE là chuỗi tương ứng với trình xác thực tài khoản được sử dụng khi tài khoản được đăng ký bằng AccountManager. Ngoài ra, còn có một loại tài khoản đặc biệt tên là ACCOUNT_TYPE_LOCAL cho các lịch không liên kết với tài khoản thiết bị. Các tài khoản ACCOUNT_TYPE_LOCAL không được đồng bộ hóa.

Truy vấn lịch

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

Kotlin

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
private val EVENT_PROJECTION: Array<String> = arrayOf(
        CalendarContract.Calendars._ID,                     // 0
        CalendarContract.Calendars.ACCOUNT_NAME,            // 1
        CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,   // 2
        CalendarContract.Calendars.OWNER_ACCOUNT            // 3
)

// The indices for the projection array above.
private const val PROJECTION_ID_INDEX: Int = 0
private const val PROJECTION_ACCOUNT_NAME_INDEX: Int = 1
private const val PROJECTION_DISPLAY_NAME_INDEX: Int = 2
private const val PROJECTION_OWNER_ACCOUNT_INDEX: Int = 3

Java

// 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ẽ tạo truy vấn. Lựa chọn này xác định tiêu chí cho truy vấn. Trong ví dụ này, truy vấn tìm kiếm lịch có ACCOUNT_NAME "hera@example.com", ACCOUNT_TYPE "com.example" và OWNER_ACCOUNT "hera@example.com". Nếu bạn muốn xem tất cả các lịch mà người dùng đã xem, chứ không chỉ các lịch mà người dùng sở hữu, hãy bỏ qua OWNER_ACCOUNT. Truy vấn này trả về một đối tượng Cursor mà bạn có thể sử dụng để truyền tải tập hợp kết quả do truy vấn cơ sở dữ liệu trả về. Để thảo luận thêm về cách sử dụng truy vấn trong trình cung cấp nội dung, hãy xem bài viết Trình cung cấp nội dung.

Kotlin

// Run query
val uri: Uri = CalendarContract.Calendars.CONTENT_URI
val selection: String = "((${CalendarContract.Calendars.ACCOUNT_NAME} = ?) AND (" +
        "${CalendarContract.Calendars.ACCOUNT_TYPE} = ?) AND (" +
        "${CalendarContract.Calendars.OWNER_ACCOUNT} = ?))"
val selectionArgs: Array<String> = arrayOf("hera@example.com", "com.example", "hera@example.com")
val cur: Cursor = contentResolver.query(uri, EVENT_PROJECTION, selection, selectionArgs, null)

Java

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

Phần tiếp theo này sử dụng con trỏ để duyệt qua tập hợp kết quả. Phương thức này sử dụng các hằng số đã thiết lập ở phần đầu ví dụ để trả về giá trị cho từng trường.

Kotlin

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    // Get the field values
    val calID: Long = cur.getLong(PROJECTION_ID_INDEX)
    val displayName: String = cur.getString(PROJECTION_DISPLAY_NAME_INDEX)
    val accountName: String = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX)
    val ownerName: String = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX)
    // Do something with the values...
}

Java

// 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 lịch

Để cập nhật lịch, bạn có thể cung cấp _ID của lịch dưới dạng mã nhận dạng được nối thêm vào URI (withAppendedId()) hoặc dưới dạng mục lựa chọn đầu tiên. Lựa chọn phải bắt đầu bằng "_id=?"selectionArg đầu tiên phải là _ID của lịch. Bạn cũng có thể cập nhật bằng cách mã hoá mã nhận dạng trong URI. Ví dụ này thay đổi tên hiển thị của lịch bằng cách sử dụng phương pháp (withAppendedId()):

Kotlin

const val DEBUG_TAG: String = "MyActivity"
...
val calID: Long = 2
val values = ContentValues().apply {
    // The new display name for the calendar
    put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar")
}
val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Calendars.CONTENT_URI, calID)
val rows: Int = contentResolver.update(updateUri, values, null, null)
Log.i(DEBUG_TAG, "Rows updated: $rows")

Java

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 lịch

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

Bảng sự kiện

Bảng CalendarContract.Events chứa thông tin chi tiết cho từng sự kiện. Để thêm, cập nhật hoặc xoá sự kiện, một ứng dụng phải đưa quyền WRITE_CALENDAR vào tệp kê khai của ứng dụng đó.

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

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

Thêm sự kiện

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

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

  • Bạn phải thêm CALENDAR_IDDTSTART.
  • Bạn phải thêm một EVENT_TIMEZONE. Để nhận danh sách mã múi giờ đã cài đặt của hệ thống, hãy sử dụng getAvailableIDs(). Xin lưu ý rằng quy tắc này không áp dụng nếu bạn chèn một sự kiện thông qua Ý định INSERT, được mô tả trong phần Sử dụng ý định để chèn sự kiện – trong trường hợp đó, 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 sử dụng DTEND.
  • Đối với các sự kiện định kỳ, bạn phải thêm một DURATION vào ngoài RRULE hoặc RDATE. Xin lưu ý rằng quy tắc này không áp dụng nếu bạn chèn một sự kiện thông qua Ý định INSERT (được mô tả trong phần Sử dụng ý định để chèn sự kiện). Trong trường hợp đó, bạn có thể sử dụng RRULE cùng với DTSTARTDTEND. Ứng dụng Lịch sẽ tự động chuyển đổi sự kiện đó thành thời lượng.

Dưới đây là ví dụ về cách chèn một sự kiện. Việc này được thực hiện trong luồng giao diện người dùng để đơn giản hoá. Trong thực tế, bạn nên chèn và cập nhật trong một luồng không đồng bộ để chuyển thao tác đó vào một luồng trong nền. Để biết thêm thông tin, hãy xem AsyncQueryHandler.

Kotlin

val calID: Long = 3
val startMillis: Long = Calendar.getInstance().run {
    set(2012, 9, 14, 7, 30)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2012, 9, 14, 8, 45)
    timeInMillis
}
...

val values = ContentValues().apply {
    put(CalendarContract.Events.DTSTART, startMillis)
    put(CalendarContract.Events.DTEND, endMillis)
    put(CalendarContract.Events.TITLE, "Jazzercise")
    put(CalendarContract.Events.DESCRIPTION, "Group workout")
    put(CalendarContract.Events.CALENDAR_ID, calID)
    put(CalendarContract.Events.EVENT_TIMEZONE, "America/Los_Angeles")
}
val uri: Uri = contentResolver.insert(CalendarContract.Events.CONTENT_URI, values)

// get the event ID that is the last element in the Uri
val eventID: Long = uri.lastPathSegment.toLong()
//
// ... do something with event ID
//
//

Java

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 ý: Hãy xem cách ví dụ này ghi lại mã sự kiện sau khi tạo sự kiện. Đây là cách dễ nhất để lấy mã sự kiện. Bạn thường cần mã sự kiện để thực hiện các thao tác khác trên lịch, ví dụ: thêm người tham dự hoặc lời nhắc vào một sự kiện.

Số sự kiện cập nhật

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

Kotlin

val DEBUG_TAG = "MyActivity"
...
val eventID: Long = 188
...
val values = ContentValues().apply {
    // The new title for the event
    put(CalendarContract.Events.TITLE, "Kickboxing")
}
val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val rows: Int = contentResolver.update(updateUri, values, null, null)
Log.i(DEBUG_TAG, "Rows updated: $rows")

Java

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 = cr.update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);

Xóa sự kiện

Bạn có thể xoá một sự kiện theo _ID của sự kiện đó dưới dạng mã nhận dạng kèm theo trên URI, hoặc bằng cách sử dụng lựa chọn chuẩn. Nếu dùng mã nhận dạng đã thêm vào, thì bạn cũng không thể lựa chọn. Có hai phiên bản xoá: dưới dạng ứng dụng và dưới dạng bộ điều hợp đồng bộ hoá. Thao tác xoá một ứng dụng sẽ đặt cột đã xoá thành 1. Cờ này cho bộ điều hợp đồng bộ biết rằng hàng đã bị xoá và hoạt động xoá này sẽ được truyền đến máy chủ. Thao tác xoá bộ chuyển đổi đồng bộ hoá sẽ xoá sự kiện khỏi cơ sở dữ liệu cùng với tất cả dữ liệu liên quan. Dưới đây là ví dụ về ứng dụng xoá một sự kiện thông qua _ID của ứng dụng đó:

Kotlin

val DEBUG_TAG = "MyActivity"
...
val eventID: Long = 201
...
val deleteUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val rows: Int = contentResolver.delete(deleteUri, null, null)
Log.i(DEBUG_TAG, "Rows deleted: $rows")

Java

private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = cr.delete(deleteUri, null, null);
Log.i(DEBUG_TAG, "Rows deleted: " + rows);

Bảng người tham dự

Mỗi hàng của bảng CalendarContract.Attendees đại diện cho một người tham dự hoặc khách của một sự kiện. Thao tác gọi query() sẽ trả về danh sách người tham dự 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 đây liệt kê các trường có thể ghi. Khi chèn một người tham dự mới, bạn phải đưa vào tất cả những người đó, ngoại trừ ATTENDEE_NAME.

Hằng số Nội dung mô tả
EVENT_ID Mã của sự kiện.
ATTENDEE_NAME Tên của người tham dự.
ATTENDEE_EMAIL Địa chỉ email của người tham dự.
ATTENDEE_RELATIONSHIP

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

ATTENDEE_TYPE

Loại người tham dự. Một trong các lựa chọn sau:

ATTENDEE_STATUS

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

Thêm người tham dự

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

Kotlin

val eventID: Long = 202
...
val values = ContentValues().apply {
    put(CalendarContract.Attendees.ATTENDEE_NAME, "Trevor")
    put(CalendarContract.Attendees.ATTENDEE_EMAIL, "trevor@example.com")
    put(
        CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
        CalendarContract.Attendees.RELATIONSHIP_ATTENDEE
    )
    put(CalendarContract.Attendees.ATTENDEE_TYPE, CalendarContract.Attendees.TYPE_OPTIONAL)
    put(
        CalendarContract.Attendees.ATTENDEE_STATUS,
        CalendarContract.Attendees.ATTENDEE_STATUS_INVITED
    )
    put(CalendarContract.Attendees.EVENT_ID, eventID)
}
val uri: Uri = contentResolver.insert(CalendarContract.Attendees.CONTENT_URI, values)

Java

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 lời nhắc

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

Bảng sau đây liệt kê các trường có thể ghi cho lời nhắc. Bạn phải thêm tất cả các thao tác này khi chèn lời nhắc mới. Lưu ý rằng các bộ chuyển đổi đồng bộ hoá sẽ chỉ định các loại lời nhắc mà chúng hỗ trợ trong bảng CalendarContract.Calendars. Hãy xem ALLOWED_REMINDERS để biết thông tin chi tiết.

Hằng số Nội dung mô tả
EVENT_ID Mã của sự kiện.
MINUTES Phút trước sự kiện mà lời nhắc sẽ kích hoạt.
METHOD

Phương thức báo thức, như đã đặt trên máy chủ. Một trong các lựa chọn sau:

Thêm lời nhắc

Ví dụ này thêm lời nhắc vào một sự kiện. Lời nhắc sẽ kích hoạt 15 phút trước sự kiện.

Kotlin

val eventID: Long = 221
...
val values = ContentValues().apply {
    put(CalendarContract.Reminders.MINUTES, 15)
    put(CalendarContract.Reminders.EVENT_ID, eventID)
    put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT)
}
val uri: Uri = contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, values)

Java

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 lưu giữ thời gian bắt đầu và kết thúc cho các lần xuất hiện của một sự kiện. Mỗi hàng trong bảng này đại diện cho một lần xuất hiện sự kiện. Bảng thực thể không thể ghi và chỉ cung cấp cách truy vấn các lần xuất hiện sự kiện.

Bảng sau đây liệt kê một số trường mà bạn có thể truy vấn cho một thực thể. Xin lưu ý rằng múi giờ được xác định bằng KEY_TIMEZONE_TYPEKEY_TIMEZONE_INSTANCES.

Hằng số Nội dung 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 Julian của thực thể, so với múi giờ của Lịch.
END_MINUTE Phút kết thúc của thực thể được đo từ nửa đêm theo múi giờ của Lịch.
EVENT_ID _ID của sự kiện cho thực thể này.
START_DAY Ngày bắt đầu Julian của phiên bản, tương ứng với múi giờ của Lịch.
START_MINUTE Phút bắt đầu của thực thể được đo từ nửa đêm, tương ứng với 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 khoảng thời gian cho truy vấn trong URI. Trong ví dụ này, CalendarContract.Instances có quyền truy cập vào trường TITLE thông qua việc triển khai giao diện CalendarContract.EventsColumns. Nói cách khác, TITLE được trả về thông qua một khung hiển thị cơ sở dữ liệu, không phải thông qua việc truy vấn bảng CalendarContract.Instances thô.

Kotlin

const val DEBUG_TAG: String = "MyActivity"
val INSTANCE_PROJECTION: Array<String> = arrayOf(
        CalendarContract.Instances.EVENT_ID, // 0
        CalendarContract.Instances.BEGIN, // 1
        CalendarContract.Instances.TITLE // 2
)

// The indices for the projection array above.
const val PROJECTION_ID_INDEX: Int = 0
const val PROJECTION_BEGIN_INDEX: Int = 1
const val PROJECTION_TITLE_INDEX: Int = 2

// Specify the date range you want to search for recurring
// event instances
val startMillis: Long = Calendar.getInstance().run {
    set(2011, 9, 23, 8, 0)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2011, 10, 24, 8, 0)
    timeInMillis
}

// The ID of the recurring event whose instances you are searching
// for in the Instances table
val selection: String = "${CalendarContract.Instances.EVENT_ID} = ?"
val selectionArgs: Array<String> = arrayOf("207")

// Construct the query with the desired date range.
val builder: Uri.Builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
ContentUris.appendId(builder, startMillis)
ContentUris.appendId(builder, endMillis)

// Submit the query
val cur: Cursor = contentResolver.query(
        builder.build(),
        INSTANCE_PROJECTION,
        selection,
        selectionArgs, null
)
while (cur.moveToNext()) {
    // Get the field values
    val eventID: Long = cur.getLong(PROJECTION_ID_INDEX)
    val beginVal: Long = cur.getLong(PROJECTION_BEGIN_INDEX)
    val title: String = cur.getString(PROJECTION_TITLE_INDEX)

    // Do something with the values.
    Log.i(DEBUG_TAG, "Event: $title")
    val calendar = Calendar.getInstance().apply {
        timeInMillis = beginVal
    }
    val formatter = SimpleDateFormat("MM/dd/yyyy")
    Log.i(DEBUG_TAG, "Date: ${formatter.format(calendar.time)}")
}

Java

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 của Lịch

Ứng dụng của bạn không cần quyền đọc và ghi dữ liệu lịch. Thay vào đó, ứng dụng này có thể sử dụng các ý định được ứng dụng Lịch của Android hỗ trợ để 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 Nhà cung cấp lịch hỗ trợ:

Hành động URI Nội dung mô tả Thông tin bổ sung

VIEW

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

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

VIEW

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

Bạn cũng có thể tham chiếu đến URI bằng Events.CONTENT_URI. Để biết ví dụ về cách sử dụng ý định này, hãy xem bài viết Sử dụng ý định để xem dữ liệu lịch.
Xem sự kiện do <event_id> chỉ định. 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 chiếu đến URI bằng Events.CONTENT_URI. Để biết ví dụ về cách sử dụng ý định này, hãy xem bài viết Sử dụng ý định để chỉnh sửa sự kiện.
Chỉnh sửa sự kiện do <event_id> chỉ định. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

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

Bảng sau đây liệt kê các ý định bổ sung được Nhà cung cấp lịch hỗ trợ:

Ý định bổ sung Nội dung 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 kể từ thời gian bắt đầu của hệ thống.
CalendarContract.EXTRA_EVENT_END_TIME Thời gian kết thúc sự kiện tính bằng mili giây kể từ thời gian bắt đầu của hệ thống.
CalendarContract.EXTRA_EVENT_ALL_DAY Giá trị boolean cho biết một sự kiện kéo dài cả ngày. Giá trị có thể là true hoặc false.
Events.EVENT_LOCATION Địa điểm diễn ra sự kiện.
Events.DESCRIPTION Nội dung mô tả sự kiện.
Intent.EXTRA_EMAIL Địa chỉ email của những người cần mời dưới dạng danh sách được phân tách bằng dấu phẩy.
Events.RRULE Quy tắc lặp lại cho sự kiện.
Events.ACCESS_LEVEL Sự kiện đó là riêng tư hay công khai.
Events.AVAILABILITY Nếu sự kiện này được tính là thời gian bận hoặc là thời gian rảnh thì bạn có thể lên lịch cho sự kiện này.

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

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

Việc sử dụng Ý định INSERT cho phép ứng dụng của bạn chuyển tác vụ chèn sự kiện cho chính Lịch. Với phương pháp này, ứng dụng của bạn thậm chí không cần đưa quyền WRITE_CALENDAR vào tệp kê khai.

Khi người dùng chạy một ứng dụng sử dụng phương pháp này, ứng dụng sẽ gửi họ đến Lịch để hoàn tất việc thêm sự kiện. Ý định INSERT sử dụng các trường bổ sung để điền trước thông tin chi tiết về sự kiện trong Lịch. Sau đó, người dùng có thể huỷ sự kiện, chỉnh sửa biểu mẫu nếu cần hoặc lưu sự kiện vào lịch của họ.

Dưới đây là đoạn mã lên lịch sự kiện vào ngày 19 tháng 1 năm 2012, diễn ra từ 7:30 sáng đến 8:30 sáng. Hãy lưu ý những điều sau về đoạn mã này:

  • Phương thức này chỉ định Events.CONTENT_URI làm URI.
  • Hàm này sử dụng các trường bổ sung CalendarContract.EXTRA_EVENT_BEGIN_TIMECalendarContract.EXTRA_EVENT_END_TIME để điền sẵn vào biểu mẫu thời gian diễn ra sự kiện. Giá trị của các thời gian này phải tính bằng mili giây UTC kể từ thời gian bắt đầu của hệ thống.
  • Dịch vụ này sử dụng trường bổ sung Intent.EXTRA_EMAIL để cung cấp danh sách khách mời được phân tách bằng dấu phẩy và được chỉ định theo địa chỉ email.

Kotlin

val startMillis: Long = Calendar.getInstance().run {
    set(2012, 0, 19, 7, 30)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2012, 0, 19, 8, 30)
    timeInMillis
}
val intent = Intent(Intent.ACTION_INSERT)
        .setData(CalendarContract.Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis)
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis)
        .putExtra(CalendarContract.Events.TITLE, "Yoga")
        .putExtra(CalendarContract.Events.DESCRIPTION, "Group class")
        .putExtra(CalendarContract.Events.EVENT_LOCATION, "The gym")
        .putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com")
startActivity(intent)

Java

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 sự kiện

Bạn có thể cập nhật trực tiếp một sự kiện, như mô tả trong phần Cập nhật sự kiện. Tuy nhiên, việc sử dụng Ý định EDIT cho phép một ứng dụng không có quyền chuyển chức năng chỉnh sửa sự kiện cho ứng dụng Lịch. Khi người dùng chỉnh sửa xong sự kiện trong Lịch, họ sẽ được quay lại ứng dụng ban đầu.

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

Kotlin

val eventID: Long = 208
val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val intent = Intent(Intent.ACTION_EDIT)
        .setData(uri)
        .putExtra(CalendarContract.Events.TITLE, "My New Title")
startActivity(intent)

Java

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 cung cấp 2 cách để sử dụng Ý định VIEW:

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

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

Kotlin

val startMillis: Long
...
val builder: Uri.Builder = CalendarContract.CONTENT_URI.buildUpon()
        .appendPath("time")
ContentUris.appendId(builder, startMillis)
val intent = Intent(Intent.ACTION_VIEW)
        .setData(builder.build())
startActivity(intent)

Java

// 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à ví dụ minh hoạ cách mở một sự kiện để xem:

Kotlin

val eventID: Long = 208
...
val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)

Java

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

Bộ điều hợp đồng bộ hoá

Chỉ có những điểm khác biệt nhỏ về cách ứng dụng và bộ điều hợp đồng bộ hoá truy cập vào Nhà cung cấp Lịch:

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

Dưới đây là một phương thức trợ giúp mà bạn có thể sử dụng để trả về một URI để sử dụng với bộ điều hợp đồng bộ hoá:

Kotlin

fun asSyncAdapter(uri: Uri, account: String, accountType: String): Uri {
    return uri.buildUpon()
            .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
            .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, account)
            .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, accountType).build()
}

Java

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