Android

动态权限申请工具包 PermissionUtil (适配Andr

2019-07-20  本文已影响13人  12313凯皇

参考文章:android 权限申请–在activity之外申请权限

Android 6.0开始,一些常用权限如相机拍照等不仅仅需要在AndroidManifest.xml中申请就可以了,还需要动态申请权限。但是申请权限后有需要在onRequestPermissionsResult方法中进行处理,这样就感觉很烦。

于是便尝试着写一个util工具包来简化操作,于是我找到了这个:RxPermissions,内部好像是通过RxJava2实现的,8K+star还是足矣说明它的强大的,不过本着学习的态度还是准备自己实现一个,哪怕适配比较差也行啊。

其实PermissionUtil比较复杂的一点就是onRequestPermissionsResult回调方法的问题,在度娘那里搜寻了一番后找到了一个比较通用的方法,就是通过一个透明主题的Activity去实现,同时还可以给出一些友好的提示性Dialog。废话说了那么多,下面开始正题:

效果图:


)

代码实现:
  1. 首先是权限申请完之后的PermissionResultCallBack回调接口
public interface PermissionResultCallBack {
    /**
     * 当全部权限的申请被用户允许之后,该方法会被调用
     */
    void onPermissionGranted();

    /**
     * 被拒绝的权限
     *
     * @param permissions permissions
     */
    void onPermissionDenied(String... permissions);

    /**
     * 被拒绝且勾选了不再提示,需要去设置界面手动开启的权限
     *
     * @param permissions permissions
     */
    void onRationalShow(String... permissions);
}

  1. 然后是用于申请权限的TransparentActivity
public class TransparentActivity extends AppCompatActivity {


    public static final String TAG = TransparentActivity.class.getSimpleName();

    /**
     * 权限申请相关
     */
    public static final String EXTRA_PERMISSIONS = "extra_permission"; //权限列表
    public static final int REQUEST_CODE = 1000;  //请求码
    private static PermissionResultCallBack mStaticPermissionResultCallBack;
    private String[] permissions;

    private AlertDialog mPermissionRequestDialog;

    /**
     * 请求权限
     * 记得在{@code AndroidManifest.xml}中加上相应权限
     */
    public static void requestPermission(Activity activity, String[] permissions, PermissionResultCallBack callBack) {
        mStaticPermissionResultCallBack = callBack;
        Intent intent = new Intent(activity, TransparentActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(TransparentActivity.EXTRA_PERMISSIONS, permissions);
        activity.startActivity(intent);
    }
  
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transparent);

        Intent intent = getIntent();
        if (intent.hasExtra(EXTRA_PERMISSIONS)) {
            //权限申请
            requestPermissions(intent);
            return;
        }

        Log.e(TAG, "申请权限需要通过\"EXTRA_PERMISSIONS\"传递权限列表");
        finish();
    }

    @Override
    protected void onDestroy() {
        if (mPermissionRequestDialog != null && mPermissionRequestDialog.isShowing()) {
            mPermissionRequestDialog.dismiss();
        }
        super.onDestroy();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        Log.d(TAG, "onRequestPermissionsResult: requestCode = " + requestCode +
                "\npermission = " + Arrays.toString(permissions) +
                "\ngrantResults = " + Arrays.toString(grantResults));

        //申请权限
        if (requestCode == REQUEST_CODE) {

            //是否为android 6.0及以上版本
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                mStaticPermissionResultCallBack.onPermissionGranted();
                return;
            }

            List<String> deniedPermissions = new ArrayList<>();
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    //某个权限未授权
                    deniedPermissions.add(permissions[i]);
                }
            }

            List<String> shouldShowRationalePermissions = getShouldShowRationPermissions(permissions,grantResults);
            if (shouldShowRationalePermissions.size() != 0) {
                //设置了不再提示且拒绝了的权限 需要到设置中去手动开启
                mStaticPermissionResultCallBack.onRationalShow(shouldShowRationalePermissions.toArray(new String[0]));
                finish();
                return;
            }

            if (deniedPermissions.size() != 0) {
                //拒绝的权限
                mStaticPermissionResultCallBack.onPermissionDenied(deniedPermissions.toArray(new String[0]));
                finish();
                return;
            }

            //所有权限都授权了
            mStaticPermissionResultCallBack.onPermissionGranted();

        }
        finish();
    }

    /**
     * 申请权限
     */
    private void requestPermissions(Intent intent) {
        String[] extraPermissions = intent.getStringArrayExtra(EXTRA_PERMISSIONS);
        if (extraPermissions == null) {
            Log.e(TAG, "permissions 传参有误");
            Toast.makeText(this, "permissions 传参有误", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }

        //需要申请的权限(剔除掉已经拥有了的权限)
        permissions = getNeedRequestPermissions(extraPermissions);
        if (permissions.length == 0) {
            Log.d(TAG, "权限都已拥有");
            mStaticPermissionResultCallBack.onPermissionGranted();
            finish();
            return;
        }

        showDialog();
    }

    /**
     * 申请权限前友好提示的dialog
     */
    private void showDialog() {
        if (mPermissionRequestDialog == null) {
            mPermissionRequestDialog = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Light_Dialog)
                    .setTitle("权限申请")
                    .setMessage("系统需要申请" + permissions.length + "项权限")
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                requestPermissions(permissions, REQUEST_CODE);
                            } else {
                                ActivityCompat.requestPermissions(TransparentActivity.this,
                                        permissions, REQUEST_CODE);
                            }
                        }
                    })
                    .setNegativeButton("拒绝", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            mStaticPermissionResultCallBack.onPermissionDenied(permissions);
                            finish();
                        }
                    }).create();
        }
        mPermissionRequestDialog.show();
    }

    /**
     * 找出需要申请的权限,去掉已经拥有了的权限
     *
     * @param permissions permissions
     * @return 需要申请的权限
     */
    @TargetApi(Build.VERSION_CODES.M)
    private String[] getNeedRequestPermissions(String[] permissions) {
        List<String> permissionsNeedRequest = new ArrayList<>();
        for (String permission : permissions) {
            if (checkSelfPermission(permission) !=
                    PackageManager.PERMISSION_GRANTED) {
                permissionsNeedRequest.add(permission);
            }
        }
        return permissionsNeedRequest.toArray(new String[0]);
    }

    /**
     * 需要跳转到设置中手动开启的权限
     */
    private List<String> getShouldShowRationPermissions(String[] permissions, int[] grantResults) {
        List<String> rationPermissions = new ArrayList<>();
        //shouldShowRequestPermissionRationale
        //如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。
        // 如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 Don't ask again 选项,
        // 此方法将返回 false。
        // 如果设备规范禁止应用具有该权限,此方法也会返回 false。
        // 注:如果已拥有该权限那么也会返回false
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            for (int i = 0; i < permissions.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED
                        && !shouldShowRequestPermissionRationale(permissions[i])) {
                    rationPermissions.add(permissions[i]);
                }
            }
        }
        return rationPermissions;
    }
}


