技术求助:呼出电话接通时OnReceive BroadcastReceiver未触发
Hey there! I’ve dealt with this exact problem before, so I totally get the frustration when your BroadcastReceiver only catches call initiation and end, but not the connected state. Let’s break down why this happens and how to fix it:
Why your current setup isn’t working
Android doesn’t send a system-wide broadcast for outgoing call connection by default. The standard ACTION_NEW_OUTGOING_CALL only triggers when the call starts, and ACTION_PHONE_STATE_CHANGED will notify you when the call ends (back to CALL_STATE_IDLE), but there’s no direct broadcast for when the call actually connects. Static registered BroadcastReceivers can’t pick up this state change because it requires more granular, dynamic listening.
Step-by-step solution
We’ll combine a BroadcastReceiver to detect outgoing call initiation, then use a PhoneStateListener (dynamically registered) plus AudioManager to confirm when the call is actually connected.
1. Update your permissions
Make sure you have these in your AndroidManifest.xml (note: for Android 10+, some permissions require runtime requests):
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
2. Create the BroadcastReceiver to catch outgoing call start
This receiver will trigger when the user initiates an outgoing call, and we’ll start our state listener from here:
public class OutgoingCallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())) { String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); // Start our call state listener CallStateMonitor.startListening(context, phoneNumber); } } }
3. Implement the CallStateMonitor with PhoneStateListener and AudioManager
This class will dynamically listen for phone state changes and check if the call is connected via audio state:
public class CallStateMonitor extends PhoneStateListener { private static TelephonyManager telephonyManager; private static AudioManager audioManager; private static String targetNumber; private static boolean isCallConnected = false; public static void startListening(Context context, String phoneNumber) { targetNumber = phoneNumber; telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); // Register the listener to track call state telephonyManager.listen(new CallStateMonitor(), PhoneStateListener.LISTEN_CALL_STATE); } @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_OFFHOOK: // This triggers when the call is initiated, but not necessarily connected // Add a small delay to let the audio state update, then check if call is active new Handler(Looper.getMainLooper()).postDelayed(() -> { if (audioManager.isVoiceCallActive()) { isCallConnected = true; // Your logic here: the outgoing call is now connected! Log.d("CallMonitor", "Outgoing call to " + targetNumber + " connected"); } }, 1000); // Adjust delay based on device performance if needed break; case TelephonyManager.CALL_STATE_IDLE: // Call ended if (isCallConnected) { Log.d("CallMonitor", "Outgoing call to " + targetNumber + " ended"); isCallConnected = false; } // Unregister the listener to free up resources telephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); break; } } }
4. Register the BroadcastReceiver in AndroidManifest.xml
<receiver android:name=".OutgoingCallReceiver" android:exported="true"> <intent-filter> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver>
Important notes for newer Android versions
- Android 8.0+: Static BroadcastReceivers for many system actions are restricted. If your receiver isn’t triggering, consider registering it dynamically in your Activity/Service instead, or use a foreground service if you need background listening.
- Runtime permissions: For Android 6.0+, you’ll need to request
READ_PHONE_STATEandPROCESS_OUTGOING_CALLSfrom the user at runtime. - OEM variations: Some device manufacturers modify telephony behavior, so the delay in the
CALL_STATE_OFFHOOKcase might need adjustment (try 500ms or 1500ms if the 1s delay doesn’t work).
Alternative fallback: AccessibilityService
If the above method isn’t reliable on certain devices, you can use an AccessibilityService to listen for call state changes. This approach is more consistent but requires the user to enable accessibility permissions for your app.
内容的提问来源于stack exchange,提问作者user5078013

