No se puede obtener el permiso de WRITE_SETTINGS

Cuando tengo una API de destino de 23 en Android M Preview 3, no puedo obtener el permiso Manifest.permission.WRITE_SETTTINGS.

requestPermissions(new String[]{Manifest.permission.WRITE_SETTINGS}, 101); 

El permiso de petición no abre el diálogo que esperaría, pero si hago la llamada siguiente sin este permiso,

  RingtoneManager.setActualDefaultRingtoneUri(activity, RingtoneManager.TYPE_RINGTONE, ringUri); 

La llamada será excepto porque no tengo el permiso.

No sé a dónde ir desde aquí. ¿Hay un nuevo tono API para 23? ¿O este cambio de permiso hizo imposible que cualquier aplicación que no sea del sistema cambiara el tono de llamada?

Para utilizar WRITE_SETTINGS , en función de los documentos:

  1. Tenga el elemento <uses-permission> en el manifiesto como normal.

  2. Call Settings.System.canWrite() para ver si es elegible para escribir configuraciones.

  3. Si canWrite() devuelve false , inicie la actividad ACTION_MANAGE_WRITE_SETTINGS para que el usuario pueda estar de acuerdo allí para permitir que su aplicación realmente escriba en la configuración.

IOW, escribir en configuración ahora es un doble opt-in (acepta instalar, accede por separado en Ajustes para permitir), similar a las API de administración de dispositivos, servicios de accesibilidad, etc.

También tenga en cuenta que no he intentado utilizar estos aún – esto se basa en la investigación que hice ayer en los cambios de Android 6.0 .

Como adición a la respuesta de CommonsWare, y el comentario de Ogix, aquí algunos código ficticio

 private boolean checkSystemWritePermission() { boolean retVal = true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { retVal = Settings.System.canWrite(this); Log.d(TAG, "Can Write Settings: " + retVal); if(retVal){ Toast.makeText(this, "Write allowed :-)", Toast.LENGTH_LONG).show(); }else{ Toast.makeText(this, "Write not allowed :-(", Toast.LENGTH_LONG).show(); FragmentManager fm = getFragmentManager(); PopupWritePermission dialogFragment = new PopupWritePermission(); dialogFragment.show(fm, getString(R.string.popup_writesettings_title)); } } return retVal; } 

El Fragmento PopupwritePermission entonces da una ventana donde se explica la situación. Un clic en el botón OK abrirá el menú del sistema Android donde se puede obtener el permiso:

 private void openAndroidPermissionsMenu() { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + getActivity().getPackageName())); startActivity(intent); } 

Las respuestas anteriores son geniales, tengo poca adición para también obtener el resultado de la solicitud de permiso.

  public static void youDesirePermissionCode(Activity context){ boolean permission; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { permission = Settings.System.canWrite(context); } else { permission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED; } if (permission) { //do your code } else { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + context.getPackageName())); context.startActivityForResult(intent, MainActivity.CODE_WRITE_SETTINGS_PERMISSION); } else { ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_SETTINGS}, MainActivity.CODE_WRITE_SETTINGS_PERMISSION); } } } 

Y luego en la Activity :

 @SuppressLint("NewApi") @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CODE_WRITE_SETTINGS_PERMISSION && Settings.System.canWrite(this)){ Log.d("TAG", "CODE_WRITE_SETTINGS_PERMISSION success"); //do your code } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == CODE_WRITE_SETTINGS_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //do your code } } 

El permiso android.permission.WRITE_SETTINGS ahora está en la signature|appop|pre23|preinstalled grupo signature|appop|pre23|preinstalled como android.permission.CHANGE_NETWORK_STATE y android.permission.SYSTEM_ALERT_WINDOW

Esto significa que usted lo consigue en sdk 22 y abajo. En la versión más reciente tiene que ser un operador de la aplicación.

Este es un ejemplo completo:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Settings.System.canWrite(context) { // Do stuff here } else { Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse(“package:” + getActivity().getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } 
  • ¿Cuánto tiempo tarda para que android pase al modo doze?
  • Android 6.0 no está autorizado a actualizar la red inalámbrica cuando se reinstala la aplicación
  • Ampliación de Byte a Int (bicho Marshmallow)
  • Detectar la aplicación actual en Android Nougat 7. + versión
  • ¿Está disponible para establecer checkSelfPermission en SDK mínimo <23?
  • checkSelfPermission devolviendo PERMISSION_GRANTED para el permiso revocado con targetSdkVersion <= 22
  • Error en la versión 6.0 de Android 6.0: EACCES (Permiso denegado)
  • Excepción de seguridad sólo en Android 6
  • Método FloatMath.sqrt () no encontrado
  • Android 6.0 maneja incorrectamente el método drawCircle
  • SMSMessage createFromPdu con formato de parámetro adicional
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.