Android request ACCESS_NOTIFICATION_POLICY and mute phone

我只是一个虾纸丫 提交于 2020-01-10 20:03:09

问题


I am a beginner Android developer and I have an interesting question at hand. I am trying to mute the phone with

AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);

But I am getting the following error

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

Now I do not understand this, as I am using EasyPermissions (https://github.com/googlesamples/easypermissions) and requesting the permission

Manifest.permission.ACCESS_NOTIFICATION_POLICY

But it does not ask me to allow anything on app startup. I figured this is because ACCESS_NOTIFICATION_POLICY is a non dangerous permission and thus granted at installation time, for which I also added it to my manifest.xml as thus

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

But it is still not working, my app is crashing because it throws the "Not allowed to change to Do Not Disturb state" error. Wierdly I found that I can request to go to the "Do Not Disturb access" screen with the following code

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

What am I doing wrong here? Why cannot I request this permissions as a normal permission? Do I really have to go through the intent to allow my app to mute the phone?


回答1:


From the 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.

From API level 23 and onward, you have to declare ACCESS_NOTIFICATION_POLICY permission in the manifest AND then the user needs to grant your app access to toggle Do Not Disturb. You can check if the access is granted with NotificationManager#isNotificationPolicyAccessGranted(). If your package do not have access, start an ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS intent so the user can give your app access.

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);
}



回答2:


I will post an answer on how I managed to solve this issue for androids over 23 and under 23 with a startActivityForResult callback

the requestMutePhonePermsAndMutePhone() function is called in the main actions onCreate function.

Mind you the code is very much intrusive, since the Settings menu is permacalled until you accept the Do Not Disturb permissions, but one can easily accomodate this code for their personal needs and maybe build a question prompt, etc...

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();
    }
}


来源:https://stackoverflow.com/questions/43123650/android-request-access-notification-policy-and-mute-phone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!