web-dev-qa-db-fra.com

Impossible d'obtenir l'autorisation WRITE_SETTINGS

Lorsque j'ai une API cible de 23 sur Android M Preview 3, il me semble impossible d'acquérir l'autorisation Manifest.permission.WRITE_SETTTINGS.

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

Demander la permission ne fait pas apparaître le dialogue auquel je m'attendrais, mais si je passe l'appel suivant sans cette permission,

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

L'appel sera sauf parce que je n'ai pas la permission.

Je ne suis pas sûr où aller d'ici. Existe-t-il une nouvelle API de sonnerie pour 23? Ou bien ce changement d'autorisation a-t-il simplement rendu impossible la modification de la sonnerie pour une application non-système?

74
Justin

Pour utiliser WRITE_SETTINGS, en fonction de la documentation:

  1. Avoir l’élément <uses-permission> dans le manifeste comme d’habitude.

  2. Appelez Settings.System.canWrite() pour voir si vous avez le droit d'écrire les paramètres.

  3. Si canWrite() retourne false, démarrez l'activité ACTION_MANAGE_WRITE_SETTINGS] afin que l'utilisateur puisse accepter de permettre à votre application d'écrire dans les paramètres.

En d'autres termes, l'écriture dans les paramètres est désormais un double opt-in (accepter d'installer, d'accord séparément dans Paramètres pour autoriser), semblable aux API d'administration de périphérique, aux services d'accessibilité, etc.

Notez également que je n’ai pas encore essayé de les utiliser - c’est basé sur recherche que j’ai faite hier sur Android 6.0 modifications .

114
CommonsWare

Outre la réponse de CommonsWare et le commentaire d’Ogix, voici un code factice:

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

Le fragment PopupwritePermission donne alors une fenêtre où la situation est expliquée. Un clic sur le bouton OK ouvre le Android System Menu où l'autorisation peut être accordée:

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

Les réponses précédentes sont excellentes, j’ai juste un petit ajout pour obtenir également le résultat obtenu avec la permission demandée.

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

Et puis dans la Activity:

@SuppressLint("NewApi")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == MainActivity.CODE_WRITE_SETTINGS_PERMISSION && Settings.System.canWrite(this)){
            Log.d("TAG", "MainActivity.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 == MainActivity.CODE_WRITE_SETTINGS_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //do your code
        }
    }
35
yshahak

Ceci est un exemple complet:

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);
    }
}
11
Daniel Raouf

À partir de Android Marshmellow, vous devez utiliser des autorisations d’exécution qui visent une sécurité accrue, ou les utiliser lorsque le besoin s’en fait documenatation

et pour les paramètres d'écriture, la documentation est ici

Dans manifeste ajouter

<uses-permission Android:name="Android.permission.WRITE_SETTINGS" />

Dans votre classe

private boolean checkSystemWritePermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if(Settings.System.canWrite(context))
            return true;
        else 
            openAndroidPermissionsMenu();
    }
    return false;
}

private void openAndroidPermissionsMenu() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
        intent.setData(Uri.parse("package:" + context.getPackageName()));
        context.startActivity(intent);
    }
}

Et l'utiliser comme ça

try {
       if (checkSystemWritePermission()) {
            RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, newUri);
            Toast.makeText(context, "Set as ringtoon successfully ", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(context, "Allow modify system settings ==> ON ", Toast.LENGTH_LONG).show();
            }
        } catch (Exception e) {
            Log.i("ringtoon",e.toString());
            Toast.makeText(context, "unable to set as Ringtoon ", Toast.LENGTH_SHORT).show();
        }
4
Abhishek Garg

La permission Android.permission.WRITE_SETTINGS est maintenant dans le groupe signature|appop|pre23|preinstalled comme Android.permission.CHANGE_NETWORK_STATE et Android.permission.SYSTEM_ALERT_WINDOW

Cela signifie que vous l'obtenez sur sdk 22 et inférieur. Sur la nouvelle version, vous devez être un opérateur d'application.

4
passsy

Mention ci-dessous permission dans AndroidManifest.xml

Dans Activité, utilisez ci-dessous si vous souhaitez modifier les paramètres.

if(Settings.System.canWrite(this)){
    // change setting here
}
else{
    //Migrate to Setting write permission screen. 
    Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
    intent.setData(Uri.parse("package:" + mContext.getPackageName()));
    startActivity(intent);
}
2
Sourabh Tejraj