2016-08-25 8 views
19

У меня есть приложение, которое отключает телефон с помощью AudioManager и настраивает режим звонка, чтобы отключить этот код:В Android 7 (API-уровень 24) моему приложению запрещается отключать телефон (установить режим звонка в режим молчания)

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, но не нашел нужное.

ответ

29

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

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

Сначала проверьте, имеете ли вы это разрешение. Если вы этого не сделаете, откройте настройки Do Not Disturb доступа для приложения:

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

Не беспокоить доступ из SDK 23 Marshmallow. Итак, '> = Build.VERSION_CODES.M' BTW необходимо для' ' –

+2

Удивительно, как сложны простые вещи, как правило, с Android. Это решение, хотя .. – milosmns

+0

@RicardoPessoa: При запуске моего приложения на виртуальном телефоне с Android M (23) мне не нужно запрашивать разрешение «Не беспокоить», чтобы иметь возможность отключать звонки, только на Android N (24). –

1

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

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. See isNotificationPolicyAccessGranted().

Пожалуйста, проверьте link

Надеется, что это помогает!

5

Доступ вы ищете:

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

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

-1

@Bjarte, что происходит, потому что с уровня API 23 у вас есть права доступа во время выполнения. Как только эта NotifyPolicy была добавлена ​​в 23-м уровне api, вот почему вы должны реализовать по-другому.

пс: К сожалению, я не могу добавить это в качестве комментария:/

С уважением

2

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

+0

Спасибо, я попробую это, когда у меня будет такая возможность. Я думаю, что у меня уже был ACCESS_NOTIFICATION_POLICY в AndroidManifest.xml, когда я получил указанную ошибку, но я заметил, что я использую другой метод отключения уведомлений (audioManager.setRingerMode (AudioManager.RINGER_MODE_SILENT)), который может быть устаревшим. Я попробую использовать notificationManager вместо этого и посмотреть, будет ли он работать лучше. –

+0

Я, наконец, добрался до внедрения notificationManager.setInterruptionFilter() для Android версий M и далее. Благодаря! Из-за этого мне пришлось начать проверку isNotificationPolicyAccessGranted() также для Android M (а не только N, что я сказал в своем первоначальном ответе). –

0

Я решил эту проблему, открыв меню Настройка и просить пользователя предоставить разрешение на это, если ИЗА> 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(); 
    } 
}