使用 intent 修改联系人

本课介绍了如何使用 Intent 插入新联系人或修改联系人的数据。无需直接访问联系人提供程序, Intent 会启动“通讯录”应用,该应用会运行相应的 Activity。对于本课中介绍的修改操作 如果您在 Intent 中发送扩展数据,这些数据会输入到 Activity已开始。

使用 Intent 插入或更新单个联系人是修改联系人提供程序的首选方法,原因如下:

  • 您无需开发自己的界面和代码,节省了时间和精力。
  • 避免了因修改未遵循 联系人提供程序的规则。
  • 这可以减少您需要请求的权限数量。您的应用无需权限即可写入联系人提供程序,因为它将修改操作委托给已具有该权限的“通讯录”应用。

使用 intent 插入新联系人

您一般希望允许用户在您的应用收到新数据时插入新联系人。例如,一个餐厅评价应用可允许用户在评价餐厅时将其添加为联系人。如需使用 intent 执行此操作,请使用尽可能多的数据创建 intent 然后将 intent 发送到“通讯录”应用。

使用“通讯录”应用插入联系人时,会在通讯录中插入一个新的原始联系人 提供方的 ContactsContract.RawContacts 表。如有必要,“通讯录”应用会在创建原始联系人时提示用户要使用的账号类型和账号。“通讯录”应用还会通知用户原始联系人是否已存在。然后,用户可以 取消插入的选项,在这种情况下不会创建任何联系人。学习内容 有关原始联系人的更多信息,请参阅 联系人提供程序 API 指南。

创建 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 进行修改;这些列在“更新”标题下针对类 ContactsContract.Contacts 的 API 参考的摘要部分中列出。

最后,发送该 intent。作为响应,“通讯录”应用会显示修改屏幕。当用户 完成修改并保存修改后,“通讯录”应用会显示联系人列表。用户点击“返回”后,会看到您的应用。

创建 intent

如需修改联系人,请调用 Intent(action) 以使用 ACTION_EDIT 操作创建 intent。致电 setDataAndType(),用于设置 intent 传递给联系人的 Contacts.CONTENT_LOOKUP_URI,并将 MIME 类型设置为 Contacts.CONTENT_ITEM_TYPE MIME 类型;因为对 setType() 会覆盖 Intent,必须同时设置数据和 MIME 类型。

要获取联系人的 Contacts.CONTENT_LOOKUP_URI,请调用 Contacts.getLookupUri(id, lookupkey) 替换为联系人的 Contacts._IDContacts.LOOKUP_KEY 值: 参数。

注意:联系人的 LOOKUP_KEY 值是您用于检索联系人的标识符。它始终保持不变 即使提供程序更改了联系人的行 ID 来处理内部操作,也是如此。

以下代码段展示了如何创建 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,并且用户修改并保存某位联系人,那么当用户点击“返回”后,会看到联系人列表屏幕。要返回 用户必须点击“Recents”并选择您的应用。

要在 Android 4.0.3(API 版本 15)及更高版本中解决此问题,请将扩展 数据键 finishActivityOnSaveCompleted,其值为 true。 Android 4.0 之前的 Android 版本接受此键,但没有任何作用。如需设置扩展数据,请执行以下操作:

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”表中的列不能修改。 这些列在“更新”标题下针对类 ContactsContract.Contacts 的 API 参考的摘要部分中列出。

发送 intent

最后,发送您构建的 intent。例如:

Kotlin

    // Sends the Intent
    startActivity(editIntent)

Java

    // Sends the Intent
    startActivity(editIntent);

让用户选择使用 intent 插入或修改

您可以允许用户选择是插入联系人还是修改现有联系人,只需发送 包含该操作的 Intent ACTION_INSERT_OR_EDIT。例如,电子邮件客户端应用可以允许用户将收到的电子邮件地址添加到新联系人,或将其添加为已有联系人的其他地址。将此 intent 的 MIME 类型设置为 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);