Sửa đổi người liên hệ bằng cách sử dụng ý định

Bài học này sẽ hướng dẫn bạn cách sử dụng Intent để chèn một mục liên hệ mới hoặc sửa đổi dữ liệu của một mục liên hệ. Thay vì truy cập trực tiếp vào Trình cung cấp danh bạ, Intent sẽ khởi động ứng dụng danh bạ và chạy Activity thích hợp. Đối với các thao tác sửa đổi được mô tả trong bài học này, nếu bạn gửi dữ liệu mở rộng trong Intent, thì dữ liệu đó sẽ được nhập vào giao diện người dùng của Activity đã bắt đầu.

Việc sử dụng Intent để chèn hoặc cập nhật một mục liên hệ là cách ưu tiên để sửa đổi Trình cung cấp danh bạ vì những lý do sau:

  • Công cụ này giúp bạn tiết kiệm thời gian và công sức phát triển giao diện người dùng và mã nguồn của riêng mình.
  • Nhờ đó, bạn có thể tránh gây ra lỗi do các nội dung sửa đổi không tuân thủ các quy tắc của Trình cung cấp danh bạ.
  • Thao tác này sẽ giảm số lượng quyền bạn cần yêu cầu. Ứng dụng của bạn không cần quyền ghi vào Trình cung cấp danh bạ vì ứng dụng này uỷ quyền sửa đổi ứng dụng danh bạ đã có quyền đó.

Chèn người liên hệ mới bằng ý định

Thường thì bạn muốn cho phép người dùng chèn một người liên hệ mới khi ứng dụng của bạn nhận được dữ liệu mới. Ví dụ: một ứng dụng đánh giá nhà hàng có thể cho phép người dùng thêm nhà hàng đó làm người liên hệ trong quá trình đánh giá. Để thực hiện việc này bằng cách sử dụng ý định, hãy tạo ý định bằng cách sử dụng nhiều dữ liệu nhất có thể, sau đó gửi ý định đó đến ứng dụng danh bạ.

Việc chèn một người liên hệ bằng ứng dụng danh bạ sẽ chèn một người liên hệ thô mới vào bảng ContactsContract.RawContacts của Trình cung cấp danh bạ. Nếu cần, ứng dụng danh bạ sẽ nhắc người dùng về loại tài khoản và tài khoản cần sử dụng khi tạo thông tin liên hệ thô. Ứng dụng danh bạ cũng sẽ thông báo cho người dùng nếu thông tin liên hệ thô đã tồn tại. Sau đó, người dùng có thể chọn huỷ quá trình chèn. Trong trường hợp đó, sẽ không có mục liên hệ nào được tạo. Để tìm hiểu thêm về danh bạ thô, hãy xem hướng dẫn về API Trình cung cấp danh bạ.

Tạo ý định

Để bắt đầu, hãy tạo một đối tượng Intent mới bằng hành động Intents.Insert.ACTION. Đặt loại MIME thành RawContacts.CONTENT_TYPE. Ví dụ:

Kotlin

...
// Creates a new Intent to insert a contact
val intent = Intent(ContactsContract.Intents.Insert.ACTION).apply {
    // Sets the MIME type to match the Contacts Provider
    type = ContactsContract.RawContacts.CONTENT_TYPE
}

Java

...
// Creates a new Intent to insert a contact
Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
// Sets the MIME type to match the Contacts Provider
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

Nếu đã có thông tin chi tiết của người liên hệ đó (chẳng hạn như số điện thoại hoặc địa chỉ email), thì bạn có thể chèn các thông tin đó vào ý định dưới dạng dữ liệu mở rộng. Đối với giá trị khoá, hãy sử dụng hằng số thích hợp trong Intents.Insert. Ứng dụng danh bạ hiển thị dữ liệu trên màn hình chèn, cho phép người dùng chỉnh sửa và bổ sung thêm.

Kotlin

private var emailAddress: EditText? = null
private var phoneNumber: EditText? = null
...
/* Assumes EditText fields in your UI contain an email address
 * and a phone number.
 *
 */
