Tổng quan về trình cung cấp lịch

Nhà cung cấp lịch là kho lưu trữ cho 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 API Nhà cung cấp lịch. Các quy tắc sẽ khác nhau 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 API Trình cung cấp lịch dưới dạng một ứng dụng. Để thảo luận về sự khác biệt của bộ điều hợp đồng bộ hoá, vui lòng xem nội dung 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, Trình cung cấp lịch cung cấp một tập hợp các ý định, như mô tả trong Ý định lịch. Những ý đị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 rồi 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 cũng như 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 được. Các trình cung cấp nội dung do nền tảng Android (bao gồm cả Trình cung cấp Lịch) cung cấp thường hiển thị dữ liệu ở dạng tập hợp các 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 API Nhà cung cấp Lịch, các ứng dụng và bộ điều hợp đồng bộ hoá có thể có quyền đọc/ghi vào các bảng cơ sở dữ liệu chứa dữ liệu lịch của người dùng.

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

Hình 1 cho thấy mô hình dữ liệu của Nhà cung cấp lịch dưới dạng đồ hoạ. Bảng này cho thấy các bảng chính và các trường liên kết các bả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 lịch và thông tin liên quan đến 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) Mô tả

CalendarContract.Calendars

Bảng này chứa thông tin cụ thể về 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, chẳng hạn như 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 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à các 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 chứa thời gian bắt đầu và kết thúc của 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, có một mối liên kết 1:1 giữa các thực thể với sự kiện. Đối với các sự kiện định kỳ, nhiều hàng sẽ tự động được tạo 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 sự kiện. Mã này chỉ định loại khách và phản hồi của khách về việc tham dự 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 duy nhất 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 nhất định thiết lập. Lời nhắc được chỉ định bằng phút trước khi diễn ra sự kiện và có một phương thức xác định cách người dùng sẽ được thông báo.

API 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 mang lại 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. 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 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 bạn không xây dựng một ứng dụng lịch hoặc trình chuyển đổi đồng bộ hoá đầy đủ, thì bạn không cần phải 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 các thao tác đọc và ghi cho ứng dụng đó. Khi bạn sử dụng ý định, ứng dụng sẽ đưa người dùng đến ứng dụng Lịch để thực hiện thao tác mong muốn trong một biểu mẫu được điền sẵn. Sau khi hoàn tất, các giá trị này 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 sẽ cung cấp cho người dùng một giao diện người dùng nhất quán và mạnh mẽ. Đây là phương pháp đề xuất. Để biết thêm thông tin, hãy xem bài viết Ý định lịch.
  • Bộ điều hợp đồng bộ hoá. Bộ chuyển đổi đồ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 bộ chuyển đổi đồng bộ hoá để sử dụng. Nhà cung cấp và ứng dụng không được sửa đổi các giá trị này. Trên thực tế, các ứng dụng này không xuất hiện trừ khi được truy cập dưới dạng trình chuyển đổi đồng bộ hoá. Để biết thêm thông tin về bộ điều hợp đồng bộ hoá, hãy xem phần 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. Tệp 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 của từng lịch. Cả ứng dụng và trình chuyển đổi đồng bộ hoá đều có thể ghi vào 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 về CalendarContract.Calendars.

Hằng số Mô tả
NAME Tên lịch.
CALENDAR_DISPLAY_NAME Tên của lịch này hiển thị cho người dùng.
VISIBLE Một boolean cho biết liệu lịch có được chọn để hiển thị hay không. Giá trị 0 cho biết rằng 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 rằng 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 Giá trị boolean cho biết liệu bạn có nên đồng bộ hoá lịch và lưu trữ các sự kiện trên thiết bị hay không. Giá trị 0 có nghĩa là không đồng bộ hoá lịch này hoặc lưu trữ sự kiện của lịch trên thiết bị. Giá trị 1 cho biết các 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 một Calendars.ACCOUNT_NAME, bạn cũng phải đưa Calendars.ACCOUNT_TYPE vào lựa chọn. Đó là do 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 có tên là ACCOUNT_TYPE_LOCAL dành cho các lịch không liên kết với tài khoản thiết bị. Tài khoản ACCOUNT_TYPE_LOCAL chưa được đồng bộ hoá.

Truy vấn lịch

