En Android 7 (nivel de API 24), mi aplicación no puede silenciar el teléfono (configura el modo de timbre en silencio)

Tengo una aplicación que silencia el teléfono usando AudioManager y configurando el modo de timbre en silencio con este código:

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

Esto funciona con Android 6, pero ahora con Android 7, aparece el siguiente error:

 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) 

¿Hay algún permiso nuevo que deba solicitar para que esto funcione?

Miré a través de la lista de permisos de Android, pero no pude encontrar ninguno que pareciera relevante.

    Gracias por sus respuestas, aquí hay un poco más de detalle.

    Para poder establecer el modo de timbre en silencio, debe tener permiso para acceder a la política de notificación (como dijo @ucsunil).

    Primero revisa si tienes este permiso. Si no lo hace, abra la configuración para el acceso de No molestar para su aplicación:

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

    Cuando ejecuta startActivity (), Android abre la configuración de acceso de No molestar para su aplicación.

    Lo que me confundió fue que la forma de pedir este permiso es completamente diferente de otros permisos.

    Solo como referencia, aquí está la forma de pedir permiso. 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); } 

    El acceso que estás buscando es:

      

    Debe solicitar al usuario que le proporcione este permiso específico.

    ACCESS_NOTIFICATION_POLICY se considera un permiso “normal”, lo que significa que NO tiene que solicitar permiso en tiempo de ejecución. Solo debe agregar el permiso a AndroidManifest.xml

       

    Luego, para silenciar todas las notificaciones, puede configurar el filtro Interrupción en 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 – Solo alarmas
    INTERRUPTION_FILTER_ALL – Filtro normal
    INTERRUPTION_FILTER_NONE – Sin interrupciones (MUTE)
    INTERRUPTION_FILTER_PRIORITY – Interrupciones de prioridad

    yo suelo

      int previous_notification_interrupt_setting = notificationManager.getCurrentInterruptionFilter(); 

    reiniciar el filtro más tarde cuando onPause () o onStop ()

    Según la documentación de Android, debes otorgar acceso a No molestar.

    A partir de la N en adelante, no se permitirán los ajustes del modo de timbre que alternarán la función No molestar, a menos que a la aplicación se le haya otorgado acceso de no molestar. Ver isNotificationPolicyAccessGranted ().

    Por favor revise el enlace

    ¡Espero eso ayude!

    Resolví este problema abriendo el menú Configuración y solicitando permiso al usuario si api> 23.

    ¡Simplemente llame a requestMutePermissions () desde cualquier lugar y funcionará!

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