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

Android来电无法获取号码,通话事件模板配置问题求助

Fixing Empty Incoming Call Number Issue in Your Android Broadcast Receiver

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_CALL action in your intent filter is incomplete (cut off mid-string).
  • Starting from Android 10 (API 29), you need the READ_CALL_LOG permission 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:16:19