Dưới đây là ví dụ cho thấy cách tải 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 được hiển thị trong luồng giao diện người dùng ("luồng chính"). Trong thực tế, bạn nên thực hiện việc này trong một luồng không đồng bộ thay vì trên luồng chính. Để thảo luận thêm, hãy xem phần 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 chỉ định tiêu chí cho truy vấn. Trong ví dụ này, truy vấn đang tìm kiếm các 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ả lịch mà người dùng đã xem, chứ không chỉ những 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 phần 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ả. Hàm này sử dụng các hằng số được thiết lập ở đầ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 thêm vào Uri (withAppendedId()) hoặc dưới dạng mục lựa chọn đầu tiên. Mục 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 một 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ộ chuyển đổi đồng bộ hoá, vì vậy, bạn chỉ nên chèn lịch mới dưới dạng bộ chuyển đổi đồng bộ hoá. Trong hầu hết trường hợp, các ứng dụng chỉ có thể thực hiện những thay đổi bề ngoài đố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 cục bộ, ứ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à 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 tài khoản thiết bị. Loại lịch này không được đồng bộ hoá với máy chủ. Để thảo luận về bộ điều hợp đồng bộ hoá, vui lòng xem nội dung 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 về từng sự kiện. Để thêm, cập nhật hoặc xoá sự kiện, ứng dụng phải bao gồm quyền WRITE_CALENDAR trong tệp kê khai.

Cả ứng dụng và bộ chuyển đổi đồng bộ hoá đều có thể ghi vào 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 về CalendarContract.Events.

Hằng số Mô tả
CALENDAR_ID _ID của lịch mà sự kiện thuộc về.
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 Địa điểm 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 sự kiện kết thúc tính theo 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ờ của 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ị "PT1H" cho biết sự kiện sẽ kéo dài một 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 trong cả ngày, theo múi giờ địa phương. Giá trị 0 cho biết đó là một sự kiện thông thường có thể bắt đầu và kết thúc vào bất kỳ thời điểm 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ể tìm thêm ví dụ tại đây.
RDATE Ngày lặp lại của sự kiện. Bạn thường sử dụng RDATE cùng 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 thông số kỹ thuật 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 lại.
GUESTS_CAN_MODIFY Liệu khách có thể sửa đổi sự kiện hay không.
GUESTS_CAN_INVITE_OTHERS Khách có thể mời khách khác hay không.
GUESTS_CAN_SEE_GUESTS Liệu khách 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 phần Sử dụng ý định để chèn 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 thực hiện.

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

  • Bạn phải thêm CALENDAR_IDDTSTART.
  • Bạn phải thêm 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 đang 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 đó, hệ thống sẽ cung cấp múi giờ mặc định.
  • Đối với các sự kiện không định kỳ, bạn phải thêm DTEND.
  • Đối với các sự kiện định kỳ, bạn phải thêm DURATION 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 đang chèn một sự kiện thông qua Ý định INSERT, được mô tả trong phần Sử dụng ý định để chèn một sự kiện. Trong trường hợp đó, bạn có thể sử dụng RRULE kết hợp với DTSTARTDTEND, và ứng dụng Lịch sẽ tự động chuyển đổi 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ộ để di chuyển thao tác vào luồng ở chế độ 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ự 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 phần Sử dụng ý định để chỉnh sửa sự kiện. Tuy nhiên, nếu cần, bạn có thể trực tiếp chỉnh sửa 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ã nhận dạng được 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ày phải 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. Sau đây là ví dụ về cách cập nhật một sự kiện. Phương thức 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 bằng _ID dưới dạng mã nhận dạng được thêm vào URI hoặc bằng cách sử dụng lựa chọn tiêu chuẩn. Nếu sử dụng mã nhận dạng được thêm vào, bạn cũng không thể chọn. Có hai phiên bản xoá: dưới dạng ứng dụng và dưới dạng trình chuyển đổi đồng bộ hoá. Thao tác xoá ứng dụng sẽ đặt cột đã xoá thành 1. Cờ này cho bộ chuyển đổi đồng bộ hoá biết rằng hàng đã bị xoá và việc xoá này sẽ được truyền đến máy chủ. Thao tác xoá trình 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ề cách ứng dụng xoá một sự kiện thông qua _ID:

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 khách mời hoặc người tham dự sự kiện. Việc gọi query() sẽ trả về danh sách người tham dự cho sự kiện có 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 thêm tất cả người tham dự ngoại trừ ATTENDEE_NAME.

Hằng số 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 những trường hợp sau:

ATTENDEE_TYPE

Loại người tham dự. Một trong những trường hợp sau:

ATTENDEE_STATUS

