Android来电无法获取号码,通话事件模板配置问题求助
Hey there, let's figure out why you're getting empty values for incoming call numbers while outgoing calls work fine. I've gone through your code and setup, and here are the key issues and fixes:
1. Broken AndroidManifest Setup
First off, your manifest has two critical problems:
- The
NEW_OUTGOING_CALLaction in your intent filter is incomplete (cut off mid-string). - Starting from Android 10 (API 29), you need the
READ_CALL_LOGpermission to access incoming call numbers—this isn't included in your current permissions.
Here's the corrected manifest section:
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> <uses-permission android:name="android.permission.READ_CALL_LOG" /> <!-- Add this for Android 10+ --> <receiver android:name=".CallReceiver" > <intent-filter> <action android:name="android.intent.action.PHONE_STATE" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> <!-- Fix this incomplete action --> </intent-filter> </receiver>
2. Missing Runtime Permissions
For Android 6.0 (API 23) and above, dangerous permissions like READ_PHONE_STATE, PROCESS_OUTGOING_CALLS, and READ_CALL_LOG need to be requested at runtime, not just declared in the manifest. Add this code to your main activity to request permissions:
private static final int PERMISSION_REQUEST_CODE = 100; private String[] requiredPermissions = { Manifest.permission.READ_PHONE_STATE, Manifest.permission.PROCESS_OUTGOING_CALLS, Manifest.permission.READ_CALL_LOG }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!hasAllPermissions()) { requestPermissions(requiredPermissions, PERMISSION_REQUEST_CODE); } } } private boolean hasAllPermissions() { for (String perm : requiredPermissions) { if (checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (!allGranted) { Toast.makeText(this, "All permissions are required for call tracking", Toast.LENGTH_LONG).show(); } } }
3. Incorrect Incoming Number Retrieval Logic
In your PhoneStateReceiver's onReceive method, you're not properly fetching the incoming call number. The Intent.EXTRA_PHONE_NUMBER is only for outgoing calls—you need to use TelephonyManager.EXTRA_INCOMING_NUMBER for incoming calls, and you had this line commented out.
Here's the fixed onReceive method:
@Override public void onReceive(Context context, Intent intent) { savedContext = context; String number = null; if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { // Handle outgoing call number savedNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); } else { // Handle phone state changes (incoming calls) String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE); number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER); // Fetch incoming number int state = 0; if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) { state = TelephonyManager.CALL_STATE_IDLE; } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { state = TelephonyManager.CALL_STATE_OFFHOOK; } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) { state = TelephonyManager.CALL_STATE_RINGING; // Save the number when ringing to ensure it's available for missed calls if (number != null) { savedNumber = number; } } onCallStateChanged(context, state, number); } }
4. Variable Consistency Fix
In your onCallStateChanged method, add a null check to avoid passing empty values to your callbacks when handling incoming calls:
case TelephonyManager.CALL_STATE_RINGING: isIncoming = true; callStartTime = new Date(); // Only update savedNumber if we have a valid incoming number if (number != null) { savedNumber = number; } onIncomingCallStarted(context, savedNumber, callStartTime); break;
Final Notes
- Test this on both older (pre-API 29) and newer Android versions to ensure compatibility.
- If you're still getting empty numbers on some devices, note that certain manufacturers might restrict access to call data—you may need to guide users to enable additional app permissions in system settings.
内容的提问来源于stack exchange,提问作者parish

