異動內容
如果應用程式指定即將推出的 Android 版本,就無法再使用 WRITE_CONTACTS 權限直接寫入聯絡人資料。請改用標準聯絡人意圖 (ACTION_INSERT、ACTION_EDIT 和 ACTION_INSERT_OR_EDIT)。如需完整的參考實作,請參閱開發人員指南,瞭解如何使用意圖修改聯絡人資料。
在搭載即將推出的 Android 版本的裝置上,這三個聯絡人意圖的行為會保持一致,且完全不需要權限。如果應用程式指定即將推出的 Android 版本或更新版本,並嘗試直接寫入聯絡人,系統會拒絕這些寫入作業,並導致 SecurityException 或權限遭拒。Android 17 QPR2 (2026 年第 4 季) 將推出新的特殊應用程式存取權限 MANAGE_CONTACTS,適用於需要廣泛存取權來建立及修改聯絡人的少數應用程式。Google Play 今天發布了更新版聯絡人存取權指南,包括MANAGE_CONTACTS。
異動原因
目前,如果應用程式需要儲存聯絡人 (即使只有一個),您可能需要要求 WRITE_CONTACTS。但這項權限會授予廣泛的存取權,允許應用程式在背景對裝置上的聯絡人進行廣泛變更,即使使用者未互動也一樣。大多數應用程式不需要這麼廣泛的權限。
雖然有替代方案,但我們收到意見回饋,指出這些方案需要更標準化,才能在整個生態系統中運作。先前,聯絡人意圖在不同裝置上的行為有所不同。部分編輯器會捨棄您傳入的資料,例如聯絡人相片。在某些裝置上,返回按鈕會在使用者無意間儲存聯絡人,或「建立新聯絡人」選項難以找到。因此,要求權限是合理的選擇。我們將在即將推出的 Android 版本中修正所有這些問題,並要求搭載該版本的裝置遵循相同標準。
替代方案
新增或編輯聯絡人:使用聯絡人意圖
使用 ACTION_INSERT、ACTION_EDIT 和 ACTION_INSERT_OR_EDIT 意圖時,系統會處理繁重的工作,提供簡潔、標準化的聯絡人編輯器體驗。使用者可以開啟快速半頁表單,新增項目,或輕鬆搜尋並新增資訊至現有聯絡人。使用者可以順暢地將這個畫面展開為全頁編輯器,填寫更多詳細資料,而應用程式完全不需要直接寫入權限。請參閱下方的暫定使用者體驗模擬圖:
圖 1:建立新聯絡人 *使用者體驗非最終版本*
圖 2:將資訊新增至現有聯絡人 *使用者體驗尚未定案*
注意:不同裝置製造商可能會修改使用者體驗,以符合其 OS 風格,但行為會保持一致。
您可以在意圖中傳遞選用的資料酬載 (稱為額外資料),進一步簡化建立程序:
EXTRA_ACCOUNT會建議聯絡人儲存到哪個帳戶,這在應用程式同步聯絡人時很有幫助。這項額外功能先前就已推出,但支援情況因裝置而異。從即將推出的 Android 版本開始,各裝置的支援功能將標準化。EXTRA_PHOTO_URI會傳遞相片,預填聯絡人相片。編輯器會為您處理 URI 讀取的權限。這是即將推出的 Android 版本新功能,整個生態系統都會支援。
之前:直接使用
// Requires android.permission.WRITE_CONTACTS fun saveContactDirectly(context: Context, name: String, phone: String, account: Account) { val ops = arrayListOf( ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, account.name) .build(), ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE ) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name) .build(), ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .build() ) context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) }
| 之後:開啟聯絡人編輯器 (不需權限)
fun saveContactWithEditor( context: Context, name: String, phone: String, account: Account, photoUri: Uri ) { val intent = Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI).apply { putExtra(ContactsContract.Intents.Insert.NAME, name) putExtra(ContactsContract.Intents.Insert.PHONE, phone) // Suggest which account the contact is saved to putExtra(ContactsContract.Intents.Insert.EXTRA_ACCOUNT, account) // New in the upcoming Android release: pre-fill the contact photo putExtra(ContactsContract.Intents.Insert.EXTRA_PHOTO_URI, photoUri) clipData = ClipData.newRawUri("", photoUri) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } context.startActivity(intent) }
|
之前:直接更新現有聯絡人
// Requires android.permission.WRITE_CONTACTS fun addPhoneDirectly(context: Context, rawContactId: Long, phone: String) { val values = ContentValues().apply { put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) } context.contentResolver.insert(ContactsContract.Data.CONTENT_URI, values) } | 之後:讓使用者選擇要更新的聯絡人,或建立新聯絡人 fun addPhoneWithEditor(context: Context, phone: String) { val intent = Intent(Intent.ACTION_INSERT_OR_EDIT).apply { type = ContactsContract.Contacts.CONTENT_ITEM_TYPE putExtra(ContactsContract.Intents.Insert.PHONE, phone) } context.startActivity(intent) } 如果您已知道要更新哪個聯絡人,請使用 fun editKnownContact(context: Context, contactUri: Uri, phone: String) { val intent = Intent(Intent.ACTION_EDIT, contactUri).apply { putExtra(ContactsContract.Intents.Insert.PHONE, phone) } context.startActivity(intent) }
|
挑選聯絡人:使用聯絡人選擇工具
如果只需要讀取使用者選擇的聯絡人,請使用 Android 17 起提供的聯絡人選擇工具。不需要任何權限。
通話和訊息應用程式:使用使用者目錄
部分應用程式會在聯絡人中加入「撥打電話給…」或「傳送訊息給…」動作,方便使用者透過「電話」或「聯絡人」應用程式撥打電話或發起即時通訊。如果您的應用程式目前會將額外項目寫入使用者的聯絡人,請改用 People Directory,這項功能將於 Android QPR2 (2026 年第 4 季) 推出。這是一個新的系統目錄,應用程式可在此發布使用者在應用程式中與他人聯絡的方式,而無需編輯使用者的聯絡人。
應用程式遷移範例
以下舉例說明不同類型的應用程式如何存取聯絡人,讓您瞭解這些替代方案的實際運作方式:
| 應用程式類型範例 (僅列舉部分) | 建議的遷移路徑 |
| 社群、P2P 付款和共乘應用程式 | 如果應用程式可讓使用者尋找好友、分攤帳單或分享行程狀態,則完全不需要聯絡人權限。使用聯絡人選擇工具選取一次聯絡人,並在使用者輕觸個人資料中的「儲存至聯絡人」時,使用 EXTRA_PHOTO_URI 啟動 ACTION_INSERT。 |
| 名片掃描器和活動交流應用程式 | 如果應用程式掃描識別證或 QR code 並儲存新聯絡人,或將公司電話號碼新增至現有同事的項目,請使用 ACTION_INSERT 或 ACTION_INSERT_OR_EDIT。標準化的半頁編輯器會預填剖析欄位 (姓名、公司、電話、電子郵件和相片),使用者只要輕觸一下即可驗證並儲存,不必授予背景權限。 |
| VoIP 通話和訊息應用程式 | 請不要要求 WRITE_CONTACTS 將自訂的「撥打電話給…」或「傳送訊息給…」資料列插入使用者的通訊錄,而是透過使用者目錄發布可連線中繼資料,並在使用者從即時通訊討論串新增聯絡人時使用 ACTION_INSERT。 |
| 企業客戶關係管理和雲端同步應用程式 | 如果應用程式會持續與雲端或企業帳戶雙向同步處理背景聯絡人,且無法為每筆記錄向使用者顯示意圖 UI,則應用程式符合宣告 MANAGE_CONTACTS 的資格。 |
請檢查下列幾種變動
- 編輯器不支援自訂資料類型。如果您傳遞的
Insert.DATA資料列含有標準ContactsContract.CommonDataKinds類型以外的 MIME 類型,編輯器會忽略這些 MIME 類型,且不會顯示任何訊息。 SHOW_OR_CREATE_CONTACT並非由系統編輯器處理。裝置隨附的「聯絡人」應用程式仍可處理這項操作。如要在各裝置上維持一致的行為,請使用ACTION_INSERT_OR_EDIT。- 寫入作業預設會失敗。指定即將推出的 Android 版本後,任何不含
MANAGE_CONTACTS的直接寫入都會導致SecurityException or permission denial。進行測試。
我需要MANAGE_CONTACTS嗎?
別緊張。如果應用程式是應使用者要求儲存或編輯聯絡人,上述意圖就足以涵蓋這類行為,您不必取得權限,也不必在 Play 管理中心聲明。
MANAGE_CONTACTS 適用於核心用途為管理聯絡人,且意圖不足的應用程式。例如:
| 您的應用程式… | 需要MANAGE_CONTACTS嗎? |
| 儲存即時通訊、商家名片或訂單中的聯絡人。 | 否,使用 ACTION_INSERT |
| 將電話號碼或電子郵件地址新增至現有聯絡人。 | 否,請使用 ACTION_INSERT_OR_EDIT 或 ACTION_EDIT |
| 讓使用者挑選要邀請、分享或付款的聯絡人。 | 否,請使用聯絡人選擇工具 |
| 在聯絡人中新增通話或訊息動作。 | 否,使用「使用者目錄」 |
| 有專屬的聯絡人編輯畫面。 | 否,僅有自訂介面不符合資格 |
| 是專門用來管理聯絡人或取代撥號器的應用程式。 | 可能可以 |
| 是來電顯示和騷擾/廣告來電阻擋應用程式,可大量更新通訊錄項目。 | 可能可以 |
| 在背景將聯絡人與企業或雲端帳戶同步。 | 可能可以 |
| 大量備份/還原聯絡人,或在裝置間轉移手機資料。 | 可能可以 |
| 為個別聯絡人設定自訂鈴聲。 | 可能可以 |
運作方式:
MANAGE_CONTACTS是特殊的應用程式存取權限。這不是執行階段對話方塊。使用者可依序前往「設定」>「特殊應用程式存取權」>「管理聯絡人」,開啟這項功能。
// Opens Settings > Apps > Special app access > Manage contacts val intent = Intent(Settings.ACTION_MANAGE_CONTACTS, Uri.fromParts("package", packageName, null)) context.startActivity(intent)
- 包括讀取、新增、編輯及刪除聯絡人、帳戶和使用者目錄資料。您不需要同時要求
READ_CONTACTS。 - 如要使用
MANAGE_CONTACTS在 Google Play 發布應用程式,請在 Play 管理中心提交聲明,說明為何意圖無法滿足應用程式的核心功能需求。
遷移步驟
- 尋找聯絡人寫入。在程式碼中搜尋
WRITE_CONTACTS、ContactsContract.RawContacts.CONTENT_URI、ContactsContract.Data.CONTENT_URI和applyBatch(ContactsContract.AUTHORITY, …)。 - 將每個使用者導向的寫入作業替換為意圖:
ACTION_INSERT用於新聯絡人,ACTION_EDIT或ACTION_INSERT_OR_EDIT用於更新。 - 在
Insert.DATA中僅使用標準資料類型。將通話或訊息動作移至「使用者目錄」。 - 請根據上表,判斷是否確實需要
MANAGE_CONTACTS。如有,請規劃 Play 管理中心聲明。 - 如果沒有程式碼路徑需要
WRITE_CONTACTS,請從資訊清單中移除 。
時間軸
| When | 後續事宜 |
| 2026 年 10 月 21 日 | Google Play 宣布MANAGE_CONTACTS政策 |
| 2026 年 (Android 17 季度平台版本 2) | MANAGE_CONTACTS權限可用 |
| 2027 (即將推出的 Android 版本) | WRITE_CONTACTS 不再授予寫入權限給指定即將推出 Android 版本的應用程式。聯絡人意圖在所有裝置上都採用標準化 |
| 2027 年,不早於即將推出的 Android 版本 | Play 管理中心要求使用 MANAGE_CONTACTS 的應用程式提交聲明 |
| 2027 年,不早於即將推出的 Android 版本 | 必須遵守 Play 政策 |
常見問題
- 這項異動會影響所有應用程式嗎?
WRITE_CONTACTS淘汰異動僅適用於指定即將推出的 Android 版本及後續版本的應用程式。指定舊版 SDK 的應用程式會維持現有行為,但無論目標 SDK 為何,所有在新 OS 上執行的應用程式都能使用新的標準化聯絡人編輯器。
- 我的應用程式可以透過意圖刪除聯絡人嗎?
- 沒有,目前沒有刪除聯絡人的意圖。使用者在「聯絡人」應用程式中刪除聯絡人。具有
MANAGE_CONTACTS的應用程式可以直接刪除聯絡人。
- 沒有,目前沒有刪除聯絡人的意圖。使用者在「聯絡人」應用程式中刪除聯絡人。具有
- 我已有自己的聯絡人編輯畫面,可以保留嗎?
- 只有在應用程式符合
MANAGE_CONTACTS資格時,想保留自訂設計,本身不足以構成申請這項權限的理由。
- 只有在應用程式符合
MANAGE_CONTACTS是否會取代 READ_CONTACTS?MANAGE_CONTACTS包含讀取權限,因此您不需要同時要求這兩項權限,但許多應用程式符合READ_CONTACTS的資格,完全不需要修改聯絡人。這些應用程式可以繼續要求READ_CONTACTS。
- 如果使用者使用舊版 Android,會受到什麼影響?
- 聯絡人意圖也適用於舊版本,由裝置的「聯絡人」應用程式處理。大多數應用程式在使用這些意圖時,都能在所有裝置上正常運作。如果應用程式受到特定一致性問題影響,且該問題只能透過最新版本解決,您可以在資訊清單中保留
WRITE_CONTACTS權限,並設定適當的 maxSdkVersion。
- 聯絡人意圖也適用於舊版本,由裝置的「聯絡人」應用程式處理。大多數應用程式在使用這些意圖時,都能在所有裝置上正常運作。如果應用程式受到特定一致性問題影響,且該問題只能透過最新版本解決,您可以在資訊清單中保留
-
產品最新消息在 2026 年 Google I/O 大會上,我們宣布 Android 將從作業系統轉型為智慧系統。我們也示範了如何使用系統原生建構智慧型體驗,並將 Google AI 的強大功能融入應用程式。
Jingyu Shi • 閱讀時間:2 分鐘 -
產品最新消息在今年的 Google I/O 大會上,我們不只會介紹漸進式變更,還會探討應用程式建構方式的根本轉變。我們最新推出的工具專為 AI 代理時代打造,不僅能提升 Android 開發人員的工作效率,還能大幅強化您在程式碼集中部署的 AI 代理。
Matthew Warner • 閱讀時間:8 分鐘 -
產品最新消息在今天的 The Android Show 中,我們宣布 Android 將從作業系統轉型為智慧系統,為應用程式創造更多互動機會。
Matthew McCullough • 閱讀時間:4 分鐘
每週透過電子郵件接收最新的 Android 開發洞察資訊。