【问题标题】:Understanding the Android 6 permission method了解Android 6权限方法
【发布时间】:2016-03-16 16:00:42
【问题描述】:

我正在尝试从图库中获取图像并将其设置为图像视图,但在 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;
}

现在我想获得getPermissionToReadExternalStorage() 方法的结果,这样我就可以为Android 6 启动用于挑选画廊的活动。如何获得void 类的结果? 另一件事是我是否必须为我的应用程序要求的每个权限编写方法?

【问题讨论】:

    标签: android android-6.0-marshmallow runtime-permissions


    【解决方案1】:

    编辑

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

    旧答案:

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

    通常我这样写代码:

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

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

    【讨论】:

    • 但是你如何使用它?或者当用户要点击某物时使用它??????所以授予许可你可以做你的任务。?在我的情况下你会如何使用它?或任何其他情况,只需向我展示带有侦听器之类的代码。
    【解决方案2】:

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

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

    public abstract class PermissionActivity extends AppCompatActivity {
    
        private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>();
    
        @SuppressWarnings("unused")
        public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) {
            requestPermissions(requestCode, requestPermissions, null, permissionListener);
        }
    
        @SuppressWarnings("unused")
        public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) {
            final int[] grantResults = new int[requestPermissions.length];
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                ArrayList<String> list_notGranted = new ArrayList<>();
    
                for (String requestPermission : requestPermissions)
                    if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED)
                        list_notGranted.add(requestPermission);
    
                if (list_notGranted.size() > 0) {
                    permissionListeners.add(permissionListener);
    
                    requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]);
    
                    if (message != null) {
                        boolean shouldShowRequestPermissionRationale = false;
    
                        for (String permission : requestPermissions)
                            if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
                                shouldShowRequestPermissionRationale = true;
                                break;
                            }
    
                        if (shouldShowRequestPermissionRationale) {
                            final String[] f_requestPermissions = requestPermissions;
    
                            AlertDialog.Builder builder = new AlertDialog.Builder(this);
    
                            builder.setMessage(message);
    
                            DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
    
                                @TargetApi(Build.VERSION_CODES.M)
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    switch (which) {
                                        case DialogInterface.BUTTON_POSITIVE:
                                            PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode);
                                            break;
                                        default:
                                            for (int i = 0; i < grantResults.length; i++)
                                                grantResults[i] = PackageManager.PERMISSION_DENIED;
    
                                            if (permissionListener != null)
                                                permissionListener.onResult(requestCode, f_requestPermissions, grantResults);
                                            break;
                                    }
                                }
                            };
    
                            builder.setPositiveButton("OK", onClickListener);
                            builder.setNegativeButton("Cancel", onClickListener);
    
                            builder.show();
                        } else {
                            super.requestPermissions(requestPermissions, requestCode);
                        }
                    } else {
                        super.requestPermissions(requestPermissions, requestCode);
                    }
                } else {
                    for (int i = 0; i < grantResults.length; i++)
                        grantResults[i] = PackageManager.PERMISSION_GRANTED;
    
                    if (permissionListener != null)
                        permissionListener.onResult(requestCode, requestPermissions, grantResults);
                }
            } else {
                if (permissionListener != null) {
                    for (int i = 0; i < grantResults.length; i++)
                        grantResults[i] = PackageManager.PERMISSION_GRANTED;
    
                    permissionListener.onResult(requestCode, requestPermissions, grantResults);
                }
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
            for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext(); ) {
                PermissionListener permissionListener = it.next();
                if (permissionListener.onResult(requestCode, permissions, grantResults)) {
                    it.remove();
                }
            }
        }
    
        public interface PermissionListener {
    
            boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults);
    
        }
    }
    

    如果你想从 Fragments 请求权限,添加这个类:

    public class PermissionFragment extends Fragment {
    
        @SuppressWarnings("unused")
        public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) {
            requestPermissions(requestCode, requestPermissions, null, permissionListener);
        }
    
        @SuppressWarnings("unused")
        public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) {
            ((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener);
        }
    }
    

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

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

    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 时,requestCode 正确时不要忘记return true,否则 PermissionListener 不会被移除从 ArrayList 中,你很可能会得到一个小的内存泄漏。

    【讨论】:

    • 谢谢老兄。我知道了。
    • 好主意!是否可以使用处理旧 android 版本的 ContextCompat 进行改进?谢谢!
    • 但是“permissionListeners.remove(permissionListener);”不会抛出 ConcurrentModificationException?
    • @Gilian 会的。从那时起,我对这段代码进行了很多改进。很快就会更新答案。
    • @geNia 不错的解决方案,我喜欢使用 shouldShowRequestPermissionRationale() 方法来使用消息,再次感谢!
    【解决方案3】:

    初始化您的权限

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

    对RequestPermissionsResult的权限更新权限和检查方法

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

    【讨论】:

      猜你喜欢
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 2016-11-12
      相关资源
      最近更新 更多