2018-03-14 动态权限获取(转)

转自:http://blog.csdn.net/yvan_z/article/details/54138477


以下是Android中的危险权限分为9组24种
2018-03-14 动态权限获取(转)_第1张图片
3780051-92dda32c577e32cb.png

下面我们来看如何动态获取权限!!!
先看最简单的,动态获取一个权限
比如现在要动态获取一个打电话的权限。。
首先需要在AndroidManifest.xml文件中写上这个权限


然后在Java代码进行动态获取
请求授权的代码

 /**
     * 请求授权
     */
    private void requestPermission(){
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){ //表示未授权时
            //进行授权
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},1);
        }else{
            //调用打电话的方法
            makeCall();
        }
    }

请求之后,我们需要重写onRequestPermissionsResult这个方法

/**
 * 权限申请返回结果
 * @param requestCode 请求码
 * @param permissions 权限数组
 * @param grantResults  申请结果数组,里面都是int类型的数
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case 1:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ //同意权限申请
                makeCall();
            }else { //拒绝权限申请
                Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show();
            }
            break;
        default:
            break;
    }
}


/**
 * 打电话方法
 */
private void makeCall(){
    try {
        Intent intent = new Intent(Intent.ACTION_CALL);
        intent.setData(Uri.parse("tel://123456789"));
        startActivity(intent);
    }catch (SecurityException e){
        e.printStackTrace();
    }
}

上面只是对一个权限进行授权,如果我们需要对多个权限进行授权呢?难道还是这样一个一个写吗?答案是否定的,我们看一下授权申请的方法

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},1);

我们注意到权限的参数是一个String类型的数组,这就说明我们可以直接把所有要授权的权限放在一个数组中,这样就可以对多个权限进行授权了
以打电话和SD卡权限为例

/**
 * 当有多个权限需要申请的时候
 * 这里以打电话和SD卡读写权限为例
 */
private void requestPermissions(){

    List permissionList = new ArrayList<>();
    if (ContextCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
        permissionList.add(Manifest.permission.CALL_PHONE);
    }

    if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
        permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    if (!permissionList.isEmpty()){  //申请的集合不为空时,表示有需要申请的权限
        ActivityCompat.requestPermissio8ns(this,permissionList.toArray(new String[permissionList.size()]),1);
    }else { //所有的权限都已经授权过了

    }
}

同样需要写onRequestPermissionsResult()方法,这里和单个权限申请的写法有一点区别

/**
 * 权限申请返回结果
 * @param requestCode 请求码
 * @param permissions 权限数组
 * @param grantResults  申请结果数组,里面都是int类型的数
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case 1:
            if (grantResults.length > 0){ //安全写法,如果小于0,肯定会出错了
                for (int i = 0; i < grantResults.length; i++) {

                    int grantResult = grantResults[i];
                    if (grantResult == PackageManager.PERMISSION_DENIED){ //这个是权限拒绝
                        String s = permissions[i];
                        Toast.makeText(this,s+"权限被拒绝了",Toast.LENGTH_SHORT).show();
                    }else{ //授权成功了
                        //do Something
                    }
                }
            }
            break;
        default:
            break;
    }
}

上面两种是单个和多个的权限申请,可是这还有一个问题,就是我们只能在当前类中使用。这个时候,我们需要想到一个封装,然后让所有的类都可以使用。
如何去封装呢? 我们在开发一个项目的时候,都会打一个框架,这里面可定会有各种各样的基类,这个时候我们就可以把权限的申请放在BaseActivity中,然后各个子Activity去继承BaseActivity。
然后通过接口回调的方式把授权结果传给子Activity。
下面来看代码:
首先是定义的接口

/**
 * Created by 11213 on 2017/1/4.
 * 权限回调接口
 */

public interface PermissionListener {

    //授权成功
    void onGranted();

    //授权部分
    void onGranted(List grantedPermission);

    //拒绝授权
    void onDenied(List deniedPermission);
}

BaseActivity的代码

public class BaseActivity1 extends AppCompatActivity {
    private PermissionListener mlistener;

    /**
     * 权限申请
     * @param permissions 待申请的权限集合
     * @param listener  申请结果监听事件
     */
    protected void requestRunTimePermission(String[] permissions,PermissionListener listener){
        this.mlistener = listener;

        //用于存放为授权的权限
        List permissionList = new ArrayList<>();
        //遍历传递过来的权限集合
        for (String permission : permissions) {
            //判断是否已经授权
            if (ContextCompat.checkSelfPermission(this,permission) != PackageManager.PERMISSION_GRANTED){
                //未授权,则加入待授权的权限集合中
                permissionList.add(permission);
            }
        }

        //判断集合
        if (!permissionList.isEmpty()){  //如果集合不为空,则需要去授权
            ActivityCompat.requestPermissions(this,permissionList.toArray(new String[permissionList.size()]),1);
        }else{  //为空,则已经全部授权
            listener.onGranted();
        }
    }



