本課程說明如何使用 Intent 插入新聯絡人或修改聯絡人資料。Intent 不會直接存取聯絡人供應程式,而是啟動「聯絡人」應用程式,由後者執行適當的 Activity。對於本課程所述的修改動作,如果您在 Intent 中傳送擴充資料,系統會將資料輸入到已啟動的 Activity UI 中。
使用 Intent 插入或更新單一聯絡人,是修改聯絡人供應程式的首選方式,原因如下:
- 這樣一來,您就不必花費時間和心力自行開發 UI 和程式碼。
- 這可避免因修改不符合聯絡人供應程式規則而導致錯誤。
- 這可減少您需要要求的權限數量。應用程式不需要寫入聯絡人供應程式的權限,因為應用程式會將修改作業委派給已具備該權限的「聯絡人」應用程式。
使用意圖插入新聯絡人
當應用程式收到新資料時,您通常會希望允許使用者插入新聯絡人。舉例來說,餐廳評論應用程式可讓使用者在評論餐廳時,將餐廳新增為聯絡人。如要使用意圖執行這項操作,請使用盡可能多的可用資料建立意圖,然後將意圖傳送至「聯絡人」應用程式。
使用「聯絡人」應用程式插入聯絡人,會將新的「原始」聯絡人插入聯絡人供應程式的 ContactsContract.RawContacts 資料表。如有必要,聯絡人應用程式會提示使用者在建立原始聯絡人時,提供要使用的帳戶類型和帳戶。如果原始聯絡人已存在,「聯絡人」應用程式也會通知使用者。使用者可以選擇取消插入,這樣就不會建立聯絡人。如要進一步瞭解原始聯絡人,請參閱聯絡人供應程式 API 指南。
建立意圖
首先,請使用 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);
如果您已有聯絡人的詳細資料 (例如電話號碼或電子郵件地址),可以將這些資料做為擴充資料插入意圖。如要設定按鍵值,請使用 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);
這項呼叫會在「聯絡人」應用程式中開啟畫面,讓使用者輸入新聯絡人。畫面頂端會列出聯絡人的帳戶類型和帳戶名稱。使用者輸入資料並點選「Done」後,系統會顯示「聯絡人」應用程式的聯絡人清單。使用者點選「Back」即可返回應用程式。
使用意圖編輯現有聯絡人
如果使用者已選擇感興趣的聯絡人,使用 Intent 編輯現有聯絡人會很有幫助。舉例來說,如果應用程式找到有郵寄地址但缺少郵遞區號的聯絡人,可以讓使用者選擇查詢郵遞區號,然後將其新增至聯絡人。
如要使用意圖編輯現有聯絡人,請採用與插入聯絡人相似的程序。按照「使用意圖插入新聯絡人」一節所述建立意圖,但將聯絡人的 Contacts.CONTENT_LOOKUP_URI 和 MIME 類型 Contacts.CONTENT_ITEM_TYPE 新增至意圖。如要使用現有詳細資料編輯聯絡人,可以將這些資料放入意圖的擴充資料。請注意,部分名稱欄無法使用意圖編輯;這些欄會列在 ContactsContract.Contacts 類別 API 參考資料的摘要部分,標題為「Update」。
最後,傳送意圖。「聯絡人」應用程式會顯示編輯畫面。使用者完成編輯並儲存後,「聯絡人」應用程式會顯示聯絡人清單。使用者點選「Back」後,系統會顯示應用程式。
建立意圖
如要編輯聯絡人,請呼叫 Intent(action),使用 ACTION_EDIT 動作建立意圖。呼叫 setDataAndType(),將意圖的資料值設為聯絡人的 Contacts.CONTENT_LOOKUP_URI,並將 MIME 類型設為 Contacts.CONTENT_ITEM_TYPE MIME 類型;由於呼叫 setType() 會覆寫 Intent 的目前資料值,因此您必須同時設定資料和 MIME 類型。
如要取得聯絡人的 Contacts.CONTENT_LOOKUP_URI,請呼叫 Contacts.getLookupUri(id, lookupkey),並以聯絡人的 Contacts._ID 和 Contacts.LOOKUP_KEY 值做為引數。
注意:聯絡人的 LOOKUP_KEY 值是您擷取聯絡人時應使用的 ID。即使供應商變更聯絡人的資料列 ID 以處理內部作業,該 ID 仍會保持不變。
下列程式碼片段說明如何建立意圖:
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) 以上版本中,「聯絡人」應用程式的問題會導致導覽錯誤。當應用程式將編輯意圖傳送至「聯絡人」應用程式,且使用者編輯並儲存聯絡人後,點選「返回」就會看到聯絡人清單畫面。如要返回應用程式,使用者必須按一下「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 參考資料的摘要部分,標題為「Update」。
傳送意圖
最後,傳送您建構的意圖。例如:
Kotlin
// Sends the Intent startActivity(editIntent)
Java
// Sends the Intent startActivity(editIntent);
讓使用者選擇使用意圖插入或編輯
您可以傳送含有 ACTION_INSERT_OR_EDIT 動作的 Intent,讓使用者選擇要插入聯絡人或編輯現有聯絡人。舉例來說,電子郵件用戶端應用程式可讓使用者將收到的電子郵件地址新增至新聯絡人,或新增為現有聯絡人的其他地址。將這個意圖的 MIME 類型設為 Contacts.CONTENT_ITEM_TYPE,但不要設定資料 URI。
傳送這項意圖時,「聯絡人」應用程式會顯示聯絡人清單。使用者可以插入新聯絡人,或選取現有聯絡人並加以編輯。您在意圖中新增的任何擴充資料欄位,都會填入顯示的畫面。您可以使用 Intents.Insert 中指定的任何鍵值。以下程式碼片段說明如何建構及傳送意圖:
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);