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
相关产品推荐
相关产品推荐

