自 2025 年 3 月 27 日起,我們建議您使用 android-latest-release
而非 aosp-main
建構及貢獻 AOSP。詳情請參閱「Android 開放原始碼計畫變更」。
導入電話號碼封鎖功能
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
由於電話是開放式通訊管道,任何人都可以隨時撥打或傳送簡訊給任何號碼,因此 Android 使用者需要能夠輕鬆封鎖不想要的來電和簡訊。
在 Android 7.0 之前,Android 使用者必須依賴下載的應用程式,才能限制來自惱人電話號碼的通話和簡訊。由於缺乏用於封鎖通話和訊息的適當 API,因此許多這類應用程式無法正常運作,或提供不理想的使用體驗。
部分製造商可能會提供自家的封鎖解決方案,但如果使用者切換裝置,由於缺乏互通性,他們可能會完全失去封鎖清單。最後,即使使用者採用提供這類功能的撥號應用程式和訊息應用程式,仍可能需要在每個應用程式中執行封鎖動作,才能讓封鎖措施同時對通話和簡訊生效。
功能
Android 7.0 版本推出 BlockedNumberProvider
內容供應器,可儲存使用者指定的電話號碼清單,這些號碼不應透過電話通訊 (通話、簡訊、多媒體訊息) 與使用者聯絡。系統會尊重封鎖清單中的號碼,限制來自這些號碼的通話和簡訊。Android 7.0 會顯示已封鎖的號碼清單,並允許使用者新增及移除號碼。
此外,系統和平台上的相關應用程式可透過號碼封鎖功能共同運作,協助保護使用者並簡化使用體驗。預設撥號程式、預設訊息應用程式、UICC 特權應用程式,以及與系統具有相同簽章的應用程式,都可以直接讀取及寫入封鎖清單。由於系統會儲存已封鎖的號碼,因此無論使用者採用哪種撥號或訊息應用程式,這些號碼都會持續封鎖。最後,無論製造商為何,都可以在任何新裝置上還原封鎖號碼清單。
- 使用者可以確保擁有可立即使用的封鎖功能,且在切換應用程式或換新手機時,不會遺失封鎖清單。系統中所有相關應用程式都可以共用相同的清單,為使用者提供最簡化順暢的體驗。
- 應用程式開發人員不必自行開發方法來管理封鎖清單,以及接收的通話和訊息。他們只需使用平台提供的功能即可。
- 使用者選取做為預設的撥號 / 訊息應用程式,可以讀取及寫入供應器。其他應用程式可以使用
createManageBlockedNumbersIntent()
啟動封鎖清單管理使用者介面 - 原始設備製造商 (OEM) 可以使用平台提供的功能,提供封鎖功能的即時運作體驗。原始設備製造商 (OEM) 可以放心,因為使用者從其他 OEM 裝置切換時,系統會一併轉移封鎖清單,讓使用者享有更優質的使用者體驗。
- 如果電信業者有自己的撥號或訊息應用程式,可以重複使用平台功能,讓使用者管理封鎖清單。他們可以放心,即使使用者換新裝置,使用者的封鎖名單仍會保留在裝置上。最後,所有具備電信業者特權的應用程式都能讀取封鎖清單,因此如果電信業者想根據封鎖清單為使用者提供更強大的封鎖功能,現在就能透過這項功能實現。
資料流程
圖 1. 封鎖電話號碼資料流
範例和來源
以下是使用新功能「封鎖號碼」的呼叫範例:
透過應用程式啟動已封鎖號碼管理工具
Context.startActivity(telecomManager.createManageBlockedNumbersIntent(), null);
查詢已封鎖的號碼
Cursor c = getContentResolver().query(BlockedNumbers.CONTENT_URI,
new String[]{BlockedNumbers.COLUMN_ID,
BlockedNumbers.COLUMN_ORIGINAL_NUMBER,
BlockedNumbers.COLUMN_E164_NUMBER}, null, null, null);
輸入要封鎖的電話號碼
ContentValues values = new ContentValues();
values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
刪除封鎖的電話號碼
ContentValues values = new ContentValues();
values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
getContentResolver().delete(uri, null, null);
實作
以下是必須完成的概略工作,才能使用電話號碼封鎖功能:
- 原始設備製造商 (OEM) 可使用
BlockedNumberProvider
在裝置上實作通話/訊息限制功能 - 如果電信業者有撥號或訊息應用程式,請使用
BlockedNumberProvider
實作通話/訊息限制功能 - 第三方撥號和訊息應用程式供應商使用
BlockedNumberProvider
來實作封鎖功能
原始設備製造商 (OEM) 的最佳做法
如果裝置先前從未附帶任何額外的通話/訊息限制功能,請在所有這類裝置上使用 Android 開放原始碼計畫 (AOSP) 中的電話號碼封鎖功能。建議您支援合理的封鎖條件,例如直接從通話記錄或訊息會話串中封鎖號碼。
如果裝置先前已提供通話/訊息限制功能,請調整這些功能,讓所有遭封鎖的完全相符的電話號碼都儲存在 BlockedNumberProvider,
中,且供應商的行為符合 Android 相容性定義文件 (CDD) 中列出的這項功能要求。
只要符合禁止嚴格比對電話號碼的 CDD 規定,您可以透過自訂供應器和自訂 UI/控制項實作任何其他進階功能。建議將這些其他功能標示為「進階」功能,以免與基本號碼封鎖功能混淆。
API
以下是使用的 API:
TelecomManager
API
Intent createManageBlockedNumbersIntent()
Carrier
Config
KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT
- 請參閱
BlockedNumberContract
BlockedNumberContract
提供的 API
boolean isBlocked(Context context, String phoneNumber)
int unblock(Context context, String phoneNumber)
boolean canCurrentUserBlockNumbers(Context context)
使用者介面
AOSP 提供的 BlockedNumbersActivity.java 使用者介面可直接使用。只要裝置導入者導入的 UI 版本符合相關 CDD 規定,也可以導入自己的 UI 版本。
請注意,您可能需要合作夥伴的電腦應用程式來備份及還原,才能使用 BlockedNumberProvider
實作封鎖清單還原作業。請參閱下方圖片,瞭解 AOSP 提供的封鎖號碼介面。
圖 2. 封鎖電話號碼使用者介面
驗證
實作者可以執行下列 CTS 測試,確保功能的版本能正常運作:
android.provider.cts.BlockedNumberContractTest
com.android.cts.numberblocking.hostside.NumberBlockingTest
android.telecom.cts.ExtendedInCallServiceTest#testIncomingCallFromBlockedNumber_IsRejected
android.telephony.cts.SmsManagerTest#testSmsBlocking
執行 $ adb root
後,您可以使用 adb
指令操作 BlockedNumberProvider
。例如:
adb root
adb shell content query --uri content://com.android.blockednumber/blocked
adb shell content insert --uri / content://com.android.blockednumber/blocked --bind / original_number:s:'6501002000'
adb shell content delete --uri / content://com.android.blockednumber/blocked/1
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-02-21 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-02-21 (世界標準時間)。"],[],[],null,["# Implement phone number blocking\n\nBecause telephony is such an open communications channel - anyone may call or\ntext any number at any time - Android users need the ability to easily block\nunwanted calls and texts.\n\n\nBefore Android 7.0, Android users had to rely on downloaded apps to restrict calls and\ntexts from bothersome phone numbers. Many of those apps either do not work as\ndesired or provide a less-than ideal experience because there are no proper APIs\nfor blocking calls and messages.\n\n\nSome manufacturers might ship their own blocking solutions out-of-the-box, but\nif users switch devices, they may lose the blocked list completely due to lack\nof interoperability. Finally, even if users are employing dialing apps and\nmessaging clients that provide such functionality, they likely still have to\nperform the block action in each app for the block to take effect for both\ncalling and texting.\n\nFeatures\n--------\n\n\nThe Android 7.0 release introduces a `BlockedNumberProvider` content\nprovider that stores a list of phone numbers the user has specified should not\nbe able to contact them via telephony communications (calls, SMS, MMS). The\nsystem will respect the numbers in the blocked list by restricting calls and\ntexts from those numbers. Android 7.0 displays the list of blocked numbers and\nallows the user to add and remove numbers.\n\n\nFurther, the number-blocking feature enables the system and the relevant apps on\nthe platform to work together to help protect the user and to simplify the\nexperience. The default dialer, default messaging client, UICC-privileged app,\nand apps with the same signature as the system can all directly read from and\nwrite to the blocked list. Because the blocked numbers are stored on the system,\nno matter what dialing or messaging apps the user employs, the numbers stay\nblocked. Finally, the blocked numbers list may be restored on any new device,\nregardless of the manufacturer.\n\n- User will be guaranteed to have a blocking feature that works out-of-the-box and will not lose their block list when they switch apps or get a new phone. All relevant apps on the system can share the same list to provide the user with the most streamlined experience.\n- App developers do not need to develop their own way to manage a block list and the calls and messages that come in. They can simply use the platform-provided feature.\n- Dialer / messenger apps that are selected as the default by the user can read and write to the provider. Other apps can launch the block list management user interface by using `createManageBlockedNumbersIntent()`\n- OEMs can use platform provided feature to ship a blocking feature out-of-the-box. OEMs can rest assured that when users switch from another OEM's device that they have a better onboarding experience because the block list will be transferred as well.\n- If carrier has their own dialer or messenger app, they can reuse platform feature for allowing the user to maintain a block list. They can rest assured that the user's block list can stay with the users, even when they get a new device. Finally, all carrier-privileged apps can read the block list, so if the carrier wants to provide some additional more powerful blocking for the user based on the block list, that is now possible with this feature.\n\nData flow\n---------\n\n\n**Figure 1.** Block phone numbers data flow\n\nExamples and source\n-------------------\n\n\nHere are example calls using the number-blocking new feature:\n\n### Launch blocked number manager from app\n\n```text\nContext.startActivity(telecomManager.createManageBlockedNumbersIntent(), null);\n```\n\n### Query blocked numbers\n\n```scdoc\nCursor c = getContentResolver().query(BlockedNumbers.CONTENT_URI,\n new String[]{BlockedNumbers.COLUMN_ID,\n BlockedNumbers.COLUMN_ORIGINAL_NUMBER,\n BlockedNumbers.COLUMN_E164_NUMBER}, null, null, null);\n```\n\n### Put blocked number\n\n```scdoc\nContentValues values = new ContentValues();\nvalues.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, \"1234567890\");\nUri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);\n```\n\n### Delete blocked number\n\n```scdoc\nContentValues values = new ContentValues();\nvalues.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, \"1234567890\");\nUri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);\ngetContentResolver().delete(uri, null, null);\n```\n\nImplementation\n--------------\n\n\nThese are the high-level tasks that must be completed to put the number-blocking\nfeature to use:\n\n- OEMs implement call/message-restriction features on their devices by using `BlockedNumberProvider`\n- If carrier has dialer or messenger app, implement call/message restriction features by using `BlockedNumberProvider`\n- Third-party dialer and messenger app vendors use `BlockedNumberProvider` for their blocking features\n\n### Recommendations for OEMs\n\n\nIf the device had previously never shipped with any additional call/message\nrestriction features, use the number-blocking feature in the Android Open Source\nProject (AOSP) on all such devices. It is recommended that reasonable entry\npoints for blocking are supported, such as blocking a number right from the call\nlog or within a message thread.\n\n\nIf the device had previously shipped with call/message restriction features,\nadapt the features so all *strict-match phone numbers* that are blocked\nare stored in the `BlockedNumberProvider,` and that the behavior\naround the provider satisfy the requirements for this feature outlined in the\nAndroid Compatibility Definition Document (CDD).\n\n\nAny other advanced feature can be implemented via custom providers and custom UI\n/ controls, as long as the CDD requirements are satisfied with regards to\nblocking strict-match phone numbers. It is recommended that those other features\nbe labeled as \"advanced\" features to avoid confusion with the basic\nnumber-blocking feature.\n\n### APIs\n\n\nHere are the APIs in use:\n\n- [TelecomManager](http://developer.android.com/reference/android/telecom/TelecomManager.html)`\n API`\n - `Intent createManageBlockedNumbersIntent()`\n- [Carrier\n Config](http://developer.android.com/reference/android/telephony/CarrierConfigManager.html)\n - `KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT`\n- Please refer to `BlockedNumberContract`\n - APIs provided by [BlockedNumberContract](https://developer.android.com/reference/android/provider/BlockedNumberContract.html)\n - `boolean isBlocked(Context context, String phoneNumber)`\n - `int unblock(Context context, String phoneNumber)`\n - `boolean canCurrentUserBlockNumbers(Context context)`\n\n### User interface\n\n\nThe BlockedNumbersActivity.java user interface provided in AOSP can be used as\nis. Device implementers may also implement their own version of the UI, as long as it\nsatisfies related CDD requirements.\n\n\nPlease note, the partner's PC app for backup and restore may be needed\nto implement restoration of the block list by using\n`BlockedNumberProvider`. See the images below for the blocked\nnumbers interface supplied in AOSP.\n\n\n**Figure 2.** Block phone numbers user interface\n\nValidation\n----------\n\n\nImplementers can ensure their version of the feature works as intended by\nrunning the following CTS tests: \n\n```\nandroid.provider.cts.BlockedNumberContractTest\ncom.android.cts.numberblocking.hostside.NumberBlockingTest\nandroid.telecom.cts.ExtendedInCallServiceTest#testIncomingCallFromBlockedNumber_IsRejected\nandroid.telephony.cts.SmsManagerTest#testSmsBlocking\n```\n\n\nThe `BlockedNumberProvider` can be manipulated using `adb` commands\nafter running `$ adb root`. For example: \n\n adb root\n adb shell content query --uri content://com.android.blockednumber/blocked\n adb shell content insert --uri / content://com.android.blockednumber/blocked --bind / original_number:s:'6501002000'\n adb shell content delete --uri / content://com.android.blockednumber/blocked/1"]]