实现权限请求?一个注解就够了

请求系统权限?一个注解就够了。

在Android 6.0(API level 23)之后,并且编译时targetSdkVersion大于等于23时。用户是在应用运行时才去授予权限给应用,而不是在用户安装app的时候。所以,如果没有权限,运行到敏感代码时便会抛出异常。好在现在封装了不少开源库去帮助我们请求权限,比如说著名的RxPermissions。

好了,废话不多说。为了尽量简化开发时的工作。(我决定删库跑路,sorry ~ 跑题了,不小心说出了心里话。)我想用一个注解来请求权限,并且当用户拒绝之后,不在执行被注解修饰的函数。

​ 设计思路如下:

这里写图片描述

在实现我的“伟业”前,需要自定义一个注解,用来作为AOP的切入点。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Permission {
    String[] value();
}

非常简单,该注解由元注解修饰,表示其存在于运行时,并且只能用于修饰方法(函数)。该注解需要传入一个String数组,该数组就是调用者需要声明的权限名称。

ok,在定义完注解之后,很明显需要一个地方来使用这个注解。这里需要引入另一个AOP库aspectjx。通过自定义注解@Permission来作为AOP的连接点,并且通过aspectjx的@Around注解来达到获得权限执行原方法,被拒绝了权限就跳过原方法。代码如下:

@Aspect
public class SysPermissionAspect {

    @Around("execution(@com.luck.permission.annotation.Permission * *(..)) && @annotation(permission)")
    public void clickAspectj(final ProceedingJoinPoint joinPoint, final Permission permission) {
            if(isGranted){
                joinPoint.proceed();//获得权限,执行原方法
            }else{
                //拒绝权限后,跳过原方法
                Log.d("SysPermissionAspect", "拒绝了权限:" + permission.value());
            }
    }
}

​ 这时你可能会很疑惑,老子这么xx写的代码,凭什么你AOP之后说执行就执行,说跳过不执行就不执行啊???

这里写图片描述

​ 骚年别着急,放下手中愤怒的西瓜刀。其实最初我也很疑惑,最初接触到AOP还是在公司项目无痕埋点的时候。。。

为了解决这个疑惑,我们不妨反编译一下编译生成的代码。看一眼AOP到底做了什么操作?同样是九年义务教育凭什么AOP就能这么秀??

项目源码中的代码

这里写图片描述

编译完成后,反编译查看到的代码

这里写图片描述

不难发现,编译完后的代码,被织入了大量的代码,原有的函数已经发生了变化。。。

ok,接下来的问题就是如何去请求权限,因为请求权限的回调函数

onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)

该方法只存在于Activity和Fragment中。所以,当我们只能拿到当前运行的Activity的时候,如何能获取到请求权限后的回调?就像鼎鼎大名的图片加载库Gilde,是如何通过只拿到Acitvity或者Fragment的实例,而进行生命周期同步的?

通过查看Gilde源码发现,当Gilde.with(Activity) 传入的是Activity的时候,这时通过Activity的FragmentManager来管理一个Fragment从而间接的同步Activity的生命周期。于是我们的onRequestPermissionsResult便可以模仿一下。

 public static void requestPermissionsResult(Activity activity, String[] permission,
                                                PermissionsFragment.OnPermissionListener callback){
        PermissionsFragment permissionsFragment = getPermissionsFragment(activity);
        permissionsFragment.setOnPermissionListener(callback);
        permissionsFragment.requestPermissions(permission);
    }

private static PermissionsFragment getPermissionsFragment(Activity activity) {
    PermissionsFragment permissionsFragment = (PermissionsFragment) activity.getFragmentManager().findFragmentByTag(TAG);
    boolean isNewInstance = permissionsFragment == null;
    if (isNewInstance) {
        permissionsFragment = PermissionsFragment.newInstance();
        FragmentManager fragmentManager = activity.getFragmentManager();
        fragmentManager
                .beginTransaction()
                .add(permissionsFragment, TAG)
                .commitAllowingStateLoss();
        fragmentManager.executePendingTransactions();
    }
    return permissionsFragment;
}
public class PermissionsFragment extends Fragment {
    private static final int PERMISSIONS_REQUEST_CODE = 42;
    private OnPermissionListener mOnPermissionListener;

    public static PermissionsFragment newInstance() {
        Bundle args = new Bundle();
        PermissionsFragment fragment = new PermissionsFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @TargetApi(Build.VERSION_CODES.M)
    void requestPermissions(@NonNull String[] permissions) {
        if (checkPermissions(getActivity(), permissions)) {
            if (mOnPermissionListener != null) {
                mOnPermissionListener.onPermissionGranted();
            }
        } else {
            List<String> deniedPermissions = getDeniedPermissions(getActivity(), permissions);
            if (deniedPermissions.size() > 0) {
                requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]),
                        PERMISSIONS_REQUEST_CODE);//请求权限
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode != PERMISSIONS_REQUEST_CODE) return;
        if (verifyPermissions(grantResults)) {
            if (mOnPermissionListener != null)
                mOnPermissionListener.onPermissionGranted();
        } else {
            if (mOnPermissionListener != null)
                mOnPermissionListener.onPermissionDenied();
        }
    }

    /**
     * 验证权限是否都已经授权
     */
    private static boolean verifyPermissions(int[] grantResults) {
        for (int grantResult : grantResults) {
            if (grantResult != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取权限列表中所有需要授权的权限
     *
     * @param context     上下文
     * @param permissions 权限列表
     * @return
     */
    private static List<String> getDeniedPermissions(Context context, String... permissions) {
        List<String> deniedPermissions = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) {
                deniedPermissions.add(permission);
            }
        }
        return deniedPermissions;
    }

    /**
     * 检查所有的权限是否已经被授权
     *
     * @param permissions 权限列表
     * @return
     */
    private static boolean checkPermissions(Context context, String... permissions) {
        if (isOverMarshmallow()) {
            for (String permission : permissions) {
                if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 判断当前手机API版本是否 >= 6.0
     */
    private static boolean isOverMarshmallow() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
    }

    public void setOnPermissionListener(OnPermissionListener onPermissionListener) {
        this.mOnPermissionListener = onPermissionListener;
    }

    public interface OnPermissionListener {
        void onPermissionGranted();

        void onPermissionDenied();
    }

最后,我们再来看看, 外部在使用权限时如何调用。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.tv_hello).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testRequest();
            }
        });
        findViewById(R.id.btn_group).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testGroupPermission();
            }
        });
    }

    @Permission(Manifest.permission.CAMERA)
    private void testRequest() {
        Log.d("MainActivity", "获得了相机权限");
    }

    @Permission({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CALL_PHONE})
    private void testGroupPermission() {
        Log.d("MainActivity", "获得了组合权限");
    }
}

怎么样,是不是很方便,仅需要一个注解,就完成了权限的请求。

源码地址

猜你喜欢

转载自blog.csdn.net/qq_23186653/article/details/81221740