Android中如何通过TelephonyManager检测去电接通状态
Android 去电接通状态检测实现
你现有代码里用PhoneStateListener监听CALL_STATE_RINGING只能覆盖来电响铃场景,首先要明确:TelephonyManager原生定义的3种基础通话状态,本身无法直接区分去电接通的节点,三个状态分别是:
CALL_STATE_IDLE:无任何通话的待机状态CALL_STATE_RINGING:来电响铃状态CALL_STATE_OFFHOOK:线路占用状态,去电拨号启动、来电接通、去电接通三个场景都会触发这个状态,没法单独识别去电接通的瞬间
要精准检测去电接通,需要按Android版本适配对应方案:
高版本适配(Android 6.0 及以上,推荐)
Android 6.0开始系统新增了InCallService相关API,可以拿到精确到每通电话的全生命周期状态,不需要申请敏感权限,是目前兼容性、准确率最高的方案。
- 先在
AndroidManifest.xml中声明服务:
<service android:name=".CallDetectService" android:permission="android.permission.BIND_INCALL_SERVICE"> <intent-filter> <action android:name="android.telecom.InCallService" /> </intent-filter> <!-- 标记为非UI通话服务,不会替换系统默认通话界面 --> <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="false" /> </service>
- 实现服务逻辑,监听去电接通事件:
public class CallDetectService extends InCallService { // 标记当前是否为去电路径 private boolean currentIsOutgoing = false; @Override public void onCallAdded(Call call) { super.onCallAdded(call); // 新通话建立时先判断是否是去电 int initState = call.getState(); if (initState == Call.STATE_DIALING || initState == Call.STATE_CONNECTING) { currentIsOutgoing = true; } // 注册通话状态变更回调 call.registerCallback(new Call.Callback() { @Override public void onStateChanged(Call call, int newState) { super.onStateChanged(call, newState); // 去电状态变为ACTIVE即为接通 if (currentIsOutgoing && newState == Call.STATE_ACTIVE) { String callNumber = call.getDetails().getHandle().getSchemeSpecificPart(); // 此处写入去电接通后的业务逻辑 Log.i("CallDetect", "去电接通,号码:" + callNumber); } // 通话断开时重置标记 if (newState == Call.STATE_DISCONNECTED) { currentIsOutgoing = false; call.unregisterCallback(this); } } }); } }
低版本兼容(Android 6.0 以下)
Android 5.x及更早版本没有开放精确的通话状态API,可以通过组合逻辑近似判断:
- 注册监听
NEW_OUTGOING_CALL系统广播,捕获去电发起的时机,记录去电号码、拨号开始时间 - 配合
PhoneStateListener监听CALL_STATE_OFFHOOK状态,排除拨号秒挂的场景后,如果线路持续处于占用状态超过3秒,即可判定为去电接通
注意:这个方案在不同厂商定制ROM上可能存在1-2秒的判断误差,仅建议作为低版本兼容兜底使用,高版本务必使用
InCallService方案保证准确率。
内容的提问来源于stack exchange,提问作者Aneeb
相关产品推荐
相关产品推荐

