问题 WRITE_SETTINGS权限模糊


我正在为Android 6.0 Marshmallow构建我的应用程序,它需要 WRITE_SETTTINGS 允许。搜索后 从这里 我开始知道这称呼:

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

不会显示对话框权限。所以,基于 CommonsWare 解决方案,我们应该检查一下 Settings.System.canWrite() 返回true或false。所以,我应该调用Activity ACTION_MANAGE_WRITE_SETTINGS   作为行动。

但问题是,当我调用此活动时,它显示我的应用程序已通过该方法获得了权限 Settings.System.canWrite() 返回false。

我在这里遗漏了什么或者我必须禁用它然后再次启用它。


12628
2018-01-28 06:04


起源

在请求许可之前,您是否已经批准了权限。如果已经授予您,则无需再次申请授予许可。因为在棉花糖上用户可以通过设置手动控制拒绝权限。 - Avi
如果您需要代码如何检查已经授予的权限,我们可以提供。 - Avi
@Pankaj stackoverflow.com/a/32083622/1168654 CommonsWare他已解释如果Settings.System.canWrite()返回false然后启动活动ACTION_MANAGE_WRITE_SETTINGS然后用户必须允许 - Dhawal Sodha Parmar
System.canWrite()返回false但权限页面显示它已被授予@DhawalSodhaParmar - Pankaj


答案:


在我的Nexus 6上使用Android 6.0.1(MMB29S)这段代码:

if (!android.provider.Settings.System.canWrite(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
    intent.setData(Uri.parse("package:dummy"));
    startActivity(intent);
}

仅在打开“设置”时 允许修改系统设置 被设定为 。例如,在全新安装后首次启动( 不重新安装)

编辑(见评论): 某些设备可能会针对此代码进行窃听 canWrite() 总是回来 false,无论设置的价值如何。


6
2018-02-05 09:50



始终在第一次启动时返回false。 - Pankaj
嗨,你们有没有得出任何结论?我现在正在遇到同样的问题@Pankaj,canWrite()总是返回false,除了“ACTION_MANAGE_WRITE_SETTINGS”屏幕显示开关为ON。我找到的唯一解决方法是在交换机中单击两次,因此重置值并且canWrite()开始返回true,但这对于用户管理来说非常糟糕。 - Thomaz Freitas Barbosa
我得出了类似的结论,在Moto X 2nd Gen 6.0上,一切都很完美,但是Galaxy Note 5和Galaxy S6(均为6.0.1)正在重现这个问题。 - Thomaz Freitas Barbosa
三星默认启用写入系统设置,但在调用Settings.System.canWrite(this)时返回false。如果您再次禁用并启用该设置,则仅返回true。是的,另一个三星虫。 developer.samsung.com/forum/thread/... - Thiago
不正确的开关显示似乎是一个Android错误: code.google.com/p/android/issues/detail?id=204610 - mike47


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (Settings.System.canWrite(context)) {

            //Write code to feature for eg. set brightness or vibrate device 
           /* ContentResolver cResolver = context.getContentResolver();
            Settings.System.putInt(cResolver, Settings.System.SCREEN_BRIGHTNESS,brightness);*/
        }
        else {
            showBrightnessPermissionDialog(context);
        }

对话: -

 private  static  void showBrightnessPermissionDialog(final Context context) {

    final AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setCancelable(true);
    final AlertDialog alert = builder.create();
    builder.setMessage("Please give the permission to change brightness. \n Thanks ")
            .setCancelable(false)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
                    intent.setData(Uri.parse("package:" + context.getPackageName()));
                   // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intent);
                    alert.dismiss();
                }
            });
    alert.show();
}

例如。完整的亮度代码。

 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
 import android.provider.Settings;
 import android.support.v7.app.AlertDialog;

  public class BrightnessHelper {

  public static void  setBrightness(Context context, int brightness){

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (Settings.System.canWrite(context)) {

      //Write code to feature for eg. set brightness or vibrate device
            ContentResolver cResolver = context.getContentResolver();  Settings.System.putInt(cResolver,  Settings.System.SCREEN_BRIGHTNESS,brightness);
        }
        else {
            showBrightnessPermissionDialog(context);
        }
    }

}

public static int getBrightness(Context context) {
    ContentResolver cResolver = context.getContentResolver();
    try {
        return Settings.System.getInt(cResolver,  Settings.System.SCREEN_BRIGHTNESS);
    } catch (Settings.SettingNotFoundException e) {
        return 0;
    }
}