emailAddress = findViewById(R.id.email)
phoneNumber = findViewById(R.id.phone)
...
/*
 * Inserts new data into the Intent. This data is passed to the
 * contacts app's Insert screen
 */
intent.apply {
    // Inserts an email address
    putExtra(ContactsContract.Intents.Insert.EMAIL, emailAddress?.text)
    /*
     * In this example, sets the email type to be a work email.
     * You can set other email types as necessary.
     */
    putExtra(
            ContactsContract.Intents.Insert.EMAIL_TYPE,
            ContactsContract.CommonDataKinds.Email.TYPE_WORK
    )
    // Inserts a phone number
    putExtra(ContactsContract.Intents.Insert.PHONE, phoneNumber?.text)
    /*
     * In this example, sets the phone type to be a work phone.
     * You can set other phone types as necessary.
     */
    putExtra(
            ContactsContract.Intents.Insert.PHONE_TYPE,
            ContactsContract.CommonDataKinds.Phone.TYPE_WORK
    )
}

Java

private EditText emailAddress = null;
private EditText phoneNumber = null;
...
/* Assumes EditText fields in your UI contain an email address
 * and a phone number.
 *
 */
emailAddress = (EditText) findViewById(R.id.email);
phoneNumber = (EditText) findViewById(R.id.phone);
...
/*
 * Inserts new data into the Intent. This data is passed to the
 * contacts app's Insert screen
 */
// Inserts an email address
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, emailAddress.getText())
/*
 * In this example, sets the email type to be a work email.
 * You can set other email types as necessary.
 */
      .putExtra(ContactsContract.Intents.Insert.EMAIL_TYPE,
            ContactsContract.CommonDataKinds.Email.TYPE_WORK)
// Inserts a phone number
      .putExtra(ContactsContract.Intents.Insert.PHONE, phoneNumber.getText())
/*
 * In this example, sets the phone type to be a work phone.
 * You can set other phone types as necessary.
 */
      .putExtra(ContactsContract.Intents.Insert.PHONE_TYPE,
            ContactsContract.CommonDataKinds.Phone.TYPE_WORK);

Sau khi bạn tạo Intent, hãy gửi đối tượng đó bằng cách gọi startActivity().

Kotlin

    /* Sends the Intent
     */
    startActivity(intent)

Java

    /* Sends the Intent
     */
    startActivity(intent);

Cuộc gọi này sẽ mở ra một màn hình trong ứng dụng danh bạ để cho phép người dùng nhập một người liên hệ mới. Loại tài khoản và tên tài khoản cho người liên hệ đó sẽ được liệt kê ở đầu màn hình. Sau khi người dùng nhập dữ liệu và nhấp vào Xong, danh bạ của ứng dụng danh bạ sẽ xuất hiện. Người dùng quay lại ứng dụng của bạn bằng cách nhấp vào Back (Quay lại).

Chỉnh sửa một người liên hệ hiện có bằng cách sử dụng ý định

Việc chỉnh sửa một người liên hệ hiện có bằng Intent sẽ hữu ích nếu người dùng đã chọn một người liên hệ quan tâm. Ví dụ: một ứng dụng tìm những người liên hệ có địa chỉ bưu chính nhưng thiếu mã bưu chính có thể cho phép người dùng tra cứu mã rồi thêm vào người liên hệ đó.

Để chỉnh sửa một mục liên hệ hiện có bằng ý định, hãy sử dụng quy trình tương tự như chèn một mục liên hệ. Tạo một ý định theo mô tả trong phần Chèn một liên hệ mới bằng cách sử dụng ý định, nhưng thêm Contacts.CONTENT_LOOKUP_URI và loại MIME của liên hệ Contacts.CONTENT_ITEM_TYPE vào ý định. Nếu muốn chỉnh sửa thông tin liên hệ theo thông tin bạn đã có, bạn có thể đưa thông tin đó vào dữ liệu mở rộng của ý định. Lưu ý rằng một số cột tên không thể chỉnh sửa bằng ý định; những cột này được liệt kê trong phần tóm tắt của tài liệu tham khảo API cho lớp ContactsContract.Contacts trong tiêu đề "Cập nhật".

