安卓动态权限申请
安卓开发避不开的一个点就是权限申请,从以前的只需简单声明所用权限到Android M开始的动态权限申请,安卓变得更安全了,但是开发时候需要考虑的东西也就多了。关于动态权限申请,你可以借助一些第三方的库,使用很简单。当然,动态权限申请其实也不是什么复杂的过程,所以完全可以自己简单地实现。

本笔记主要介绍博主常用的处理方式,附带一个简单的demo,请求存储和相机权限。

下面进入正题。为了操作更直观更方便,首先新建一个工具类:PermissionCheck.java。里面封装了权限检查方法。代码如下:
package org.devsong.permissionrequest;

import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat;

public class PermissionCheck {

    private Context context;

    public PermissionCheck(Context context){
        this.context = context;
    }

    /**
     * 检查是否获取了所有权限
     * @param permissions :权限集合
     * @return :检查结果
     */
    public boolean hasPermissions(String...permissions){

        for(String permission : permissions){
            if(!isGrantedPermission(permission)){
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否获取权限
     * @param permission 权限
     * @return 
     */
    public boolean isGrantedPermission(String permission){
        return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 从请求结果中判断是否获取了所有权限
     * @param res 请求结果集合
     * @return
     */
    public boolean hasAllPermission(int[] res){
        for(int i : res){
            if(i == PackageManager.PERMISSION_DENIED){
                return false;
            }
        }
        return true;
    }

}


由于上述工具需要用到运行上下文,所以需要在activity里面初始化一下。下面是MainActivity的代码:
package org.devsong.permissionrequest;

import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private boolean isGotPermission = false;
    private PermissionCheck permissionCheck;
    private AlertDialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        permissionCheck = new PermissionCheck(getApplicationContext());  //初始化

    }

    /**
     * 结合 Activity 的生命周期来看,权限检查放到 onResume 里面是比较合适的
     * 因为在引导用户跳转到 App 详情页面后并不能保证用户一定会开启权限,所以当用户返回 App 时需要再次检查权限
     */
    @Override
    protected void onResume() {
        super.onResume();
        if (!isGotPermission && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !permissionCheck.hasPermissions(IConst.PERMISSION_ARR)) {
            if (!shouldAlertPermissionRequestDialog()) { //如果不需要弹出 自定义的引导开启权限窗口 则 用系统默认的处理方式(默认权限请求窗口)请求权限
                ActivityCompat.requestPermissions(this, IConst.PERMISSION_ARR, IConst.PERMISSION_REQUEST_CODE);
            } else if (dialog == null) { //否则如果没有弹出自定义的权限开启引导窗口 则 开启
                showPermissionReqDialog();
            }
        }
    }

    /**
     * 权限请求结果处理
     * @param requestCode 请求代号
     * @param permissions 权限数组
     * @param grantResults 请求结果
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == IConst.PERMISSION_REQUEST_CODE && permissionCheck.hasAllPermission(grantResults)) {
            Toast.makeText(getApplicationContext(), "获取权限成功", Toast.LENGTH_SHORT).show();
            isGotPermission = true;
        } else if (shouldAlertPermissionRequestDialog()) {  //如果没有请求成功,则弹出自定义的权限引导对话框,引导用户到设置里面开启权限
            showPermissionReqDialog();
        }
    }

    /**
     * 自定义的权限请求引导对话框
     */
    private void showPermissionReqDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("权限申请").setMessage("程序缺少必要权限,请打开点击\"设置\"->开启相关权限。");
        builder.setNegativeButton("退出", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                //如果用户点击退出,则表示用户不想授予必要权限,结束运行
                Toast.makeText(getApplicationContext(), "未获取权限,结束运行。", Toast.LENGTH_SHORT).show();
                finish();
            }
        });
        builder.setPositiveButton("设置", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                //若用户点击了设置,则跳转到app的详情页面
                startSetting();
            }
        });
        builder.setCancelable(false);
        dialog = builder.show();
    }

    /**
     * 跳转到软件详情页面
     */
    public void startSetting() {
        dialog.dismiss();  //关闭自定义的权限请求对话框
        dialog = null;
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse(IConst.PACKAGE_URL_SCHEME + getPackageName()));
        startActivity(intent);
    }

    /**
     * 判断是否应该弹出用户自定义对话框引导用户开启权限
     */
    public boolean shouldAlertPermissionRequestDialog() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            for (String permission : IConst.PERMISSION_ARR) {
                //shouldShowRequestPermissionRationale:默认返回false, 实测对应的权限点击了拒绝就会返回true,并不是网上描述的点击了不再提醒才返回true
                //可能是安卓太自由,定制化系统太多,产生了差异,不能说谁对谁错
                if (shouldShowRequestPermissionRationale(permission)) {
                    return true;
                }
            }
        }
        return false;
    }
}

最后是一些常量,单独放到一个类里面方便维护:IConst.java
package org.devsong.permissionrequest;

import android.Manifest;

public class IConst {

    //测试权限:存储、相机
    public static final String[] PERMISSION_ARR = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};

    public static final int PERMISSION_REQUEST_CODE = 1;

    public static final String PACKAGE_URL_SCHEME = "package:";

}

一些需要注意的地方代码里也做了说明。按照上面过程可以方便地完成动态权限的申请。下面是运行结果的展示。 文章正文图片

测试环境:原生安卓 6.0
It's
欢迎访问本站,欢迎留言、分享、点赞。愿您阅读愉快!
*转载请注明出处,严禁非法转载。
https://www.devsong.org
QQ留言 邮箱留言
头像
引用:
取消回复
提交
涂鸦
涂鸦
热门