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

如何使用CallScreeningService API获取来电号码并在Activity中注册服务

Android CallScreeningService 实现与Activity集成指南

1. 清单文件中声明服务与权限

首先必须在AndroidManifest.xml中注册你的CallScreeningService子类,并添加必要权限:

<!-- 基础权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- Android 10+ 需添加 -->
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<!-- Android 12+ 需添加 -->
<uses-permission android:name="android.permission.READ_CALL_LOG" />

<application ...>
    <service
        android:name=".YourCallScreeningService"
        android:permission="android.permission.BIND_SCREENING_SERVICE">
        <intent-filter>
            <action android:name="android.telecom.CallScreeningService" />
        </intent-filter>
    </service>
</application>

2. Activity中请求动态权限

上述权限均为危险权限,需在Activity中动态申请:

private static final int REQUEST_PERM = 100;

private String[] getRequiredPermissions() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        return new String[]{
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.CALL_PHONE,
                Manifest.permission.ANSWER_PHONE_CALLS,
                Manifest.permission.READ_CALL_LOG
        };
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        return new String[]{
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.CALL_PHONE,
                Manifest.permission.ANSWER_PHONE_CALLS
        };
    } else {
        return new String[]{
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.CALL_PHONE
        };
    }
}

// 在Activity初始化时调用
private void checkAndRequestPermissions() {
    boolean allGranted = true;
    for (String perm : getRequiredPermissions()) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            allGranted = false;
            break;
        }
    }
    if (!allGranted) {
        ActivityCompat.requestPermissions(this, getRequiredPermissions(), REQUEST_PERM);
    } else {
        setDefaultScreeningApp();
    }
}

// 处理权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERM) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }
        if (allGranted) {
            setDefaultScreeningApp();
        } else {
            Toast.makeText(this, "需授予全部权限才能使用来电筛选功能", Toast.LENGTH_SHORT).show();
        }
    }
}

3. 设置应用为默认来电筛选应用

只有被设为默认的应用才能收到来电回调,在Activity中添加以下代码:

private static final int REQUEST_SET_DEFAULT = 200;

private void setDefaultScreeningApp() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        TelecomManager telecomManager = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
        if (telecomManager == null) return;
        
        ComponentName serviceComponent = new ComponentName(this, YourCallScreeningService.class);
        String currentDefault = telecomManager.getDefaultCallScreeningApp();
        if (!serviceComponent.flattenToString().equals(currentDefault)) {
            Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_CALL_SCREENING_APP);
            intent.putExtra(TelecomManager.EXTRA_CALL_SCREENING_COMPONENT_NAME, serviceComponent);
            startActivityForResult(intent, REQUEST_SET_DEFAULT);
        }
    }
}

// 处理默认应用设置结果
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_SET_DEFAULT) {
        if (resultCode == RESULT_OK) {
            Toast.makeText(this, "已设为默认来电筛选应用", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "未设置默认应用,无法获取来电信息", Toast.LENGTH_SHORT).show();
        }
    }
}

4. 在服务类中获取来电号码

你的YourCallScreeningService子类中,重写onScreenCall方法即可获取来电信息:

public class YourCallScreeningService extends CallScreeningService {
    @Override
    public void onScreenCall(Call.Details callDetails) {
        // 获取来电号码
        String phoneNumber = callDetails.getHandle().getSchemeSpecificPart();
        Log.d("CallLog", "来电号码:" + phoneNumber);
        
        // 允许通话(如需拦截可调用responseBuilder.setDisallowCall(true))
        CallResponse response = new CallResponse.Builder().build();
        respondToCall(callDetails, response);
        
        // 可通过广播/ViewModel等方式将号码传递给Activity
        sendCallNumberToActivity(phoneNumber);
    }
    
    // 示例:用LocalBroadcast传递数据到Activity
    private void sendCallNumberToActivity(String number) {
        Intent intent = new Intent("com.your.package.CALL_RECEIVED");
        intent.putExtra("PHONE_NUMBER", number);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
}

5. Activity接收来电数据

以LocalBroadcast为例,在Activity中注册接收器:

private BroadcastReceiver callReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String number = intent.getStringExtra("PHONE_NUMBER");
        // 更新UI或处理号码
        tvCallNumber.setText("收到来电:" + number);
    }
};

@Override
protected void onResume() {
    super.onResume();
    LocalBroadcastManager.getInstance(this)
            .registerReceiver(callReceiver, new IntentFilter("com.your.package.CALL_RECEIVED"));
}

@Override
protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(callReceiver);
}

内容的提问来源于stack exchange,提问作者Akshay M Joshi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:31:19