Trạng thái tham dự của người tham dự. Một trong những trường hợp 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 bạn bắt buộc phải có EVENT_ID:

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 cho một sự kiện. Việc gọi query() sẽ trả về một 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 của lời nhắc. Bạn phải đưa tất cả các thông tin này vào khi chèn lời nhắc mới. Xin lưu ý rằng trình chuyển đổi đồng bộ hoá 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ố Mô tả
EVENT_ID Mã của sự kiện.
MINUTES Số phút trước khi sự kiện diễn ra mà lời nhắc sẽ kích hoạt.
METHOD

Phương thức báo động, được đặt trên máy chủ. Một trong những trường hợp 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 khi sự kiện diễn ra.

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 đối tượng

Bảng CalendarContract.Instances chứa thời gian bắt đầu và kết thúc của các 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. Bạn không thể ghi vào bảng thực thể và bảng này 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 trường hợp cụ thể. Xin lưu ý rằng múi giờ do KEY_TIMEZONE_TYPEKEY_TIMEZONE_INSTANCES xác định.

Hằng số Mô tả
BEGIN Thời gian bắt đầu của thực thể, tính bằng mili giây theo giờ UTC.
END Thời gian kết thúc của thực thể, tính bằng mili giây theo giờ UTC.
END_DAY Ngày kết thúc của trường hợp Julian tương ứng với múi giờ của Lịch.
END_MINUTE Phút kết thúc của thực thể được tính 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 theo lịch Julian của thực thể, tương ứng với múi giờ của Lịch.
START_MINUTE Số phút bắt đầu của thực thể được tính 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 Instances (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 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 chế độ xem cơ sở dữ liệu, chứ không phải thông qua 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 về 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 có thể sử dụng các ý định được ứng dụng Lịch của Android hỗ trợ để chuyển 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ợ:

Thao tác URI 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 phần 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 có.

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 phần 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 phần 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 phần Sử dụng ý định để chèn một sự kiện.
Tạo một sự kiện. Mọi tính năng bổ sung được liệt kê trong bảng dưới đây.

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

Ý định bổ sung Mô tả
Events.TITLE Tên 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 diễn ra 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 bạn muố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 có ở chế độ riêng tư hay công khai.
Events.AVAILABILITY Liệu sự kiện này có được tính là thời gian bận hay là thời gian rảnh có thể lên lịch không.

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 phải đư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 sẵn thông tin chi tiết về sự kiện trong Lịch vào biểu mẫu. 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.

Dưới đây là một đoạn mã lên lịch một sự kiện vào ngày 19 tháng 1 năm 2012, chạy từ 7:30 đến 8:30. 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.
  • Phương thức này sử dụng các trường bổ sung CalendarContract.EXTRA_EVENT_BEGIN_TIMECalendarContract.EXTRA_EVENT_END_TIME để điền sẵn thời gian của sự kiện vào biểu mẫu. Các giá trị cho những thời điểm này phải tính bằng mili giây theo giờ UTC kể từ thời gian bắt đầu.
  • Phương thức 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, đượ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 ứng dụng không có quyền chuyển quyền 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 đưa trở lại ứng dụng ban đầu.

Dưới đây là ví dụ về một ý định đặt tiêu đề mới cho một sự kiện cụ thể 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

Nhà cung cấp lịch cung cấp hai cách sử dụng Ý định VIEW:

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

Sau đây là ví dụ về cách mở Lịch đến 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);

Dưới đây là ví dụ cho thấy 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ó một số khác biệt nhỏ về cách ứng dụng và trình chuyển đổi đồng bộ hoá truy cập vào Nhà cung cấp lịch:

  • Bộ chuyển đổi đồng bộ hoá cần chỉ định rằng đó là bộ chuyển đổi đồng bộ hoá bằng cách đặt CALLER_IS_SYNCADAPTER thành true.
  • Bộ chuyển đổi đồng bộ hoá cần cung cấp ACCOUNT_NAMEACCOUNT_TYPE dưới dạng tham số truy vấn trong URI.
  • Bộ chuyển đổi đồ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 số đặc điểm của lịch, chẳng hạn như tên, tên hiển thị, chế độ hiển thị và liệu lịch có được đồng bộ hoá hay không. So sánh thì trình chuyển đổi đồng bộ hoá không chỉ có thể truy cập vào các cột đó mà còn 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à nó đã chỉ định.

Dưới đây là phương thức trợ giúp bạn có thể sử dụng để trả về URI nhằm 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();
 }