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

.NET MAUI实现CallScreeningService遇问题:角色请求失败及服务注册疑问

问题解决指南

一、解决来电筛选角色请求返回Canceled的问题

  1. 先检查是否已持有角色
    不要直接在OnCreate中发起请求,先判断当前应用是否已经拥有来电筛选角色,同时动态申请必要权限(Android 6.0+危险权限需手动授权):
public class MainActivity : MauiAppCompatActivity
{
    public static MainActivity ActivityCurrent { get; set; }
    private static int REQUEST_ROLE_ID = 1;
    private static int REQUEST_PERMISSION_ID = 2;

    public MainActivity()
    {
        ActivityCurrent = this;
    }
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        RoleManager roleManager = (RoleManager)GetSystemService(RoleService);
        
        if (!roleManager.IsRoleHeld(RoleManager.RoleCallScreening))
        {
            // 先申请必要的危险权限
            RequestPermissions(
                new string[] { Manifest.Permission.ReadPhoneState, Manifest.Permission.ReadCallLog }, 
                REQUEST_PERMISSION_ID);
        }
    }

    // 处理权限申请结果
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
    {
        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSION_ID)
        {
            bool allPermissionsGranted = true;
            foreach (var result in grantResults)
            {
                if (result != Permission.Granted)
                {
                    allPermissionsGranted = false;
                    break;
                }
            }
            if (allPermissionsGranted)
            {
                // 权限全部通过后发起角色请求
                RoleManager roleManager = (RoleManager)GetSystemService(RoleService);
                Intent intent = roleManager.CreateRequestRoleIntent(RoleManager.RoleCallScreening);
                StartActivityForResult(intent, REQUEST_ROLE_ID);
            }
        }
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_ROLE_ID)
        {
            if (resultCode == Result.Ok)
            {
                // 角色申请成功
            }
            else
            {
                // 若仍返回Canceled,需检查是否有其他应用已占据来电筛选角色
                // Android同一时间仅允许一个应用拥有该角色
            }
        }
    }
}
  1. 版本与系统限制
  • RoleManager.RoleCallScreening仅支持Android 10(API 29)及以上系统,若应用目标SDK低于29需改用旧版权限逻辑。
  • 若已有其他应用设置为默认来电筛选应用,你的请求会被系统拒绝,需引导用户到系统设置切换默认应用。

二、注册IncomingCallService服务

需在AndroidManifest.xml的<application>标签内添加服务声明,指定Intent过滤器和绑定权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:allowBackup="true" android:icon="@mipmap/appicon" 
        android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
        <!-- 注册来电筛选服务 -->
        <service android:name=".IncomingCallService"
            android:permission="android.permission.BIND_SCREENING_SERVICE">
            <intent-filter>
                <action android:name="android.telecom.CallScreeningService"/>
            </intent-filter>
        </service>
    </application>
    <!-- 保留原有权限声明 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.BIND_SCREENING_SERVICE" />
</manifest>

注:android:name=".IncomingCallService"中的.代表当前包名,若服务在子包下需填写完整类名(如com.yourapp.services.IncomingCallService)。

三、补充优化来电处理逻辑

在OnScreenCall方法中,必须调用RespondToCall告知系统处理结果,否则会导致来电无响应:

public class IncomingCallService : CallScreeningService
{
    public override void OnScreenCall(Call.Details callDetails)
    {
        // 获取来电号码
        var handle = callDetails.GetHandle();
        string phoneNumber = handle?.SchemeSpecificPart;

        // 必须响应来电,允许正常响铃
        CallResponse response = new CallResponse.Builder()
            .SetDisallowCall(false)
            .SetRejectCall(false)
            .Build();
        RespondToCall(callDetails, response);
    }
}

内容的提问来源于stack exchange,提问作者zvz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:12:28