本课介绍了如何使用 Intent
插入新联系人或修改联系人的数据。Intent
会启动相应的“通讯录”应用(该应用运行适当的 Activity
),而不是直接访问联系人提供程序。对于本课中介绍的修改操作,如果您在 Intent
中发送扩展数据,这些数据会输入到启动的 Activity
的界面。
使用 Intent
插入或更新单个联系人是修改联系人提供程序的首选方法,原因如下:
- 您无需开发自己的界面和代码,节省了时间和精力。
- 避免了由于修改时未遵循联系人提供程序规则而导致的错误。
- 减少了您需要请求的权限数。您的应用无需权限即可写入联系人提供程序,因为它将修改操作委托给已具有该权限的“通讯录”应用。
使用 intent 插入新联系人
您一般希望允许用户在您的应用收到新数据时插入新联系人。例如,一个餐厅评价应用可允许用户在评价餐厅时将其添加为联系人。如需使用 intent 进行此操作,请使用尽可能多的数据创建 intent,然后将该 intent 发送到“通讯录”应用。
使用“通讯录”应用插入联系人,会将新的原始联系人插入到联系人提供商的 ContactsContract.RawContacts
表。如有必要,“通讯录”应用会在创建原始联系人时提示用户要使用的帐号类型和帐号。“通讯录”应用还会通知用户原始联系人是否已存在。如果联系人已存在,用户可以选择取消插入,在这种情况下,不会创建任何联系人。如需详细了解原始联系人,请参阅联系人提供程序 API 指南。
创建 intent
首先,使用 Intents.Insert.ACTION
操作创建新的 Intent
对象。将 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,但向 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
;由于调用 setType()
会覆盖 Intent
的当前数据值,因此您必须同时设置数据和 MIME 类型。
如需获取联系人的 Contacts.CONTENT_LOOKUP_URI
,请调用 Contacts.getLookupUri(id, lookupkey)
,将联系人的 Contacts._ID
以及 Contacts.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,并且用户修改并保存某位联系人,那么当用户点击“返回”后,会看到联系人列表屏幕。为了返回您的应用,用户必须点击“最近”并选择您的应用。
如需在 Android 4.0.3(API 版本 15)及更高版本中解决此问题,请将扩展数据键 finishActivityOnSaveCompleted
添加到 intent 中,并将其值设置为 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);