.NET MAUI实现CallScreeningService遇问题:角色请求失败及服务注册疑问
问题解决指南
一、解决来电筛选角色请求返回Canceled的问题
- 先检查是否已持有角色
不要直接在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同一时间仅允许一个应用拥有该角色 } } } }
- 版本与系统限制
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
相关产品推荐
相关产品推荐