    /**
     * 权限申请结果
     * @param requestCode  请求码
     * @param permissions  所有的权限集合
     * @param grantResults 授权结果集合
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0){
                    //被用户拒绝的权限集合
                    List deniedPermissions = new ArrayList<>();
                    //用户通过的权限集合
                    List grantedPermissions = new ArrayList<>();
                    for (int i = 0; i < grantResults.length; i++) {
                        //获取授权结果,这是一个int类型的值
                        int grantResult = grantResults[i];

                        if (grantResult != PackageManager.PERMISSION_GRANTED){ //用户拒绝授权的权限
                            String permission = permissions[i];
                            deniedPermissions.add(permission);
                        }else{  //用户同意的权限
                            String permission = permissions[i];
                            grantedPermissions.add(permission);
                        }
                    }

                    if (deniedPermissions.isEmpty()){  //用户拒绝权限为空
                        mlistener.onGranted();
                    }else {  //不为空
                        //回调授权成功的接口
                        mlistener.onDenied(deniedPermissions);
                        //回调授权失败的接口
                        mlistener.onGranted(grantedPermissions);
                    }
                }
                break;
            default:
                break;
        }
    }
}

子Activity中进行调用

private void requestPermission(){
    requestRunTimePermission(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE}
            , new PermissionListener() {
                @Override
                public void onGranted() {  //所有权限授权成功
                }
                @Override
                public void onGranted(List grantedPermission) { //授权失败权限集合
                }
                @Override
                public void onDenied(List deniedPermission) { //授权成功权限集合
                }
            });
}

上面的代码注释很详细,就不再解释了
上面的封装,只能用在Activity中,如果要用在非Activity中(在v4包下的Fragment也可以进行授权),比如工具类中使用时,上面的就不适用了,因为我们看到,申请权限的方法必须传递一个Activity对象,为Activity又不可以new。这个时候,我们要想到,Activity管理栈。
代码如下:
接口还是上面的接口。。。
Activity管理栈

/**
 * Created by 11213 on 2017/1/5.
 * Activity管理类
 */

public class ActivityCollector {

    private static List activityList = new ArrayList<>();

    /** 添加一个Activity到集合中*/
    public static void addActivity(Activity activity){
        activityList.add(activity);
    }

    /** 从集合中删除一个Activity*/
    public static void removeActivity(Activity activity){
        activityList.remove(activity);
    }

    /**获取Activity栈中的栈顶的Activity
     * 需要注意的是,栈是先进后出,所以最上面的Activity是集合中的最后一个*/
    public static Activity getTopActivity(){
        if (activityList.isEmpty()){  //Activity栈为空
            return null;
        }else {  //不为空时
            return activityList.get(activityList.size() - 1);
        }
    }
}

BaseActivity的代码

public class BaseActivity extends AppCompatActivity {
    private static PermissionListener mlistener;
    /**
     * 创建Activity时加到管理栈中
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }
    /**
     * 销毁时从Activity管理栈中移除
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }
    /**
     * 权限申请
     * @param permissions 待申请的权限集合
     * @param listener  申请结果监听事件
     */
    protected static void requestRunTimePermission(String[] permissions,PermissionListener listener){
        mlistener = listener;
        Activity topActivity = ActivityCollector.getTopActivity();
        if (topActivity == null){
            return;
        }
        //用于存放为授权的权限
        List permissionList = new ArrayList<>();
        //遍历传递过来的权限集合
        for (String permission : permissions) {
            //判断是否已经授权
            if (ContextCompat.checkSelfPermission(topActivity,permission) != PackageManager.PERMISSION_GRANTED){
                //未授权,则加入待授权的权限集合中
                permissionList.add(permission);
            }
        }
        //判断集合
        if (!permissionList.isEmpty()){  //如果集合不为空,则需要去授权
            ActivityCompat.requestPermissions(topActivity,permissionList.toArray(new String[permissionList.size()]),1);
        }else{  //为空,则已经全部授权
            listener.onGranted();
        }
    }
    /**
     * 权限申请结果
     * @param requestCode  请求码
     * @param permissions  所有的权限集合
     * @param grantResults 授权结果集合
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0){
                    //被用户拒绝的权限集合
                    List deniedPermissions = new ArrayList<>();
                    //用户通过的权限集合
                    List grantedPermissions = new ArrayList<>();
                    for (int i = 0; i < grantResults.length; i++) {
                        //获取授权结果,这是一个int类型的值
                        int grantResult = grantResults[i];

                        if (grantResult != PackageManager.PERMISSION_GRANTED){ //用户拒绝授权的权限
                            String permission = permissions[i];
                            deniedPermissions.add(permission);
                        }else{  //用户同意的权限
                            String permission = permissions[i];
                            grantedPermissions.add(permission);
                        }
                    }

                    if (deniedPermissions.isEmpty()){  //用户拒绝权限为空
                        mlistener.onGranted();
                    }else {  //不为空
                        //回调授权成功的接口
                        mlistener.onDenied(deniedPermissions);
                        //回调授权失败的接口
                        mlistener.onGranted(grantedPermissions);
                    }
                }
                break;
            default:
                break;
        }
    }
}

调用方法

public class Util {
    private void requestPermission(){
        BaseActivity.requestRunTimePermission(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.WRITE_EXTERNAL_STORAGE}
                , new PermissionListener() {
                    @Override
                    public void onGranted() {
                    }
                    @Override
                    public void onGranted(List grantedPermission) {
                    }
                    @Override
                    public void onDenied(List deniedPermission) {
                    }
                });
    }
}

后边的这些代码的注释写的很详细,大家都可以看明白。这些可以直接封装到自己的项目中,另外还有一些其他的封装思路,比如郭神说的使用一个透明的Activity。当然我们也可以使用第三方库。

你可能感兴趣的:(2018-03-14 动态权限获取(转))