Android Can';无法获得写入设置权限

Android Can';无法获得写入设置权限,android,android-6.0-marshmallow,Android,Android 6.0 Marshmallow,当我在Android M Preview 3上的目标API为23时,我似乎无法获得Manifest.permission.WRITE_SETTTINGS权限 requestPermissions(new String[]{Manifest.permission.WRITE_SETTINGS}, 101); Request permission不会显示我期望的对话框,但是如果我在没有此权限的情况下进行以下调用 RingtoneManager.setActualDefaultRingtoneUr

当我在Android M Preview 3上的目标API为23时,我似乎无法获得Manifest.permission.WRITE_SETTTINGS权限

requestPermissions(new String[]{Manifest.permission.WRITE_SETTINGS}, 101);
Request permission不会显示我期望的对话框,但是如果我在没有此权限的情况下进行以下调用

 RingtoneManager.setActualDefaultRingtoneUri(activity, RingtoneManager.TYPE_RINGTONE, ringUri);
除非我没有权限,否则电话将被取消

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

我不知道接下来该怎么办。23有新的铃声API吗?或者此权限更改是否使任何非系统应用程序无法更改铃声?

根据文档使用
写入设置

  • 让清单中的
    元素正常运行

  • 查看您是否有资格写出设置

  • 如果
    canWrite()
    返回
    false
    ,请启动,以便用户同意允许您的应用程序实际写入设置

  • 换句话说,写入设置现在是一种双重选择(同意安装,在设置中单独同意以允许),类似于设备管理API、辅助功能服务等


    还要注意的是,我还没有尝试使用这些功能-这是基于。

    权限
    android.permission.WRITE\u SETTINGS
    现在位于组
    signature | appop | pre23 |预安装的
    android.permission.CHANGE\u NETWORK\u STATE
    android.permission.SYSTEM\u ALERT\u WINDOW


    这意味着您可以在sdk 22及以下版本上获得它。在较新版本中,您必须是一名应用程序操作员。

    除了Commonware的答案和Ogix的评论外,以下是一些伪代码:

    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;
    }
    
    然后,片段PopupwritePermission提供了一个窗口来解释情况。单击OK按钮将打开Android系统菜单,在该菜单中可以授予权限:

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

    前面的答案很好,我只需要添加一点内容就可以得到请求许可的结果

     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);
                }
            }
        }
    
    然后在
    活动中

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

    这是一个完整的示例:

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

    在AndroidManifest.xml中提及以下权限

    在活动中,请使用下面的if-else更改设置

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

    从android Marshmellow开始,您需要使用运行时权限以提高安全性,或者在需要时使用权限

    而对于写入设置文档

    在舱单中添加

    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    
    像这样使用它

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

    我用过贝娄式的

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            boolean retVal = true;
            retVal = Settings.System.canWrite(this);
            if (retVal == false) {
                if (!Settings.System.canWrite(getApplicationContext())) {
    
                    Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
                    Toast.makeText(getApplicationContext(), "Please, allow system settings for automatic logout ", Toast.LENGTH_LONG).show();
                    startActivityForResult(intent, 200);
                }
            }else {
                Toast.makeText(getApplicationContext(), "You are not allowed to wright ", Toast.LENGTH_LONG).show();
            }
        }
    
    明示许可

    <uses-permission  android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions" />
    
    
    
    Kotlin版本,步骤简单
    遵循以下步骤:

    1.
    manifest.xml中添加权限的用法元素通常:

    
    
    2.如果要更改设置,请检查写访问:

    if(context.canWriteSettings){
    //在此处更改设置。。。
    }否则{
    startManageWriteSettingsPermission()的启动管理
    }
    
    3.在请求许可时,还应添加以下代码行:

    private fun startManageWriteSettingsPermission(){
    if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.M){
    意图(
    Settings.ACTION\u MANAGE\u WRITE\u设置,
    parse(“包:${context.packageName}”)
    ).让{
    startActivityForResult(it、请求\代码\写入\设置\权限)
    }
    }
    }
    重写activityResult(请求代码:Int,结果代码:Int,数据:Intent?){
    super.onActivityResult(请求代码、结果代码、数据)
    何时(请求代码){
    请求\代码\写入\设置\权限->{
    if(context.canWriteSettings){
    //在此处更改设置。。。
    }否则{
    Toast.makeText(上下文,“未授予写入设置权限!”,Toast.LENGTH\u SHORT.show()
    }
    }
    }
    }
    val Context.canWriteSettings:布尔值
    get()=Build.VERSION.SDK_INT
    谢谢马克!工作得很有魅力。如果我们将有多种新方法来请求权限,则需要进行一些更新。(我在发布之前已经读过你的博客,但显然在我需要的时候没有保留那条信息)这确实有效。但对于最终用户来说,这是一个糟糕的方法。谷歌有没有改变这种行为的迹象?@Fhl:我不知道他们为什么选择这条路线,而不是在安卓6.0中使用常规的
    危险的
    运行时权限方法。如果这种情况很快发生变化,我会感到惊讶。您可以在intent中指定应用程序,如下所示:
    intent.setData(Uri.parse(“package:+Context.getPackageName())另一件需要注意的事情是,Android中似乎存在一个bug,导致以前安装的应用程序在上面描述的对话框中用户授予了写入权限,其中切换开关将置于启用位置,而canWrite返回false。。为了让canWrite()方法返回true,用户必须关闭并重新打开开关。。。我在开发中看到了这一点,但希望它不会成为客户看到的东西。我输入了您的代码,它运行良好,即使授予了权限,但自定义铃声仍然没有分配,并且仍然存在写入设置权限被拒绝的问题。ActivityCompat.requestPermissions(上下文,新字符串[]{Manifest.permission.Write_SETTINGS},…);不能使用。这是特别许可。我们只能以文件中所述的意图请求此许可。同样在Marshmello之前,安装时永久授予许可time@yshahak你的变量
    MainActivity.code\u WRITE\u SETTINGS\u PERMISSION
    是什么?@BrunoBieri是的,你说得对,我忽略了这个。我将编辑我的答案,使其更加详细。那么什么是
    MainActivity.code\u WRITE\u SETTINGS\u PERMISSION
    ?intent.setData(Uri.parse(“包:”+getActivity().getPackageName());请使用此权限。