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

Android Oreo下代码挂断电话触发SecurityPermission异常问题

Android Oreo 下挂断电话权限问题的解决方案

这是个典型的Android版本权限收紧导致的问题,我来帮你梳理清楚原因和可行的解决办法:

问题根源

Android 8.0(Oreo,API 26)开始,Google对系统隐藏API的访问做了严格限制——哪怕你已经声明并获取了CALL_PHONE权限,通过反射调用ITelephony接口的endCall方法也会被系统拦截,直接抛出SecurityException。这是因为通话控制属于敏感系统操作,Google封闭了非官方的调用路径,低版本系统没有这个限制,所以你的代码在旧设备上能正常工作。

官方推荐的合法解决方案:使用AccessibilityService

辅助服务(AccessibilityService)是目前Oreo及以上版本中唯一可靠的挂断电话方式,它属于官方提供的系统交互接口,只要用户授权就能正常使用。具体实现步骤如下:

1. 创建AccessibilityService子类

public class CallBlockerAccessibilityService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        // 监听通话界面的窗口状态变化
        if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            String packageName = event.getPackageName().toString();
            // 匹配系统通话界面包名(不同厂商可能有差异,可根据需要调整)
            if (packageName.equals("com.android.incallui")) {
                // 执行挂断电话的系统全局操作
                performGlobalAction(GLOBAL_ACTION_CALL_END);
            }
        }
    }

    @Override
    public void onInterrupt() {
        // 空实现即可
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        // 配置服务监听参数
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
        setServiceInfo(info);
    }
}

2. 在Manifest中注册服务

<service
    android:name=".CallBlockerAccessibilityService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_service_config" />
</service>

3. 创建辅助服务配置文件

在res/xml目录下新建accessibility_service_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canPerformGestures="true"
    android:description="@string/accessibility_service_desc" />

然后在strings.xml中添加服务描述(用于系统设置中展示给用户):

<string name="accessibility_service_desc">该服务用于拦截并挂断不需要的来电,请开启权限以正常使用</string>

4. 引导用户开启辅助权限

辅助权限需要用户手动在系统设置中开启,你可以在应用启动时检查权限状态,未开启则引导用户跳转设置:

// 检查辅助服务是否已启用
private boolean isAccessibilityServiceEnabled() {
    int accessibilityEnabled = 0;
    final String service = getPackageName() + "/" + CallBlockerAccessibilityService.class.getCanonicalName();
    try {
        accessibilityEnabled = Settings.Secure.getInt(getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
    } catch (Settings.SettingNotFoundException e) {
        e.printStackTrace();
    }

    TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(':');
    if (accessibilityEnabled == 1) {
        String enabledServices = Settings.Secure.getString(getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
        if (enabledServices != null) {
            splitter.setString(enabledServices);
            while (splitter.hasNext()) {
                String serviceName = splitter.next();
                if (serviceName.equalsIgnoreCase(service)) {
                    return true;
                }
            }
        }
    }
    return false;
}

// 跳转到辅助服务设置页面
private void openAccessibilitySettings() {
    Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
    startActivity(intent);
}

注意事项

  • 辅助服务需要用户手动授权,你需要在应用中清晰告知用户开启权限的原因,避免用户产生不信任感;
  • 不同厂商的系统通话界面包名可能有差异(比如小米是com.android.incallui,华为可能是com.huawei.incallui),你可以根据需要扩展包名匹配逻辑;
  • 不要尝试使用模拟按键(如双击电源键)等非官方方式,这类方法在不同ROM中兼容性极差,且可能被系统限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:51:25