แก้ไขรายชื่อติดต่อโดยใช้ Intent

บทเรียนนี้จะแสดงวิธีใช้ Intent เพื่อแทรกรายชื่อติดต่อใหม่หรือแก้ไขข้อมูลของรายชื่อติดต่อ แทนที่จะเข้าถึง Contacts Provider โดยตรง Intent จะเริ่มแอปรายชื่อติดต่อซึ่งเรียกใช้ Activity ที่เหมาะสม สำหรับการดำเนินการแก้ไขที่อธิบายไว้ในบทเรียนนี้ หากคุณส่งข้อมูลเพิ่มเติมใน Intent ระบบจะป้อนข้อมูลดังกล่าวลงใน UI ของ Activity ที่เริ่มต้น

การใช้ Intent เพื่อแทรกหรืออัปเดตรายชื่อติดต่อรายการเดียวเป็นวิธีที่แนะนำในการแก้ไข Contacts Provider ด้วยเหตุผลต่อไปนี้

  • ซึ่งจะช่วยประหยัดเวลาและแรงงานในการพัฒนา UI และโค้ดของคุณเอง
  • ซึ่งจะช่วยหลีกเลี่ยงข้อผิดพลาดที่เกิดจากการแก้ไขที่ไม่เป็นไปตามกฎของ Contacts Provider
  • ซึ่งจะช่วยลดจำนวนสิทธิ์ที่คุณต้องขอ แอปของคุณไม่จำเป็นต้องมีสิทธิ์เขียนไปยัง Contacts Provider เนื่องจากแอปจะมอบสิทธิ์การแก้ไขให้กับแอปรายชื่อติดต่อซึ่งมีสิทธิ์ดังกล่าวอยู่แล้ว

แทรกรายชื่อติดต่อใหม่โดยใช้ Intent

คุณมักจะต้องการอนุญาตให้ผู้ใช้แทรกรายชื่อติดต่อใหม่เมื่อแอปได้รับข้อมูลใหม่ เช่น แอปรีวิวร้านอาหารอาจอนุญาตให้ผู้ใช้เพิ่มร้านอาหารเป็นรายชื่อติดต่อขณะที่กำลังรีวิวร้านอาหารนั้น หากต้องการดำเนินการนี้โดยใช้ Intent ให้สร้าง Intent โดยใช้ข้อมูลที่มีอยู่ให้มากที่สุด แล้วส่ง Intent ไปยังแอปรายชื่อติดต่อ

การแทรกรายชื่อติดต่อโดยใช้แอปรายชื่อติดต่อจะแทรกรายชื่อติดต่อดิบใหม่ลงในตาราง ContactsContract.RawContacts ของ Contacts Provider หากจำเป็น แอปรายชื่อติดต่อจะแจ้งให้ผู้ใช้ระบุประเภทบัญชีและบัญชีที่จะใช้เมื่อสร้างข้อมูลติดต่อดิบ แอปรายชื่อติดต่อจะแจ้งเตือนผู้ใช้ด้วยหากมีข้อมูลติดต่อดิบอยู่แล้ว จากนั้นผู้ใช้จะมีตัวเลือกในการยกเลิกการแทรก ซึ่งในกรณีนี้จะไม่มีการสร้างรายชื่อติดต่อ ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลติดต่อดิบได้ที่คู่มือ API ของ Contacts Provider

สร้าง Intent

ในการเริ่มต้น ให้สร้างออบเจ็กต์ Intent ใหม่ด้วยการดำเนินการ Intents.Insert.ACTION ตั้งค่าประเภท MIME เป็น RawContacts.CONTENT_TYPE เช่น

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

หากคุณมีรายละเอียดของรายชื่อติดต่ออยู่แล้ว เช่น หมายเลขโทรศัพท์หรืออีเมล คุณสามารถแทรกรายละเอียดเหล่านั้นลงใน Intent เป็นข้อมูลเพิ่มเติมได้ สำหรับค่าคีย์ ให้ใช้ค่าคงที่ที่เหมาะสมจาก Intents.Insert แอปรายชื่อติดต่อจะแสดงข้อมูลในหน้าจอแทรก ซึ่งช่วยให้ผู้ใช้แก้ไขและเพิ่มข้อมูลเพิ่มเติมได้

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

