马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
目次
一,背景
二,通过Aspectj管理全部的注解
三,配置注解
四,通过空白Activity完成真正的权限申请
五,引入依赖配置
一,背景
在Activity或者fragment中,写在几个方法写一些解释,用来表现权限申请成功,申请失败,多次拒绝。同时需要无侵入式,让业务开发者尽大概的少些代码,把焦点的业务逻辑下沉到框架层
二,通过Aspectj管理全部的注解
它的作用就是劫持被解释的方法的执行。我在ASPECT中配置拦截@permission解释的方法。先做判断。如果没有相识过Aspect的话,AOP面向切面编程,各人应该听说过,它可以用来配置事务、做日记、权限验证、在用户哀求时做一些处置惩罚等等。而用@Aspect做一个切面,就可以直接实现。
- package com.example.myapplication;
- import android.app.Activity;
- import android.app.Service;
- import android.content.Context;
- import android.content.Intent;
- import android.content.pm.PackageManager;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import java.lang.reflect.Method;
- import androidx.core.content.ContextCompat;
- import androidx.fragment.app.Fragment;
- import androidx.fragment.app.FragmentActivity;
- @Aspect
- public class PermissionAspect {
- //com.example.myapplication
- private static final String POINTCUT_METHOD = "execution(@com.example.myapplication.Permission * *(..))";
- @Pointcut(POINTCUT_METHOD)
- public void methodAnnotatedWithPermission() {
- }
- @Around("methodAnnotatedWithPermission()")
- public Object permissionMethod(final ProceedingJoinPoint joinPoint) throws Throwable {
- MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- Method method = signature.getMethod();
- Permission permission = method.getAnnotation(Permission.class);
- String[] permissions = permission.value();
- int requestCode = permission.requestCode();
- Object object = joinPoint.getThis();
- Context context = null;
- if (object instanceof Activity) {
- context = (Activity) object;
- } else if (object instanceof FragmentActivity) {
- context = (FragmentActivity) object;
- } else if (object instanceof Fragment) {
- context = ((Fragment) object).getContext();
- } else if (object instanceof Service) {
- context = (Service) object;
- }
- Object o = null;
- if (checkPermissions(context, permissions)) {
- o = joinPoint.proceed();
- } else {
- Intent intent = new Intent();
- intent.setClass(context, PermissionActivity.class);
- intent.putExtra("permissions", permissions);
- intent.putExtra("requestcode", requestCode);
- context.startActivity(intent);
- }
- return o;
- }
- private boolean checkPermission(Context context, String permission) {
- if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) {
- return true;
- }
- return false;
- }
- private boolean checkPermissions(Context context, String[] permissions) {
- for(String permission : permissions) {
- if (!checkPermission(context, permission)) {
- return false;
- }
- }
- return true;
- }
- }
复制代码 如许@Permission就被切点劫持了,然后方法就会跑到切面aProceedingJoinPoint。然后获取上下文Context,把权限哀求交给一个透明的Activity来做。做完之后判断效果,用户是同意了还是拒绝了还是曲线了。同意了直接执行point.proceed(),其他方式则通过Activity或者fragment获取带注解的方法,反射执行即可。
三,配置注解
- package com.example.myapplication;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Permission {
- String[] value();
- int requestCode() default 1;
- }
复制代码
四,通过空白Activity完成真正的权限申请
- package com.example.myapplication;
- import android.app.Activity;
- import android.content.Intent;
- import android.content.pm.PackageManager;
- import android.os.Bundle;
- import java.util.ArrayList;
- import java.util.List;
- import androidx.annotation.NonNull;
- import androidx.annotation.Nullable;
- import androidx.core.app.ActivityCompat;
- import androidx.core.content.ContextCompat;
- public class PermissionActivity extends Activity {
- private String[] permissions;
- private int requestCode;
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Intent intent = getIntent();
- permissions = intent.getStringArrayExtra("permissions");
- requestCode = intent.getIntExtra("requestcode", 0);
- setContentView(R.layout.activity_permission);
- if (permissions != null && permissions.length > 0) {
- requestPermission(permissions);
- }
- }
- private void requestPermission(String[] permissions) {
- List<String> failure = new ArrayList<>();
- for (String permission : permissions) {
- if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
- failure.add(permission);
- }
- }
- if (failure.size() == 0) {
- requestPermissionSuccess();
- return;
- }
- ActivityCompat.requestPermissions(this, failure.toArray(new String[]{}), requestCode);
- }
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
-
- if (requestCode == this.requestCode) {
- if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- requestPermissionSuccess();
- } else {
- boolean alwaysHidePermission = false;
- for (int i = 0; i < grantResults.length; i++) {
- if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
- //判断是否勾选禁止后不再询问
- boolean showRequestPermission = ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i]);
- if (!showRequestPermission) {
- alwaysHidePermission = true;
- }
- }
- }
- requestPermissionFailed();
- }
- }
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- }
- private void requestPermissionSuccess() {
- setResult(RESULT_OK);
- finish();
- }
- private void requestPermissionFailed() {
- setResult(RESULT_CANCELED);
- finish();
- }
- }
复制代码 五,引入依赖配置
- apply plugin: 'com.android.application'
- buildscript {
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath 'org.aspectj:aspectjtools:1.8.9'
- classpath 'org.aspectj:aspectjweaver:1.8.9'
- }
- }
- android {
- compileSdkVersion 29
- buildToolsVersion "29.0.2"
- defaultConfig {
- applicationId "com.netease.premissionstudy"
- minSdkVersion 19
- targetSdkVersion 29
- versionCode 1
- versionName "1.0"
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- }
- dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'androidx.appcompat:appcompat:1.1.0'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test.ext:junit:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
- implementation 'org.aspectj:aspectjrt:1.8.13'
- }
- import org.aspectj.bridge.IMessage
- import org.aspectj.bridge.MessageHandler
- import org.aspectj.tools.ajc.Main
- final def log = project.logger
- final def variants = project.android.applicationVariants
- variants.all { variant ->
- if (!variant.buildType.isDebuggable()) {
- log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
- return;
- }
- JavaCompile javaCompile = variant.javaCompile
- javaCompile.doLast {
- String[] args = ["-showWeaveInfo",
- "-1.8",
- "-inpath", javaCompile.destinationDir.toString(),
- "-aspectpath", javaCompile.classpath.asPath,
- "-d", javaCompile.destinationDir.toString(),
- "-classpath", javaCompile.classpath.asPath,
- "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
- log.debug "ajc args: " + Arrays.toString(args)
- MessageHandler handler = new MessageHandler(true);
- new Main().run(args, handler);
- for (IMessage message : handler.getMessages(null, true)) {
- switch (message.getKind()) {
- case IMessage.ABORT:
- case IMessage.ERROR:
- case IMessage.FAIL:
- log.error message.message, message.thrown
- break;
- case IMessage.WARNING:
- log.warn message.message, message.thrown
- break;
- case IMessage.INFO:
- log.info message.message, message.thrown
- break;
- case IMessage.DEBUG:
- log.debug message.message, message.thrown
- break;
- }
- }
- }
- }
复制代码- // Top-level build file where you can add configuration options common to all sub-projects/modules.
- buildscript {
- repositories {
- google()
- jcenter()
-
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:3.5.2'
- classpath 'org.aspectj:aspectjtools:1.8.9'
- classpath 'org.aspectj:aspectjweaver:1.8.9'
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
- }
- }
- allprojects {
- repositories {
- google()
- jcenter()
-
- }
- }
- task clean(type: Delete) {
- delete rootProject.buildDir
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |