package com.yydcdut.note.aspect.permission; import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import com.yydcdut.note.R; import com.yydcdut.note.presenters.IPresenter; import com.yydcdut.note.utils.PermissionUtils; import com.yydcdut.note.utils.YLog; import com.yydcdut.note.utils.permission.Permission; import com.yydcdut.note.views.IView; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Created by yuyidong on 2017/2/4. */ @Aspect public class PermissionAspect { private static final String TAG = "yuyidong"; @Pointcut("execution(@com.yydcdut.note.aspect.permission.AspectPermission * *(..)) && @annotation(aspectPermission)") public void pointcut2CheckAndRequestPermissions(AspectPermission aspectPermission) { } @Around("pointcut2CheckAndRequestPermissions(aspectPermission)") public void aroundCheckAndRequestPermission(ProceedingJoinPoint proceedingJoinPoint, AspectPermission aspectPermission) { if (aspectPermission == null) { return; } IPresenter iPresenter = (IPresenter) proceedingJoinPoint.getTarget(); int value = aspectPermission.value(); switch (value) { case PermissionUtils.CODE_CAMERA: case PermissionUtils.CODE_ADJUST_CAMERA: { if (hasPermission4Camera(PermissionInstance.context)) { try { proceedingJoinPoint.proceed(); } catch (Throwable throwable) { YLog.e(throwable); } } else { if (iPresenter.getContext() instanceof Activity) { requestPermissions((Activity) iPresenter.getContext(), PermissionInstance.context.getString(R.string.permission_camera_init), PermissionUtils.PERMISSION_CAMERA, value); } else { YLog.i(TAG, "iPresenter.getContext() instanceof Activity --> false"); } } } break; case PermissionUtils.CODE_STORAGE: { if (hasPermission4Storage(PermissionInstance.context)) { try { proceedingJoinPoint.proceed(); } catch (Throwable throwable) { YLog.e(throwable); } } else { if (iPresenter.getContext() instanceof Activity) { requestPermissions((Activity) iPresenter.getContext(), PermissionInstance.context.getString(R.string.permission_storage_init), PermissionUtils.PERMISSION_STORAGE, value); } else { YLog.i(TAG, "iPresenter.getContext() instanceof Activity --> false"); } } } break; case PermissionUtils.CODE_LOCATION_AND_CAMERA: { if (hasPermission4LocationAndCamera(PermissionInstance.context)) { try { proceedingJoinPoint.proceed(); } catch (Throwable throwable) { YLog.e(throwable); } } else { if (iPresenter.getContext() instanceof Activity) { requestPermissions((Activity) iPresenter.getContext(), PermissionInstance.context.getString(R.string.permission_location), PermissionUtils.PERMISSION_LOCATION_AND_CAMERA, value); } else { YLog.i(TAG, "iPresenter.getContext() instanceof Activity --> false"); } } } break; case PermissionUtils.CODE_AUDIO: { if (hasPermission4Audio(PermissionInstance.context)) { try { proceedingJoinPoint.proceed(); } catch (Throwable throwable) { YLog.e(throwable); } } else { if (iPresenter.getContext() instanceof Activity) { requestPermissions((Activity) iPresenter.getContext(), PermissionInstance.context.getString(R.string.permission_audio), PermissionUtils.PERMISSION_AUDIO, value); } else { YLog.i(TAG, "iPresenter.getContext() instanceof Activity --> false"); } } } break; case PermissionUtils.CODE_PHONE_STATE: { if (hasPermission4PhoneState(PermissionInstance.context)) { try { proceedingJoinPoint.proceed(); } catch (Throwable throwable) { YLog.e(throwable); } } else { if (iPresenter.getContext() instanceof Activity) { requestPermissions((Activity) iPresenter.getContext(), PermissionInstance.context.getString(R.string.permission_phone_state), PermissionUtils.PERMISSION_PHONE_STATE, value); } else { YLog.i(TAG, "iPresenter.getContext() instanceof Activity --> false"); } } } break; } } @After("execution(* android.support.v4.app.FragmentActivity.onRequestPermissionsResult(..))") public void afterPermissionRequestBack(JoinPoint joinPoint) { Object[] objects = joinPoint.getArgs(); Object object = joinPoint.getTarget(); if (objects.length >= 1 && objects[0] instanceof Integer && object != null && object instanceof IView && ((IView) object).getPresenter() != null) { int requestCode = (int) objects[0]; invokeMethod(((IView) object).getPresenter(), requestCode); } else { YLog.i(TAG, "afterPermissionRequestBack --> bad"); } } @After("execution(* android.app.Fragment.onRequestPermissionsResult(..))") public void afterPermissionRequestBack4Fragment(JoinPoint joinPoint) { Object[] objects = joinPoint.getArgs(); Object object = joinPoint.getTarget(); if (objects.length >= 1 && objects[0] instanceof Integer && object != null && object instanceof IView && ((IView) object).getPresenter() != null) { int requestCode = (int) objects[0]; invokeMethod(((IView) object).getPresenter(), requestCode); } else { YLog.i(TAG, "afterPermissionRequestBack4Fragment --> bad"); } } private static void invokeMethod(@NonNull IPresenter iPresenter, @NonNull int requestCode) { Class clazz = iPresenter.getClass(); for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(Permission.class)) { Permission ann = method.getAnnotation(Permission.class); if (ann.value() == requestCode) { if (method.getParameterTypes().length > 0) { throw new RuntimeException("Cannot execute non-void method " + method.getName()); } try { if (!method.isAccessible()) { method.setAccessible(true); } method.invoke(iPresenter); } catch (IllegalAccessException e) { YLog.e(e); } catch (InvocationTargetException e) { YLog.e(e); } } } } } private static void requestPermissions(final @NonNull Activity activity, String explanation, final String[] permissions, final int code) { boolean shouldShowRationale = false; for (String permission : permissions) { if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) { shouldShowRationale = true; break; } } if (shouldShowRationale) { //explanation AlertDialog dialog = new AlertDialog.Builder(activity, R.style.note_dialog) .setTitle(R.string.permission_title) .setMessage(explanation) .setCancelable(false) .setPositiveButton(R.string.dialog_btn_ok, (dialogCallback, which) -> ActivityCompat.requestPermissions(activity, permissions, code)) .setNegativeButton(R.string.dialog_btn_cancel, null) .create(); dialog.show(); } else { ActivityCompat.requestPermissions(activity, permissions, code); } } private static boolean hasPermission4Camera(@NonNull Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA); if (permissionCheck == PackageManager.PERMISSION_GRANTED) { return true; } else { return false; } } private static boolean hasPermission4Storage(@NonNull Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } int permission0 = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE); int permission1 = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE); if (permission0 == PackageManager.PERMISSION_GRANTED && permission1 == PackageManager.PERMISSION_GRANTED) { return true; } else { return false; } } private static boolean hasPermission4LocationAndCamera(@NonNull Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } int permission0 = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION); int permission1 = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION); int permission2 = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA); if (permission0 == PackageManager.PERMISSION_GRANTED && permission1 == PackageManager.PERMISSION_GRANTED && permission2 == PackageManager.PERMISSION_GRANTED) { return true; } else { return false; } } private static boolean hasPermission4Audio(@NonNull Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } int permission = ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO); if (permission == PackageManager.PERMISSION_GRANTED) { return true; } else { return false; } } private static boolean hasPermission4PhoneState(@NonNull Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } int permission = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE); if (permission == PackageManager.PERMISSION_GRANTED) { return true; } else { return false; } } }