เมื่อสร้าง Intent แล้ว ให้ส่งโดยเรียกใช้ startActivity()

Kotlin

    /* Sends the Intent
     */
    startActivity(intent)

Java

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

การเรียกนี้จะเปิดหน้าจอในแอปรายชื่อติดต่อที่อนุญาตให้ผู้ใช้ป้อนรายชื่อติดต่อใหม่ ประเภทบัญชีและชื่อบัญชีของรายชื่อติดต่อจะแสดงอยู่ที่ด้านบนของหน้าจอ เมื่อผู้ใช้ป้อนข้อมูลและคลิกเสร็จสิ้น ข้อมูลรายชื่อติดต่อของแอปรายชื่อติดต่อจะปรากฏขึ้น ผู้ใช้กลับไปที่แอปโดยคลิกกลับ

แก้ไขรายชื่อติดต่อที่มีอยู่โดยใช้ Intent

การแก้ไขรายชื่อติดต่อที่มีอยู่โดยใช้ Intent จะมีประโยชน์หากผู้ใช้เลือกรายชื่อติดต่อที่สนใจไว้แล้ว ตัวอย่างเช่น แอปที่ค้นหารายชื่อติดต่อที่มีที่อยู่ทางไปรษณีย์แต่ไม่มีรหัสไปรษณีย์อาจให้ตัวเลือกแก่ผู้ใช้ในการค้นหารหัสแล้วเพิ่มลงในรายชื่อติดต่อ

หากต้องการแก้ไขรายชื่อติดต่อที่มีอยู่โดยใช้ Intent ให้ใช้ขั้นตอนที่คล้ายกับการแทรกรายชื่อติดต่อ สร้าง Intent ตามที่อธิบายไว้ในส่วนแทรกรายชื่อติดต่อใหม่โดยใช้ Intent แต่เพิ่ม Contacts.CONTENT_LOOKUP_URI ของรายชื่อติดต่อและประเภท MIME Contacts.CONTENT_ITEM_TYPE ลงใน Intent หากต้องการแก้ไขรายชื่อติดต่อด้วยรายละเอียดที่คุณมีอยู่แล้ว คุณสามารถใส่รายละเอียดเหล่านั้นในข้อมูลเพิ่มเติมของ Intent โปรดทราบว่าคอลัมน์ชื่อบางคอลัมน์ไม่สามารถแก้ไขได้โดยใช้ Intent โดยคอลัมน์เหล่านี้จะแสดงอยู่ในส่วนสรุปของเอกสารอ้างอิง API สำหรับคลาส ContactsContract.Contacts ภายใต้หัวข้อ "อัปเดต"

สุดท้าย ให้ส่ง Intent แอปรายชื่อติดต่อจะแสดงหน้าจอแก้ไขเพื่อตอบสนองต่อคำสั่ง เมื่อผู้ใช้แก้ไขเสร็จและบันทึกการแก้ไขแล้ว แอปรายชื่อติดต่อจะแสดงข้อมูลรายชื่อติดต่อ เมื่อผู้ใช้คลิกกลับ แอปของคุณจะแสดงขึ้น

สร้าง Intent

หากต้องการแก้ไขรายชื่อติดต่อ ให้เรียก Intent(action) เพื่อสร้าง Intent ด้วยการดำเนินการ ACTION_EDIT เรียกใช้ setDataAndType() เพื่อตั้งค่าข้อมูลสำหรับ Intent เป็น Contacts.CONTENT_LOOKUP_URI ของรายชื่อติดต่อ และตั้งค่าประเภท MIME เป็นประเภท MIME Contacts.CONTENT_ITEM_TYPE เนื่องจากการเรียกใช้ setType() จะเขียนทับค่าข้อมูลปัจจุบันสำหรับ Intent คุณจึงต้องตั้งค่าข้อมูลและประเภท MIME พร้อมกัน

หากต้องการรับ Contacts.CONTENT_LOOKUP_URI ของรายชื่อติดต่อ ให้เรียกใช้ Contacts.getLookupUri(id, lookupkey) โดยมีค่า Contacts._ID และ Contacts.LOOKUP_KEY ของรายชื่อติดต่อเป็นอาร์กิวเมนต์

