安卓6.0以上动态权限申请

没啥技术含量,代码可以直接粘走使用

从安卓6.0(api23)开始,权限声明不仅需要在manifest中添加权限声明,还需要在JAVA代码中再次申请一遍,但是权限申请的结果是在onRequestPermissionsResult中回调的,当拿到回调结果后,还需要再判断用户是否勾选了“不再提示”选项,如果再次申请,会出现很多重复代码,因此,把权限申请放在baseActivity里面,我们在使用的时候,一个方法即可搞定,具体代码如下:

public class BaseActivity extends AppCompatActivity {

    private String mReason;
    private int mPermissionCode;
    private String mPermission;
    private PermissionCallback mCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    // 提供给子类调用的权限申请接口
    @TargetApi(23)
    protected void requestPermissionWithReason(String permission, String reason, 
                                               int permissionCode, PermissionCallback callback) {
        mReason = reason;
        mCallback = callback;
        mPermission = permission;
        mPermissionCode = permissionCode;
        // 检查自身是否有此权限
        if (PackageManager.PERMISSION_DENIED == checkSelfPermission(permission)) {
            // 如果没有,就去申请权限
            requestPermissions(new String[]{permission}, mPermissionCode);
        } else {
            // 如果有,则调用callback
            callback.onPermissionResult(true, mPermissionCode);
        }
    }

    // 系统回调的permission结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == mPermissionCode 
                && grantResults[0] != PackageManager.PERMISSION_DENIED) {
            // 权限申请成功
            mCallback.onPermissionResult(true, mPermissionCode);
        } else {
            // 权限申请失败时,判断是否需要告诉用户原因
            if (shouldShowRequestPermissionRationale(permissions[0])) {
                // 如果需要解释原因,则弹窗告诉用户
                showReasonDialog();
            } else {
                // 如果不需要,则返回权限申请失败
                mCallback.onPermissionResult(false, mPermissionCode);
            }
        }
    }

    // 弹窗展示权限申请原因,设定为protected是为了方便修改其它权限解释方式
    protected void showReasonDialog() {
        new AlertDialog.Builder(this)
                .setMessage(mReason)
                .setNegativeButton("取消", (dialog, which) -> {
                    // 用户点击取消时,返回权限被拒绝
                    dialog.dismiss();
                    mCallback.onPermissionResult(false, mPermissionCode);
                })
                .setPositiveButton("确定", ((dialog, which) -> {
                    // 用户点击确定时,继续申请
                    dialog.dismiss();
                    requestPermissions(new String[]{mPermission}, mPermissionCode);
                }))
                .create().show();
    }

    // 权限申请回调的接口类
    public interface PermissionCallback {
        void onPermissionResult(boolean result, int permissionCode);
    }
}

这样写的好处是,在申请权限的时候,只需要调用父类的requestPermissionWithReason()方法即可得到最终结果;另外,不建议在APP启动的时候就进行全部权限的申请,我们可以在当运行到某个需要权限的代码时再去申请,试想一下,用户第一次打开APP,啥也没做呢,遇到一大堆权限要求,估计很多人都直接拒绝了吧?

同样的,此代码也可以封装在baseFragment中,逻辑完全一致

下面列一下需要在代码中申请的权限,共计9组,只要其中一个权限申请成功了,该组中其它权限也都可以被使用:

group:android.permission-group.CONTACTS
    permission:android.permission.WRITE_CONTACTS
    permission:android.permission.GET_ACCOUNTS    
    permission:android.permission.READ_CONTACTS

group:android.permission-group.PHONE
    permission:android.permission.READ_CALL_LOG
    permission:android.permission.READ_PHONE_STATE 
    permission:android.permission.CALL_PHONE
    permission:android.permission.WRITE_CALL_LOG
    permission:android.permission.USE_SIP
    permission:android.permission.PROCESS_OUTGOING_CALLS
    permission:com.android.voicemail.permission.ADD_VOICEMAIL

group:android.permission-group.CALENDAR
    permission:android.permission.READ_CALENDAR
    permission:android.permission.WRITE_CALENDAR

group:android.permission-group.CAMERA
    permission:android.permission.CAMERA

group:android.permission-group.SENSORS
    permission:android.permission.BODY_SENSORS

group:android.permission-group.LOCATION
    permission:android.permission.ACCESS_FINE_LOCATION
    permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE
    permission:android.permission.READ_EXTERNAL_STORAGE
    permission:android.permission.WRITE_EXTERNAL_STORAGE

group:android.permission-group.MICROPHONE
    permission:android.permission.RECORD_AUDIO

group:android.permission-group.SMS
    permission:android.permission.READ_SMS
    permission:android.permission.RECEIVE_WAP_PUSH
    permission:android.permission.RECEIVE_MMS
    permission:android.permission.RECEIVE_SMS
    permission:android.permission.SEND_SMS
    permission:android.permission.READ_CELL_BROADCASTS


你可能感兴趣的:(工具类)