In Android 7 (API level 24) my app is not allowed to mute phone (set ringer mode to silent)
Thanks for your answers, here is a little more detail.
To be able to set ringer mode to silent, you must ask permission to access notification policy (like @ucsunil said).
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
Then, check if you have this permission. If you do not, open the settings for "Do Not Disturb access" for your app:
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& !notificationManager.isNotificationPolicyAccessGranted()) {
Intent intent = new Intent(
android.provider.Settings
.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivity(intent);
}
When you run startActivity(), Android opens the Do Not Disturb access settings for your app.
What confused me, was that the way to ask for this permission is completely different from other permissions.
Just for reference, here is the way to ask for permission READ_CONTACTS:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& ActivityCompat.checkSelfPermission(activity,
Manifest.permission.READ_CONTACTS)
== PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(activity,
new String[]{ Manifest.permission.READ_CONTACTS },
REQUEST_CODE_READ_CONTACTS);
}
The access you are looking for is:
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
You need to request the user to provide you with this specific permission.
ACCESS_NOTIFICATION_POLICY is considered a "normal" permission which means you do NOT have to request permission at runtime. You only have to add the permission to AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
Then, to mute all notifications you can set the Interruption filter to INTERRUPTION_FILTER_NONE
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
previous_notification_interrupt_setting = notificationManager.getCurrentInterruptionFilter();
notificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);
}
INTERRUPTION_FILTER_ALARMS - Alarms only
INTERRUPTION_FILTER_ALL - Normal filter
INTERRUPTION_FILTER_NONE - No interruptions (MUTE)
INTERRUPTION_FILTER_PRIORITY - Priority interruptions
I use
int previous_notification_interrupt_setting = notificationManager.getCurrentInterruptionFilter();
to reset the filter later when onPause() or onStop()