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

Android M设备出现READ_PHONE_STATE权限异常问题求助

解决Android M上READ_PHONE_STATE权限被拒绝的问题

看了你的问题和代码,核心问题出在权限请求的时机不对,加上你的权限处理代码有冗余逻辑,导致AirWatch的AirWatchSDKContextService这个IntentService在权限还没被授予时就启动运行,进而触发了SecurityException。下面一步步给你解决:

第一步:确认Manifest已声明权限

虽然你没贴Manifest代码,但必须确保已经添加这个权限声明,否则运行时请求也无效:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

第二步:修复运行时权限处理代码

你的代码存在重复请求权限的问题(checkAndRequestForPermission已经包含READ_PHONE_STATE的请求,却又调用getReadPhoneAccess再次请求),而且onRequestPermissionsResult里的递归调用会导致无限循环。这里给你优化成简洁可靠的版本:

优化后的权限检查与请求代码

private static final int MY_PERMISSIONS_REQUEST_ALL = 1001;

private void checkAndRequestForPermission() {
    // 整理所有需要的权限数组
    String[] requiredPermissions = {
        Manifest.permission.READ_CALENDAR,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.CALL_PHONE,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.READ_PHONE_STATE
    };

    // 收集未授予的权限
    List<String> permissionsToRequest = new ArrayList<>();
    for (String perm : requiredPermissions) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            permissionsToRequest.add(perm);
        }
    }

    if (!permissionsToRequest.isEmpty()) {
        // 只请求未授予的权限
        ActivityCompat.requestPermissions(this, 
            permissionsToRequest.toArray(new String[0]), 
            MY_PERMISSIONS_REQUEST_ALL);
    } else {
        // 所有权限都已授予,现在初始化AirWatch SDK/启动对应服务
        startAirWatchService();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_PERMISSIONS_REQUEST_ALL) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }

        if (allGranted) {
            // 权限全部授予,启动AirWatch服务
            startAirWatchService();
        } else {
            // 有权限被拒绝,提示用户去设置开启权限
            Toast.makeText(this, "需要开启必要权限才能使用应用", Toast.LENGTH_LONG).show();
            // 可选:引导用户到应用设置页面
            // Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
            // startActivity(intent);
        }
    }
}

// 封装启动AirWatch服务的方法,确保仅在权限授予后调用
private void startAirWatchService() {
    Intent serviceIntent = new Intent(this, AirWatchSDKContextService.class);
    startService(serviceIntent);
    // 若是AirWatch SDK初始化逻辑,也放在这里执行
}

第三步:确保权限授予后再启动AirWatch服务

这是关键:AirWatchSDKContextService是IntentService,它无法弹出权限请求对话框(只有Activity能弹出),所以绝对不能在权限未确认授予前启动这个服务。

把原来直接启动AirWatch服务的代码,全部移到startAirWatchService方法中,仅当checkAndRequestForPermission确认所有权限都授予后,才调用这个方法。比如原来在onCreate里直接启动服务,现在改成:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    // 先检查权限,而非直接启动服务
    checkAndRequestForPermission();
}

第四步:处理用户拒绝权限的情况

如果用户拒绝了READ_PHONE_STATE这类核心权限,应用无法正常使用AirWatch SDK,需要友好提示用户,引导他们到应用设置页面手动开启权限。

原代码出错的原因

  1. 重复请求权限:两次请求READ_PHONE_STATE导致权限流程混乱;
  2. 服务启动时机过早:AirWatch服务在权限未被用户授予时就运行,调用getDeviceId()触发异常;
  3. 递归调用的问题:onRequestPermissionsResult里的递归会导致无限弹出权限对话框,既解决不了问题还影响体验。

按照上面的步骤修改后,就能确保只有当所有必要权限都被授予后,AirWatch服务才会启动,也就不会再触发这个权限错误了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:21:26