หมายเหตุ: ค่า LOOKUP_KEY ของรายชื่อติดต่อคือตัวระบุที่คุณควรใช้เพื่อดึงข้อมูลรายชื่อติดต่อ ซึ่งจะยังคงเหมือนเดิมแม้ว่าผู้ให้บริการจะเปลี่ยนรหัสแถวของผู้ติดต่อเพื่อจัดการการดำเนินการภายในก็ตาม

ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้าง Intent

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

เพิ่มแฟล็กการนําทาง

ใน Android 4.0 (API เวอร์ชัน 14) ขึ้นไป ปัญหาในแอปรายชื่อติดต่อทำให้การนำทางไม่ถูกต้อง เมื่อแอปส่ง Intent การแก้ไขไปยังแอปรายชื่อติดต่อ และผู้ใช้แก้ไขและบันทึกรายชื่อติดต่อ เมื่อคลิกกลับ ผู้ใช้จะเห็นหน้าจอข้อมูลรายชื่อติดต่อ หากต้องการกลับไปที่แอปของคุณ ผู้ใช้จะต้องคลิกล่าสุด แล้วเลือกแอปของคุณ

หากต้องการแก้ปัญหานี้ใน Android 4.0.3 (API เวอร์ชัน 15) ขึ้นไป ให้เพิ่มคีย์ข้อมูลเพิ่มเติม finishActivityOnSaveCompleted ลงใน Intent โดยมีค่าเป็น true Android เวอร์ชันก่อน Android 4.0 จะยอมรับคีย์นี้ แต่จะไม่มีผลใดๆ หากต้องการตั้งค่าข้อมูลเพิ่มเติม ให้ทำดังนี้

Kotlin

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

Java

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

เพิ่มข้อมูลอื่นๆ ที่ขยาย

หากต้องการเพิ่มข้อมูลเพิ่มเติมที่ขยายไปยัง Intent ให้เรียกใช้ putExtra() ตามต้องการ คุณสามารถเพิ่มข้อมูลเพิ่มเติมสำหรับช่องรายชื่อติดต่อทั่วไปได้โดยใช้ค่าคีย์ที่ระบุใน Intents.Insert โปรดทราบว่าคอลัมน์บางคอลัมน์ในตาราง ContactsContract.Contacts จะแก้ไขไม่ได้ คอลัมน์เหล่านี้จะแสดงอยู่ในส่วนสรุปของเอกสารอ้างอิง API สำหรับคลาส ContactsContract.Contacts ภายใต้หัวข้อ "อัปเดต"

ส่ง Intent

สุดท้าย ให้ส่ง Intent ที่คุณสร้างขึ้น เช่น

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

อนุญาตให้ผู้ใช้เลือกแทรกหรือแก้ไขโดยใช้ Intent

คุณสามารถอนุญาตให้ผู้ใช้เลือกว่าจะแทรกรายชื่อติดต่อหรือแก้ไขรายชื่อติดต่อที่มีอยู่โดยส่ง Intent พร้อมการดำเนินการ ACTION_INSERT_OR_EDIT เช่น แอปโปรแกรมรับส่งอีเมลอาจอนุญาตให้ผู้ใช้เพิ่มอีเมลขาเข้าไปยังรายชื่อติดต่อใหม่ หรือเพิ่มเป็นอีเมลเพิ่มเติมสำหรับรายชื่อติดต่อที่มีอยู่ ตั้งค่าประเภท MIME สำหรับ Intent นี้เป็น Contacts.CONTENT_ITEM_TYPE แต่อย่าตั้งค่า URI ของข้อมูล

เมื่อคุณส่ง Intent นี้ แอปรายชื่อติดต่อจะแสดงรายการรายชื่อติดต่อ ผู้ใช้สามารถแทรกรายชื่อติดต่อใหม่หรือเลือกรายชื่อติดต่อที่มีอยู่แล้วแก้ไขได้ ฟิลด์ข้อมูลเพิ่มเติมที่คุณเพิ่มลงใน Intent จะป้อนข้อมูลในหน้าจอที่ปรากฏขึ้น คุณสามารถใช้ค่าคีย์ใดก็ได้ที่ระบุไว้ใน Intents.Insert ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างและส่ง Intent

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