package com.netease.nim.uikit.permission; import android.annotation.TargetApi; import android.app.Activity; import android.content.pm.PackageManager; import android.os.Build; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import com.netease.nim.uikit.permission.annotation.OnMPermissionDenied; import com.netease.nim.uikit.permission.annotation.OnMPermissionGranted; import com.netease.nim.uikit.permission.annotation.OnMPermissionNeverAskAgain; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; public class MPermission extends BaseMPermission { private int requestCode; private String[] permissions; private Object object; // activity or fragment private MPermission(Object object) { this.object = object; } public static MPermission with(Activity activity) { return new MPermission(activity); } public static MPermission with(Fragment fragment) { return new MPermission(fragment); } public MPermission setRequestCode(int requestCode) { this.requestCode = requestCode; return this; } public MPermission permissions(String... permissions) { this.permissions = permissions; return this; } /** * ********************* request ********************* */ @TargetApi(value = Build.VERSION_CODES.M) public void request() { doRequestPermissions(object, requestCode, permissions); } @TargetApi(value = Build.VERSION_CODES.M) private static void doRequestPermissions(Object object, int requestCode, String[] permissions) { if (!isOverMarshmallow()) { doExecuteSuccess(object, requestCode); return; } List<String> deniedPermissions = findDeniedPermissions(getActivity(object), permissions); if (deniedPermissions != null && deniedPermissions.size() > 0) { if (object instanceof Activity) { ((Activity) object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode); } else if (object instanceof Fragment) { ((Fragment) object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode); } else { throw new IllegalArgumentException(object.getClass().getName() + " is not supported"); } } else { doExecuteSuccess(object, requestCode); } } /** * ********************* on result ********************* */ public static void onRequestPermissionsResult(Activity activity, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { dispatchResult(activity, requestCode, permissions, grantResults); } public static void onRequestPermissionsResult(Fragment fragment, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { dispatchResult(fragment, requestCode, permissions, grantResults); } private static void dispatchResult(Object obj, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { List<String> deniedPermissions = new ArrayList<>(); for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { deniedPermissions.add(permissions[i]); } } if (deniedPermissions.size() > 0) { if (hasNeverAskAgainPermission(getActivity(obj), deniedPermissions)) { doExecuteFailAsNeverAskAgain(obj, requestCode); } else { doExecuteFail(obj, requestCode); } } else { doExecuteSuccess(obj, requestCode); } } /** * ********************* reflect execute result ********************* */ private static void doExecuteSuccess(Object activity, int requestCode) { executeMethod(activity, findMethodWithRequestCode(activity.getClass(), OnMPermissionGranted.class, requestCode)); } private static void doExecuteFail(Object activity, int requestCode) { executeMethod(activity, findMethodWithRequestCode(activity.getClass(), OnMPermissionDenied.class, requestCode)); } private static void doExecuteFailAsNeverAskAgain(Object activity, int requestCode) { executeMethod(activity, findMethodWithRequestCode(activity.getClass(), OnMPermissionNeverAskAgain.class, requestCode)); } private static <A extends Annotation> Method findMethodWithRequestCode(Class clazz, Class<A> annotation, int requestCode) { for (Method method : clazz.getDeclaredMethods()) { if (method.getAnnotation(annotation) != null && isEqualRequestCodeFromAnnotation(method, annotation, requestCode)) { return method; } } return null; } private static boolean isEqualRequestCodeFromAnnotation(Method m, Class clazz, int requestCode) { if (clazz.equals(OnMPermissionDenied.class)) { return requestCode == m.getAnnotation(OnMPermissionDenied.class).value(); } else if (clazz.equals(OnMPermissionGranted.class)) { return requestCode == m.getAnnotation(OnMPermissionGranted.class).value(); } else if (clazz.equals(OnMPermissionNeverAskAgain.class)) { return requestCode == m.getAnnotation(OnMPermissionNeverAskAgain.class).value(); } else { return false; } } /** * ********************* reflect execute method ********************* */ private static void executeMethod(Object activity, Method executeMethod) { executeMethodWithParam(activity, executeMethod, new Object[]{}); } private static void executeMethodWithParam(Object activity, Method executeMethod, Object... args) { if (executeMethod != null) { try { if (!executeMethod.isAccessible()) { executeMethod.setAccessible(true); } executeMethod.invoke(activity, args); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }