如何在默认来电界面为未保存的特定号码显示来电名称?
在系统默认来电UI中显示未保存特定号码的名称方案
针对你的需求,无需开发自有拨号应用或弹窗,可通过系统原生API实现未保存特定号码的来电名称显示,分Android和iOS平台分别说明:
Android平台实现方式
利用Android系统的CallScreeningService(Android 10及以上推荐),该API允许第三方应用作为来电筛选服务,向系统提供来电识别信息,系统默认来电UI会直接显示该名称。
步骤1:配置Manifest与权限
在AndroidManifest.xml中声明服务并申请必要权限:
<!-- 声明来电筛选服务 --> <service android:name=".MyCallScreeningService" android:permission="android.permission.BIND_CALL_SCREENING_SERVICE"> <intent-filter> <action android:name="android.telecom.CallScreeningService" /> </intent-filter> </service> <!-- 申请必要权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ 需添加 -->
步骤2:实现来电筛选服务
创建CallScreeningService子类,在来电时匹配目标号码并设置显示名称:
public class MyCallScreeningService extends CallScreeningService { // 替换为目标号码(需使用E.164格式,如+8613xxxxxxxxx) private static final String TARGET_PHONE_NUMBER = "+1234567890"; private static final String DISPLAY_NAME = "亚马逊"; @Override public void onScreenCall(Call.Details callDetails) { String incomingNumber = callDetails.getHandle().getSchemeSpecificPart(); CallResponse.Builder responseBuilder = new CallResponse.Builder(); // 匹配目标号码,设置显示名称 if (TARGET_PHONE_NUMBER.equals(incomingNumber)) { responseBuilder.setCallerDisplayName(DISPLAY_NAME, CallResponse.DISPLAY_SOURCE_VERIFIED); } // 允许来电,不拦截 responseBuilder.setShouldAllowCall(true); respondToCall(callDetails, responseBuilder.build()); } }
步骤3:引导用户开启权限
应用需引导用户前往系统设置,开启应用的来电识别权限(路径:设置 > 应用 > 你的应用 > 权限 > 来电识别),否则服务无法正常工作。
iOS平台实现方式
利用iOS的CallKit框架中的CXCallDirectoryExtension,该扩展可向系统提供来电识别数据,默认电话应用会自动读取并显示未保存号码的名称。
步骤1:创建CallKit目录扩展
在Xcode中添加新的Target,选择Call Directory Extension,命名后创建。
步骤2:配置Info.plist
扩展的Info.plist会自动生成以下配置,确保正确:
<key>NSExtension</key> <dict> <key>NSExtensionMainStoryboard</key> <string>MainInterface</string> <key>NSExtensionPointIdentifier</key> <string>com.apple.callkit.calldirectory</string> <key>NSExtensionPrincipalClass</key> <string>$(PRODUCT_MODULE_NAME).CustomCallDirectoryProvider</string> </dict>
步骤3:实现识别逻辑
在扩展的主类中添加目标号码与对应名称:
import CallKit class CustomCallDirectoryProvider: CXCallDirectoryProvider, CXCallDirectoryExtensionContextDelegate { // 替换为目标号码(E.164格式)与显示名称 private let targetEntries = ["+1234567890": "亚马逊"] override func beginRequest(with context: CXCallDirectoryExtensionContext) { context.delegate = self addIdentificationEntries(to: context) context.completeRequest() } private func addIdentificationEntries(to context: CXCallDirectoryExtensionContext) { for (phoneNumber, label) in targetEntries { guard let number = CXCallDirectoryPhoneNumber(phoneNumber) else { continue } context.addIdentificationEntry(withNextSequentialPhoneNumber: number, label: label) } } func requestFailed(for extensionContext: CXCallDirectoryExtensionContext, withError error: Error) { // 处理请求失败逻辑,如日志记录 } }
步骤4:引导用户开启权限
应用需引导用户前往系统设置,开启应用的来电阻止与身份识别权限(路径:设置 > 电话 > 来电阻止与身份识别),否则扩展无法生效。
通用注意事项
- 号码格式:必须使用E.164标准格式(含国家码的完整号码),否则匹配会失败。
- 动态更新:如需添加/修改目标号码,Android可在服务中维护号码列表;iOS可通过主应用调用
CXCallDirectoryManager.reloadExtension(_:completionHandler:)触发扩展重新加载。 - 权限依赖:两个平台均需用户手动开启对应权限,应用需提供清晰的引导流程。
内容的提问来源于stack exchange,提问作者Mohammad Taqi
相关产品推荐
相关产品推荐

