问题
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