Cuối cùng, hãy gửi ý định. Để đáp lại, ứng dụng danh bạ sẽ hiển thị màn hình chỉnh sửa. Khi người dùng hoàn tất việc chỉnh sửa và lưu nội dung chỉnh sửa, ứng dụng danh bạ sẽ hiển thị một danh bạ. Khi người dùng nhấp vào Back (Quay lại), ứng dụng của bạn sẽ xuất hiện.

Tạo ý định

Để chỉnh sửa một người liên hệ, hãy gọi Intent(action) để tạo một ý định bằng thao tác ACTION_EDIT. Gọi setDataAndType() để đặt giá trị dữ liệu cho ý định thành Contacts.CONTENT_LOOKUP_URI của người liên hệ và loại MIME thành loại MIME Contacts.CONTENT_ITEM_TYPE; vì lệnh gọi đến setType() ghi đè giá trị dữ liệu hiện tại cho Intent, nên bạn phải thiết lập đồng thời cả dữ liệu và loại MIME.

Để nhận Contacts.CONTENT_LOOKUP_URI của một mục liên hệ, hãy gọi Contacts.getLookupUri(id, lookupkey) bằng các giá trị Contacts._IDContacts.LOOKUP_KEY của mục liên hệ đó làm đối số.

Lưu ý: Giá trị LOOKUP_KEY của một mục liên hệ là giá trị nhận dạng mà bạn nên dùng để truy xuất một mục liên hệ. Giá trị này không thay đổi, ngay cả khi trình cung cấp thay đổi mã hàng của người liên hệ để xử lý các hoạt động nội bộ.

Đoạn mã sau đây cho bạn biết cách tạo ý định:

Kotlin

    // The Cursor that contains the Contact row
    var mCursor: Cursor? = null
    // The index of the lookup key column in the cursor
    var lookupKeyIndex: Int = 0
    // The index of the contact's _ID value
    var idIndex: Int = 0
    // The lookup key from the Cursor
    var currentLookupKey: String? = null
    // The _ID value from the Cursor
    var currentId: Long = 0
    // A content URI pointing to the contact
    var selectedContactUri: Uri? = null
    ...
    /*
     * Once the user has selected a contact to edit,
     * this gets the contact's lookup key and _ID values from the
     * cursor and creates the necessary URI.
     */
    mCursor?.apply {
        // Gets the lookup key column index
        lookupKeyIndex = getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)
        // Gets the lookup key value
        currentLookupKey = getString(lookupKeyIndex)
        // Gets the _ID column index
        idIndex = getColumnIndex(ContactsContract.Contacts._ID)
        currentId = getLong(idIndex)
        selectedContactUri = ContactsContract.Contacts.getLookupUri(currentId, mCurrentLookupKey)
    }

    // Creates a new Intent to edit a contact
    val editIntent = Intent(Intent.ACTION_EDIT).apply {
        /*
         * Sets the contact URI to edit, and the data type that the
         * Intent must match
         */
        setDataAndType(selectedContactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE)
    }

Java

    // The Cursor that contains the Contact row
    public Cursor mCursor;
    // The index of the lookup key column in the cursor
    public int lookupKeyIndex;
    // The index of the contact's _ID value
    public int idIndex;
    // The lookup key from the Cursor
    public String currentLookupKey;
    // The _ID value from the Cursor
    public long currentId;
    // A content URI pointing to the contact
    Uri selectedContactUri;
    ...
    /*
     * Once the user has selected a contact to edit,
     * this gets the contact's lookup key and _ID values from the
     * cursor and creates the necessary URI.
     */
    // Gets the lookup key column index
    lookupKeyIndex = mCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);
    // Gets the lookup key value
    currentLookupKey = mCursor.getString(lookupKeyIndex);
    // Gets the _ID column index
    idIndex = mCursor.getColumnIndex(ContactsContract.Contacts._ID);
    currentId = mCursor.getLong(idIndex);
    selectedContactUri =
            Contacts.getLookupUri(currentId, mCurrentLookupKey);
    ...
    // Creates a new Intent to edit a contact
    Intent editIntent = new Intent(Intent.ACTION_EDIT);
    /*
     * Sets the contact URI to edit, and the data type that the
     * Intent must match
     */
    editIntent.setDataAndType(selectedContactUri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);