然后是透明主题

<!--继承Theme.AppCompat.NoActionBar,不显示标题栏,用于PermissionActivity-->
<style name="TransparentTheme" parent="Theme.AppCompat.NoActionBar">
    <!--不设置activity进入和退出动画样式-->
    <item name="android:windowAnimationStyle">@null</item>
    <!--设置窗口的背景为透明,设置透明背景必须要设置此项-->
    <item name="android:windowBackground">@android:color/transparent</item>
    <!--设置窗口的背景是否为半透明,设置透明背景必须要设置此项-->
    <item name="android:windowIsTranslucent">true</item>
    <!--设置状态栏的背景为半透明-->
    <item name="android:windowTranslucentStatus">true</item>
</style>

别忘了注册Activity

<activity
     android:name="com.yu.hu.permissionlibrary.util.TransparentActivity"
     android:theme="@style/TransparentTheme" />
  1. 权限申请PermissionUtil
public class PermissionUtil {

    private static final String TAG = "PermissionUtil";

    /**
     * 申请相机权限
     */
    public static void requestCameraPermission(Activity activity, PermissionResultCallBack callBack) {
        requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, callBack);
    }

    /**
     * 申请录制音频权限
     */
    public static void requestRecordAudioPermission(Activity activity, PermissionResultCallBack callBack) {
        requestPermissions(activity, new String[]{Manifest.permission.RECORD_AUDIO}, callBack);
    }

    /**
     * 适用于app初始化或在主页时申请所需所有权限使用
     */
    public static void requestInitPermissions(Activity activity, String[] permissions, PermissionResultCallBack callBack) {
        requestPermissions(activity, permissions, callBack);
    }

    /**
     * 请求多个权限
     *
     * @param activity    activity
     * @param permissions 权限列表
     * @param callBack    
     */
    private static void requestPermissions(Activity activity, String[] permissions, @NonNull PermissionResultCallBack callBack) {
        //使用PermissionRequestActivity请求
        Log.d(TAG, "使用PermissionRequestActivity请求权限 "
                + "\n请求权限:" + Arrays.toString(permissions));
        TransparentActivity.requestPermission(activity, permissions, callBack);
    }


}
  1. 使用
PermissionUtil.requestInitPermissions(MainActivity.this,
        new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.READ_EXTERNAL_STORAGE}
        , new PermissionResultCallBack() {
            @Override
            public void onPermissionGranted() {
                Toast.makeText(MainActivity.this, "允许了权限", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPermissionDenied(String... permissions) {
                Log.d("MainActivity", "拒绝的权限: " + Arrays.toString(permissions));
                Toast.makeText(MainActivity.this, "拒绝了权限" + Arrays.toString(permissions), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onRationalShow(String... permissions) {
                Log.d("MainActivity", "需要到系统设置开启的权限: " + Arrays.toString(permissions));
                Toast.makeText(MainActivity.this, "需要到系统设置开启的权限: " + Arrays.toString(permissions), Toast.LENGTH_SHORT).show();
            }
        });
上一篇下一篇

猜你喜欢

热点阅读