理解android6权限方法

理解android6权限方法,android,android-6.0-marshmallow,runtime-permissions,Android,Android 6.0 Marshmallow,Runtime Permissions,我正在尝试从Gallery中获取图像并将其设置为imageview,但在Android 6中存在一些权限问题。下面是请求许可的方法。我应该请求读取外部存储还是写入外部存储 以下是我迄今为止所做的工作: private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1; public void getPermissionToReadExternalStorage() { if (ContextCompat.c

我正在尝试从Gallery中获取图像并将其设置为imageview,但在Android 6中存在一些权限问题。下面是请求许可的方法。我应该请求读取外部存储还是写入外部存储

以下是我迄今为止所做的工作:

    private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;


    public void getPermissionToReadExternalStorage() {

    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {

        if (shouldShowRequestPermissionRationale(
                Manifest.permission.READ_EXTERNAL_STORAGE)) {

            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    READ_CONTACTS_PERMISSIONS_REQUEST);
        }}}
    @Override
            public void onRequestPermissionsResult(int requestCode,
                                                   @NonNull String permissions[],
                                                   @NonNull int[] grantResults){
                // Make sure it's our original READ_CONTACTS request
                if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
                    if (grantResults.length == 1 &&
                            grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show();

                    } else {
                        Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                }
            }
现在,单击“我的侦听器”从库中拾取数据:

     pro.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            intent.setType("image/*");
            if (android.os.Build.VERSION.SDK_INT >= 23) {
                getPermissionToReadExternalStorage();
                if (getPermissionToReadExternalStorage () this???? <==)
                startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
            } else {
                startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
        }}

    });
    return v;
}
pro.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
Intent Intent=新Intent(Intent.ACTION\u PICK,android.provider.MediaStore.Images.Media.EXTERNAL\u CONTENT\u URI);
intent.setType(“image/*”);
如果(android.os.Build.VERSION.SDK_INT>=23){
GetPermissionToReaderExternalStorage();
如果(GetPermissionToReaderExternalStoreage(),则此???编辑

我已经重写了代码,并在另一个答案中发布

旧答案:

是的,你每次都必须检查并请求许可

通常我会这样编写代码:

private int requestPermissionCode;
private Runnable requestPermissionRunnable;

private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) {
    if (android.os.Build.VERSION.SDK_INT >= 23) {
        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            requestPermissionCode = requestCode;
            requestPermissionRunnable = codeToRun;

            requestPermissions(new String[]{requestPermission},
                    requestCode);
        }
    } else {
        codeToRun.run();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String permissions[],
                                       @NonNull int[] grantResults) {
    if (requestCode == requestPermissionCode) {
        if (grantResults.length == 1 &&
                grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            if (requestPermissionRunnable != null)
                requestPermissionRunnable.run();
        } else {
            Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
        }
    } else {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}
    runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() {

        @Override
        public void run() {
            // your code here
        }
    });
然后像这样运行它:

private int requestPermissionCode;
private Runnable requestPermissionRunnable;

private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) {
    if (android.os.Build.VERSION.SDK_INT >= 23) {
        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            requestPermissionCode = requestCode;
            requestPermissionRunnable = codeToRun;

            requestPermissions(new String[]{requestPermission},
                    requestCode);
        }
    } else {
        codeToRun.run();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String permissions[],
                                       @NonNull int[] grantResults) {
    if (requestCode == requestPermissionCode) {
        if (grantResults.length == 1 &&
                grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            if (requestPermissionRunnable != null)
                requestPermissionRunnable.run();
        } else {
            Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
        }
    } else {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}
    runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() {

        @Override
        public void run() {
            // your code here
        }
    });

我确信这不是一个最好的方法,但至少它提供了一个请求权限的可能性,并使操作更容易。

因此我完全重写了请求权限的代码。 现在,它支持请求多个权限并以正确的结果运行代码。 它也适用于PremarshAllow设备,因此在这种情况下,您不必检查和复制代码

首先,使用此代码创建一个Activity类(您可以扩展任何需要的活动,例如AppCompatActivity):

您的活动和片段应该扩展这些类,而不是标准类

现在,您可以通过调用以下方法请求权限:

requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)
如果应用程序需要权限才能工作,则应调用此方法并指定消息,说明为什么需要权限

requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)
不要错误调用默认方法,即

// DON'T USE THIS ONE!
requestPermissions(String[] requestPermissions, int requestCode)
// DON'T USE THIS ONE!
以下是请求联系人的示例:

private void requestAndLoadContacts() {
    String[] permissions = new String[]{Manifest.permission.READ_CONTACTS};

    requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() {

        @Override
        public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) {
            // Check if the requestCode is ours
            if (requestCode == REQUEST_PERMISSIONS_CONTACTS) {
                // Check if the permission is correct and is granted
                if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission granted
                    // Calling a method to actually load the contacts
                    loadContacts();
                } else {
                    // Permission not granted
                    Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show();
                }

                return true;
            }

            return false;
        }
    });
}
注:
在实现PermissionListener时,当请求代码正确时,不要忘记返回true,否则PermissionListener将不会从ArrayList中删除,并且很可能会出现小内存泄漏。

初始化您的权限

private static final int INITIAL_REQUEST = 1337;
private static final int GET_ACCOUNTS = INITIAL_REQUEST+2;
private static final int LOCATION_REQUEST =INITIAL_REQUEST+3;

private static final String[] INITIAL_PERMS = {
        Manifest.permission.GET_ACCOUNTS,
        Manifest.permission.INTERNET,
        Manifest.permission.ACCESS_FINE_LOCATION
};
检查设备并请求权限

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) {
            requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
        }
    }
是否授予检查权限

private boolean canAccessAccounts() {

    return (hasPermission(Manifest.permission.GET_ACCOUNTS));
}
private boolean canAccessLocation() {

    return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean canAccessInternet() {
    return (hasPermission(Manifest.permission.INTERNET));
}
private boolean hasPermission(String perm) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
    }
    return (true);
}
 void UpdatePermissions(){

    canAccessInternet();
    canAccessLocation();
    canAccessInternet();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    UpdatePermissions();
    switch(requestCode) {
        case GET_ACCOUNTS:
            if (canAccessAccounts()) {

            }
            else {

            }
            break;

        case LOCATION_REQUEST:
            if (canAccessLocation()) {

            }
            else {

            }
            break;

        case INITIAL_REQUEST:
            if(canAccessInternet()){

            }else {

            }
            break;

    }
}
在RequestPermissionsResult上更新权限并检查权限的方法

private boolean canAccessAccounts() {

    return (hasPermission(Manifest.permission.GET_ACCOUNTS));
}
private boolean canAccessLocation() {

    return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean canAccessInternet() {
    return (hasPermission(Manifest.permission.INTERNET));
}
private boolean hasPermission(String perm) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
    }
    return (true);
}
 void UpdatePermissions(){

    canAccessInternet();
    canAccessLocation();
    canAccessInternet();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    UpdatePermissions();
    switch(requestCode) {
        case GET_ACCOUNTS:
            if (canAccessAccounts()) {

            }
            else {

            }
            break;

        case LOCATION_REQUEST:
            if (canAccessLocation()) {

            }
            else {

            }
            break;

        case INITIAL_REQUEST:
            if(canAccessInternet()){

            }else {

            }
            break;

    }
}

但是你如何使用它?或者当用户要点击某个东西时你如何使用它?这样你就可以完成你的任务了。在我的情况下,你会如何使用它?或者任何其他情况下,只需向我展示带有侦听器的代码之类的东西。谢谢,伙计。我明白了。好主意!有可能改进使用处理旧android版本的ContextCompat吗?比谢谢!但是“permissionListeners.remove(permissionListener);”不会抛出ConcurrentModificationException吗?@Gilian会的。从那以后,我对这段代码做了很多改进。很快就会更新答案。@geNia很好的解决方案,我喜欢使用shouldShowRequestPermissionRegulation()方法来使用消息,再次感谢!