Thêm cờ điều hướng

Trong Android 4.0 (API phiên bản 14) trở lên, một vấn đề trong ứng dụng danh bạ sẽ gây ra lỗi điều hướng không chính xác. Khi ứng dụng của bạn gửi ý định chỉnh sửa đến ứng dụng danh bạ, đồng thời người dùng cũng chỉnh sửa và lưu một mục liên hệ, thì khi nhấp vào Back (Quay lại), họ sẽ thấy màn hình danh bạ. Để quay lại ứng dụng của bạn, họ phải nhấp vào Recents (Gần đây) rồi chọn ứng dụng của bạn.

Để khắc phục vấn đề này trong Android 4.0.3 (API phiên bản 15) trở lên, hãy thêm khoá dữ liệu mở rộng finishActivityOnSaveCompleted vào ý định, với giá trị true. Các phiên bản Android trước Android 4.0 chấp nhận khoá này nhưng khoá này không có tác dụng. Để đặt dữ liệu mở rộng, hãy làm như sau:

Kotlin

    // Sets the special extended data for navigation
    editIntent.putExtra("finishActivityOnSaveCompleted", true)

Java

    // Sets the special extended data for navigation
    editIntent.putExtra("finishActivityOnSaveCompleted", true);

Thêm dữ liệu mở rộng khác

Để thêm dữ liệu mở rộng khác vào Intent, hãy gọi putExtra() nếu muốn. Bạn có thể thêm dữ liệu mở rộng cho các trường liên hệ phổ biến bằng cách sử dụng các giá trị khoá được chỉ định trong Intents.Insert. Hãy nhớ rằng bạn không thể sửa đổi một số cột trong bảng ContactsContract.Contacts. Các cột này được liệt kê trong phần tóm tắt của tài liệu tham khảo API cho lớp ContactsContract.Contacts trong tiêu đề "Cập nhật".

Gửi ý định

Cuối cùng, hãy gửi ý định bạn đã tạo. Ví dụ:

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

Cho phép người dùng chọn chèn hoặc chỉnh sửa bằng cách sử dụng ý định

Bạn có thể cho phép người dùng chọn chèn người liên hệ hoặc chỉnh sửa người liên hệ hiện có bằng cách gửi Intent kèm theo thao tác ACTION_INSERT_OR_EDIT. Ví dụ: ứng dụng email khách có thể cho phép người dùng thêm địa chỉ email đến cho một người liên hệ mới hoặc thêm địa chỉ này làm địa chỉ bổ sung cho một người liên hệ hiện có. Đặt loại MIME cho ý định này thành Contacts.CONTENT_ITEM_TYPE, nhưng không đặt URI dữ liệu.

Khi bạn gửi ý định này, ứng dụng danh bạ sẽ hiển thị danh sách những người liên hệ. Người dùng có thể chèn một người liên hệ mới hoặc chọn một người liên hệ hiện có rồi chỉnh sửa. Mọi trường dữ liệu mở rộng mà bạn thêm vào ý định đều sẽ điền vào màn hình xuất hiện. Bạn có thể sử dụng bất kỳ giá trị khoá nào được chỉ định trong Intents.Insert. Đoạn mã sau đây cho biết cách tạo và gửi ý định:

Kotlin

    // Creates a new Intent to insert or edit a contact
    val intentInsertEdit = Intent(Intent.ACTION_INSERT_OR_EDIT).apply {
        // Sets the MIME type
        type = ContactsContract.Contacts.CONTENT_ITEM_TYPE
    }
    // Add code here to insert extended data, if desired

    // Sends the Intent with an request ID
    startActivity(intentInsertEdit)

Java

    // Creates a new Intent to insert or edit a contact
    Intent intentInsertEdit = new Intent(Intent.ACTION_INSERT_OR_EDIT);
    // Sets the MIME type
    intentInsertEdit.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
    // Add code here to insert extended data, if desired
    ...
    // Sends the Intent with an request ID
    startActivity(intentInsertEdit);