private  static  void showBrightnessPermissionDialog(final Context context) {

    final AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setCancelable(true);
    final AlertDialog alert = builder.create();
    builder.setMessage("Please give the permission to change brightness. \n Thanks ")
            .setCancelable(false)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
                    intent.setData(Uri.parse("package:" + context.getPackageName()));
                   // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(intent);
                    alert.dismiss();
                }
            });
    alert.show();
}

/ *     private boolean checkSystemWritePermission(Activity activity){         boolean retVal = true;         if(Build.VERSION.SDK_INT> = activity.Build.VERSION_CODES.M){             retVal = Settings.System.canWrite(activity.getApplicationContext());            // Log.d(标签,“可以写设置:”+ retVal);             如果(retVal的){                 Toast.makeText(活动,“允许写入:-)”,Toast.LENGTH_LONG)。show();             }其他{                 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));             }         }         返回retVal;     } * / }


3
2017-11-10 08:07





我在为Android 6开发时遇到了类似的问题。这是因为,现在开发人员必须在运行时请求权限。我的解决方案在这里 -

在onCreate中,显示权限对话框。让我们说这个方法的名字是 showPermissionsDialog()

//Global variable request code
private static final int WRITE_PERMISSION_REQUEST = 5000;

private void showPermissionsDialog() {
    if (Build.VERSION.SDK_INT == 23) {

      int hasWriteSettingsPermission = checkSelfPermission(Manifest.permission.WRITE_SETTINGS);
      if (hasWriteSettingsPermission != PackageManager.PERMISSION_GRANTED) {
        //You can skip the next if block. I use it to explain to user why I wan his permission.
        if (!ActivityCompat.shouldShowRequestPermissionRationale(HomeActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)) {
          showMessageOKCancel("You need to allow write settings",
              new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                  ActivityCompat.requestPermissions(HomeActivity.this, new String[]{Manifest.permission.WRITE_SETTINGS}, WRITE_PERMISSION_REQUEST);
                }
              });
          return;
        }
//The next line causes a dialog to popup, asking the user to allow or deny us write permission
        ActivityCompat.requestPermissions(HomeActivity.this, new String[]{Manifest.permission.WRITE_SETTINGS}, WRITE_PERMISSION_REQUEST);
        return;
      } else {
        //Permissions have already been granted. Do whatever you want :) 
      }
    }
}

//Now you only need this if you want to show the rationale behind  
//requesting the permission.      
    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
    new AlertDialog.Builder(HomeActivity.this).setMessage(message).setPositiveButton("OK", okListener)
        .setNegativeButton("Cancel", null).show();
  }

//This method is called immediately after the user makes his decision to either allow 
  // or disallow us permision.
  @Override
  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
      case WRITE_PERMISSION_REQUEST:
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
          //User pressed the allowed button
          //Do what you want :)
        } else {
          //User denied the permission
          //Come up with how to hand the requested permission
        }
      default:
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
  }

1
2018-01-30 19:40



我问的是Settings.System.canWrite()的错误行为的原因。 - Pankaj
如果用户已完成以下操作,请参阅用户不会显示对话框 - 1.已获准许您。 2.拒绝你的许可。但是,如果用户是第一次安装此应用程序,则会显示该用户。如果用户拒绝了您的许可,他仍然可以通过转到设置中的应用权限并选择相关权限来明确地将其提供给您。所以你可以打算去那边。我还没有探索意图部分,但我认为这是可能的。 - Vaibhav Sharma


事实证明,如果你有 CHANGE_NETWORK_STATE 在你的清单中声明,允许的切换 WRITE_SETTINGS 即使未授予权限,也将默认为on位置。你甚至不需要申报 WRITE_SETTINGS 遇到这个bug。


1
2017-12-02 10:58



错误报告在这里: code.google.com/p/android/issues/detail?id=204610 - mike47
谢谢。这应该是正确的答案。任何解决方法?我需要在我的应用中使用CHANGE_NETWORK_STATE吗?我可以在运行时询问它,以便开关显示正确的位置吗?所有这些东西对我的下载都很糟糕。如果未授予许可,应用程序甚至不会启动:-( - Ton
@Ton no CHANGE_NETWORK_STATE不需要运行时权限。它只需要在清单中声明 - Anish Bhandari


写下这个方法如下:

public void writePermission(){

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.System.canWrite(getApplicationContext())) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, 200);

        }
    }
}

然后在调用对话框之前调用方法(writePermission)

我希望这有帮助


1
2018-03-13 11:22