В Android 7 (уровень API 24) моему приложению не разрешено отключать звук телефона (установите беззвучный режим звонка)

У меня есть приложение, которое отключает звук телефона с помощью AudioManager и отключает режим звонка с помощью этого кода:

AudioManager audioManager = 
    (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
try {
    audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT)
} catch (Exception e) {
    e.printStackTrace();
}

Это работает с Android 6, но теперь с Android 7 я получаю следующую ошибку:

System.err: java.lang.SecurityException: Not allowed to change Do Not Disturb state
System.err: at android.os.Parcel.readException(Parcel.java:1683)
System.err: at android.os.Parcel.readException(Parcel.java:1636)
System.err: at android.media.IAudioService$Stub$Proxy.setRingerModeExternal(IAudioService.java:962)
System.err: at android.media.AudioManager.setRingerMode(AudioManager.java:1022)
System.err: at controllers.SearchResultController.mutePhone(SearchResultController.java:185)

Есть ли какие-либо новые разрешения, которые мне нужно запросить, чтобы это сработало?

Я просмотрел список разрешений Android, но не смог найти ничего подходящего.


person Bjarte Aune Olsen    schedule 25.08.2016    source источник


Ответы (7)


Спасибо за ваши ответы, вот немного подробнее.

Чтобы иметь возможность установить беззвучный режим звонка, вы должны запросить разрешение на доступ к политике уведомлений (как сказал @ucsunil).

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

Затем проверьте, есть ли у вас это разрешение. Если вы этого не сделаете, откройте настройки «Доступ в режиме «Не беспокоить»» для вашего приложения:

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

Когда вы запускаете startActivity(), Android открывает настройки доступа «Не беспокоить» для вашего приложения.

Что меня смутило, так это то, что способ запроса этого разрешения полностью отличается от других разрешений.

Просто для справки, вот как запросить разрешение 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);
}
person Bjarte Aune Olsen    schedule 25.08.2016
comment
Доступ к режиму «Не беспокоить» предоставляется из SDK 23 Marshmallow. Итак, >= Build.VERSION_CODES.M BTW необходимо для <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" /> - person Ricardo Pessoa; 07.11.2016
comment
Удивительно, насколько сложными становятся простые вещи с Android. Хотя это решение.. - person milosmns; 23.08.2017
comment
@RicardoPessoa: при запуске моего приложения на виртуальном телефоне с Android M (23) мне не нужно запрашивать разрешение «Не беспокоить», чтобы отключить звук звонка, только на Android N (24). - person Bjarte Aune Olsen; 30.11.2017
comment
@RicardoPessoa: Извините, моя ошибка. Когда вы отключаете звук телефона с помощью audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); вам не нужно это разрешение в Android M, но когда вы отключаете звук телефона с помощьюnotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE);, который работает в Android M и далее, вам необходимо запросить это разрешение. Обновил мой ответ выше. - person Bjarte Aune Olsen; 30.11.2017
comment
В моем случае мой телефон никогда не беспокоился об этом, но в какой-то момент он начал выдавать это исключение. это было очень странно, но я рад узнать, что другие нашли это решение - person Juan Mendez; 03.02.2018

Доступ, который вы ищете, это:

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

Вам нужно попросить пользователя предоставить вам это конкретное разрешение.

person ucsunil    schedule 25.08.2016

ACCESS_NOTIFICATION_POLICY считается «нормальным» разрешением, что означает, что вам НЕ нужно запрашивать разрешение во время выполнения. Вам нужно только добавить разрешение в AndroidManifest.xml

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

Затем, чтобы отключить все уведомления, вы можете установить фильтр прерывания на 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 – только будильники
INTERRUPTION_FILTER_ALL – обычный фильтр
INTERRUPTION_FILTER_NONE – без прерываний (MUTE)
INTERRUPTION_FILTER_PRIORITY – приоритетные прерывания

я использую

 int previous_notification_interrupt_setting = notificationManager.getCurrentInterruptionFilter();

сбросить фильтр позже, когда onPause() или onStop()

person Winston Brown    schedule 08.10.2016
comment
Спасибо, я попробую это, когда у меня будет возможность. Я думаю, что у меня уже была ACCESS_NOTIFICATION_POLICY в AndroidManifest.xml, когда я получил упомянутую ошибку, но я заметил, что использую другой метод для отключения уведомлений (audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT)), который может быть устаревшим. Вместо этого я попробую использовать notificationManager и посмотрю, работает ли он лучше. - person Bjarte Aune Olsen; 08.10.2016
comment
Наконец-то я добрался до реализации notificationManager.setInterruptionFilter() для версий Android M и выше. Спасибо! Из-за этого мне пришлось начать проверку isNotificationPolicyAccessGranted() также для Android M (а не только N, как я указал в своем первоначальном ответе). - person Bjarte Aune Olsen; 30.11.2017

Я решил эту проблему, открыв меню «Настройки» и попросив пользователя предоставить разрешение на это, если API> 23.

Просто вызовите requestMutePermissions() из любого места, и все заработает!

private void requestMutePermissions() {
    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.requestForDoNotDisturbPermissionOrSetDoNotDisturbForApi23AndUp();
        }
    } catch ( SecurityException e ) {

    }
}

private void requestForDoNotDisturbPermissionOrSetDoNotDisturbForApi23AndUp() {

    NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
    // if user granted access else ask for permission
    if ( notificationManager.isNotificationPolicyAccessGranted()) {
        AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
        audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
    } else{
        // Open Setting screen to ask for permisssion
        Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
        startActivityForResult( intent, 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 == ON_DO_NOT_DISTURB_CALLBACK_CODE ) {
        this.requestForDoNotDisturbPermissionOrSetDoNotDisturbForApi23AndUp();
    }
}
person Waqar UlHaq    schedule 20.02.2018
comment
Есть ли способ направить пользователя непосредственно к действию для вашего приложения, а не к действию для всех приложений? Я хотел бы уменьшить количество шагов, которые должны предпринять наши пользователи, чтобы включить разрешение. - person TALE; 01.09.2020

Согласно документации Android, вы должны предоставить доступ к режиму «Не беспокоить».

Начиная с N, настройки режима звонка, которые будут переключать режим «Не беспокоить», не разрешены, если приложению не предоставлен доступ «Не беспокоить». См. isNotificationPolicyAccessGranted().

Перейдите по ссылке.

Надеюсь, поможет!

person Lucas Santos    schedule 25.08.2016

Hy, если кому-то нужно это разрешение в Котлине, вот вам

var notificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && !notificationManager.isNotificationPolicyAccessGranted
    ) {
        val intent = Intent(
            Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS
        )
        startActivity(intent)
    }

Я очень ценю ваши советы, которые спасли жизнь! :D

person Botond Németh    schedule 18.05.2021

Я столкнулся с этой проблемой только в эмуляторе. Когда я запускаю приложение на своем мобильном телефоне, оно никогда не приходит и работает, как и ожидалось.

person UzumakiL    schedule 05.02.2020