You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android通话场景下获取号码并检测是否存储在通讯录的实现问询

实现步骤

1. 先在AndroidManifest.xml添加必要权限和广播配置

<!-- 读取电话状态权限,获取来电号码需要 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 读取通讯录权限,调用已实现的isNumberStored方法需要 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- 安卓9及以下获取去电号码需要的权限,安卓10+废弃该权限,需通过CallLog查询去电 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" android:maxSdkVersion="28" />
<!-- 安卓10+获取去电号码需要额外申请通话记录读取权限 -->
<uses-permission android:name="android.permission.READ_CALL_LOG" />

<receiver android:name=".CallReceiver">
    <intent-filter>
        <!-- 监听来电状态广播 -->
        <action android:name="android.intent.action.PHONE_STATE" />
        <!-- 安卓9及以下监听去电广播 -->
        <action android:name="android.intent.action.NEW_OUTGOING_CALL" android:priority="1000" />
    </intent-filter>
</receiver>

2. 修改CallReceiver的onReceive逻辑,获取号码并调用检测方法

public class CallReceiver extends BroadcastReceiver {
    // 存储获取到的电话号码,避免重复取值
    private String phoneNumber = null;

    @Override
    public void onReceive(Context context , Intent intent) {
        String action = intent.getAction();
        // 处理去电广播(仅安卓9及以下生效)
        if (Intent.ACTION_NEW_OUTGOING_CALL.equals(action)) {
            phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            if (phoneNumber != null && !phoneNumber.isEmpty()) {
                // 检测去电号码是否在通讯录
                boolean isStored = isNumberStored(context, phoneNumber);
                // 此处添加你需要的后续逻辑
            }
        }
        // 处理来电状态广播
        else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
            // 来电响铃状态,获取来电号码
            if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
                phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                if (phoneNumber != null && !phoneNumber.isEmpty()) {
                    // 检测来电号码是否在通讯录
                    boolean isStored = isNumberStored(context, phoneNumber);
                    // 此处添加你需要的后续逻辑
                }
            }
            // 通话接通状态,安卓10+可在此状态下查询最新去电记录获取号码
            else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && phoneNumber == null) {
                    Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI,
                            new String[]{CallLog.Calls.NUMBER},
                            CallLog.Calls.TYPE + " = ?",
                            new String[]{String.valueOf(CallLog.Calls.OUTGOING_TYPE)},
                            CallLog.Calls.DATE + " DESC limit 1");
                    if (cursor != null && cursor.moveToFirst()) {
                        phoneNumber = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER));
                        cursor.close();
                        if (phoneNumber != null && !phoneNumber.isEmpty()) {
                            boolean isStored = isNumberStored(context, phoneNumber);
                            // 此处添加你需要的后续逻辑
                        }
                    }
                    if (cursor != null) {
                        cursor.close();
                    }
                }
            }
            // 通话结束回到空闲状态,清空缓存的号码
            else if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) {
                phoneNumber = null;
            }
        }
    }

    // 原有已经实现的isNumberStored方法无需修改
    public boolean isNumberStored(Context context, String number) {
        Uri lookupUri = Uri.withAppendedPath(
                ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                Uri.encode(number));
        String[] mPhoneNumberProjection = { ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.NUMBER, ContactsContract.PhoneLookup.DISPLAY_NAME };
        Cursor cur = context.getContentResolver().query(lookupUri,mPhoneNumberProjection, null, null, null);
        try {
            if (cur.moveToFirst()) {
                cur.close();
                return true;
            }
        } finally {
            if (cur != null)
                cur.close();
        }
        return false;
    }
}

注意事项

  • 以上涉及的所有权限都属于危险权限,Android 6.0及以上需要在运行时动态申请,获得用户同意后才能正常使用
  • 拿到号码后需做空判断,避免部分异常场景下号码为空导致逻辑崩溃

内容的提问来源于stack exchange,提问作者D Com

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 17:27:04