Android 请求 ACCESS_NOTIFICATION_POLICY 并静音 phone

Android request ACCESS_NOTIFICATION_POLICY and mute phone

我是初学者 Android 开发人员,我手头有一个有趣的问题。我正在尝试使用

将 phone 静音
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);

但我收到以下错误

java.lang.SecurityException: Not allowed to change Do Not Disturb state

现在我不明白这一点,因为我正在使用 EasyPermissions (https://github.com/googlesamples/easypermissions) 并请求权限

Manifest.permission.ACCESS_NOTIFICATION_POLICY

但它不要求我在应用程序启动时允许任何内容。我想这是因为 ACCESS_NOTIFICATION_POLICY 是一个非危险权限,因此在安装时授予,为此我也将它添加到我的 manifest.xml 中,因此

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

但它仍然无法正常工作,我的应用程序崩溃了,因为它抛出了 "Not allowed to change to Do Not Disturb state" 错误。奇怪的是,我发现我可以使用以下代码请求转到 "Do Not Disturb access" 屏幕

Intent intent = new Intent(
                    android.provider.Settings
                            .ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
 startActivity(intent);

我在这里做错了什么?为什么我不能将此权限请求为普通权限?我真的必须完成允许我的应用静音 phone 的意图吗?

来自AudioManager#setRingerMode() reference

From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed unless the app has been granted Do Not Disturb Access.

从 API 级别 23 及以后,您必须在清单 AND 中声明 ACCESS_NOTIFICATION_POLICY 权限,然后用户需要授予您的应用访问权限切换请勿打扰。您可以使用 NotificationManager#isNotificationPolicyAccessGranted() 检查是否已授予访问权限。如果您的包没有访问权限,请启动 ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS 意图,以便用户可以授予您的应用访问权限。

NotificationManager n = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if(n.isNotificationPolicyAccessGranted()) {
  AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
  audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}else{
  // Ask the user to grant access
  Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
  startActivityForResult(intent);
}

我会post回答我是如何通过 startActivityForResult 回调为 23 岁以上和 23 岁以下的机器人解决这个问题的

requestMutePhonePermsAndMutePhone() 函数在主要操作 onCreate 函数中被调用。

请注意,该代码具有很强的侵入性,因为在您接受“请勿打扰”权限之前,“设置”菜单是永久调用的,但是人们可以轻松地根据个人需要容纳此代码,并可能构建问题提示等。 .

private void requestMutePhonePermsAndMutePhone() {
    try {
        if (Build.VERSION.SDK_INT < 23) {
            AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
            audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
        } else if( Build.VERSION.SDK_INT >= 23 ) {
            this.requestDoNotDisturbPermissionOrSetDoNotDisturbApi23AndUp();
        }
    } catch ( SecurityException e ) {

    }
}

private void requestDoNotDisturbPermissionOrSetDoNotDisturbApi23AndUp() {
    //TO SUPPRESS API ERROR MESSAGES IN THIS FUNCTION, since Ive no time to figrure our Android SDK suppress stuff
    if( Build.VERSION.SDK_INT < 23 ) {
        return;
    }

    NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
    if ( notificationManager.isNotificationPolicyAccessGranted()) {
        AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
        audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
    } else{
        // Ask the user to grant access
        Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
        startActivityForResult( intent, MainActivity.ON_DO_NOT_DISTURB_CALLBACK_CODE );
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Check which request we're responding to
    if (requestCode == MainActivity.ON_DO_NOT_DISTURB_CALLBACK_CODE ) {
        this.requestDoNotDisturbPermissionOrSetDoNotDisturbApi23AndUp();
    }
}