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

如何使用InCallService拒接来电并获取Android12+来电号码

问题
  1. 如何使用InCallService拒接来电?官方文档显示TelephonyManager.EXTRA_INCOMING_NUMBER和TelecomManager.endCall()已被弃用,需改用InCallService,但不清楚具体用法,仅需实现拒接功能,无需开发默认通话应用。
  2. Android 12及以上版本中,通过CallerNumberReceiver无法获取来电号码,如何解决?

用户提供的配置与代码

AndroidManifest.xml

<receiver android:name=".CallerNumberReceiver"
          android:enabled="true"
          android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver>

CallerNumberReceiver类

package com.example.myapplication1;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;

import android.widget.Toast;

import androidx.annotation.RequiresApi;

public class CallerNumberReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {

            telephonyManager.registerTelephonyCallback(context.getMainExecutor(), new CallStateListener() {
                @Override
                public void onCallStateChanged(int state) {
                    if(state == TelephonyManager.CALL_STATE_RINGING){
                        // WHERE IS PHONE NUMBER?
                    }
                }
            });
        } else {
            telephonyManager.listen(new PhoneStateListener() {
                @Override
                public void onCallStateChanged(int state, String phoneNumber) {
                    super.onCallStateChanged(state, phoneNumber);
                    if (state == TelephonyManager.CALL_STATE_RINGING) {
                        Toast.makeText(context, "number : " + phoneNumber, Toast.LENGTH_SHORT).show();
                    }
                }
            }, PhoneStateListener.LISTEN_CALL_STATE);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.S)
    abstract static class CallStateListener extends TelephonyCallback implements TelephonyCallback.CallStateListener {
        @Override
        public void onCallStateChanged(int state) {

        }

    }

}

解决方案

一、Android 12+ 获取来电号码

Android 12(API 31)及以上,PHONE_STATE广播不再携带来电号码,TelephonyCallback.CallStateListener也无法获取号码,需改用TelephonyCallback.CallerIdListener,同时需要申请对应权限:

  1. 添加权限到Manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
  1. 动态申请权限
    在应用启动或使用前,动态申请上述危险权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_PHONE_NUMBERS}, 1001);
}
  1. 修改Receiver代码
    替换原监听逻辑为CallerIdListener,在回调中获取来电号码:
@RequiresApi(api = Build.VERSION_CODES.S)
static class CallerIdCallback extends TelephonyCallback implements TelephonyCallback.CallerIdListener {
    private Context context;

    public CallerIdCallback(Context context) {
        this.context = context;
    }

    @Override
    public void onCallerIdReceived(@NonNull TelephonyManager.CallerIdResult callerIdResult) {
        super.onCallerIdReceived(callerIdResult);
        String phoneNumber = callerIdResult.getPhoneNumber();
        if (phoneNumber != null) {
            Toast.makeText(context, "来电号码: " + phoneNumber, Toast.LENGTH_SHORT).show();
        }
    }
}

// 在onReceive方法中注册
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    telephonyManager.registerTelephonyCallback(context.getMainExecutor(), new CallerIdCallback(context));
}

二、使用InCallService拒接来电

即使不开发默认通话应用,也可通过InCallService实现拒接功能,步骤如下:

  1. 添加权限与服务到Manifest
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<application>
    <service android:name=".MyInCallService"
             android:permission="android.permission.BIND_INCALL_SERVICE">
        <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI"
                   android:value="false" /> <!-- 无需UI,仅处理逻辑 -->
        <intent-filter>
            <action android:name="android.telecom.InCallService" />
        </intent-filter>
    </service>
</application>
  1. 实现InCallService子类
package com.example.myapplication1;

import android.telecom.Call;
import android.telecom.InCallService;

public class MyInCallService extends InCallService {

    @Override
    public void onCallAdded(Call call) {
        super.onCallAdded(call);
        // 判断来电状态,执行拒接
        if (call.getState() == Call.STATE_RINGING) {
            call.reject(false, null);
        }
    }

    @Override
    public void onCallRemoved(Call call) {
        super.onCallRemoved(call);
    }
}
  1. 动态申请权限
    在应用启动时申请ANSWER_PHONE_CALLS权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    requestPermissions(new String[]{Manifest.permission.ANSWER_PHONE_CALLS}, 1002);
}
  1. 注意事项
  • 部分厂商对通话拦截有额外限制,需确保应用权限正常授予。
  • 系统会在来电时绑定该服务,若多个应用注册InCallService,优先级由系统控制。

内容的提问来源于stack exchange,提问作者Muthana Rabab'ah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:09:57