diff --git a/.github/ISSUE_TEMPLATE/issue_template.md b/.github/ISSUE_TEMPLATE/issue_template.md deleted file mode 100644 index 2cc1d66..0000000 --- a/.github/ISSUE_TEMPLATE/issue_template.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -name: 提交 Bug -about: 请告诉我不足,让我做得更好! -labels: bug -assignees: getActivity - ---- - -## 问题描述 - -* 框架版本:XXX - -* 问题描述:XXX - -* 复现步骤:XXX - -* 是否必现:填是/否 - -* 手机信息:例如某米 9 / Android 10 - -## 请回答 - -* 是部分机型还是所有机型都会出现:部分/全部 - -* 框架最新的版本是否存在这个问题:是/否 - -* 是否已经查阅框架文档还未能解决的:是/否 - -* issue 是否有人曾提过类似的问题:是/否 - -* 是否可以通过 Demo 来复现该问题:是/否 - -## 其他 - -* 提供报错堆栈(如果有报错的话必填) - -* 提供截图或视频(根据需要提供,不强制) - -* 提供解决方案(如果已经解决了的话) \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/issue_template_bug.md b/.github/ISSUE_TEMPLATE/issue_template_bug.md new file mode 100644 index 0000000..677d4a5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue_template_bug.md @@ -0,0 +1,41 @@ +--- +name: 提交 Bug +about: 请告诉我框架存在的问题,我会协助你解决此问题! +labels: bug +assignees: getActivity + +--- + +## 问题描述 + +* 框架版本:XXX + +* 问题描述:XXX + +* 复现步骤:XXX + +* 是否必现:填是/否 + +* 手机信息:例如某米 9 / Android 10 + +## 请回答 + +* 是部分机型还是所有机型都会出现:部分/全部(例如:某为,某 Android 版本会出现) + +* 框架最新的版本是否存在这个问题:是/否(如果用的是旧版本的话,建议升级看问题是否还存在) + +* 是否已经查阅框架文档还未能解决的:是/否(文档会提供最常见的问题解答,可以看看是否有自己想要的) + +* issue 是否有人曾提过类似的问题:是/否(看看曾经有人提过类似的问题,先参考一下别人是怎么解决的) + +* 是否可以通过 Demo 来复现该问题:是/否(排查一下是不是自己的项目代码写得有问题导致的) + +* 使用原生 API 是否会出现该问题:是/否(排查一下是不是框架的代码写法存在问题导致的) + +## 其他 + +* 提供报错堆栈(如果有报错的话必填) + +* 提供截图或视频(根据需要提供,此项不强制) + +* 提供解决方案(如果已经解决了的话,此项不强制) \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/issue_template_suggest.md b/.github/ISSUE_TEMPLATE/issue_template_suggest.md new file mode 100644 index 0000000..15bba88 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue_template_suggest.md @@ -0,0 +1,13 @@ +--- +name: 提交建议 +about: 请告诉我框架的不足之处,让我做得更好! +labels: bug +assignees: getActivity + +--- + +## 建议收集 + +* 你觉得框架有什么不足之处?(必答项,你可以描述框架有什么令你不满意的地方) + +* 你觉得该怎么去完善会比较好?(非必答项,你可以提供一下自己的想法或者做法供作者参考) \ No newline at end of file diff --git a/README.md b/README.md index a4a5d04..addfd67 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ android { dependencies { // 权限请求框架:https://github.com/getActivity/XXPermissions - implementation 'com.github.getActivity:XXPermissions:11.0' + implementation 'com.github.getActivity:XXPermissions:11.2' } ``` @@ -186,7 +186,7 @@ public class XxxActivity extends AppCompatActivity { 4. 如果申请的权限中包含后台定位权限, 那么这里面则不能包含和定位无关的权限,否则框架会抛出异常,因为 `ACCESS_BACKGROUND_LOCATION` 和其他非定位权限定位掺和在一起申请,在 Android 11 上会出现不申请直接被拒绝的情况。 - 5. 如果申请的权限和项目中的 **targetSdkVersion** 对不上,框架会抛出异常,是因为 **targetSdkVersion** 代表着项目适配到哪个 Android 版本,系统会自动做向下兼容,假设申请的权限是 Android 11 才出现的,但是 **targetSdkVersion** 还停留在 29,那么在某些机型上的申请结果会出现授权结果异常的情况。 + 5. 如果申请的权限和项目中的 **targetSdkVersion** 对不上,框架会抛出异常,是因为 **targetSdkVersion** 代表着项目适配到哪个 Android 版本,系统会自动做向下兼容,假设申请的权限是 Android 11 才出现的,但是 **targetSdkVersion** 还停留在 29,那么在某些机型上的申请,会出现授权异常的情况,也就是用户明明授权了,但是系统返回的始终是 false。 6. 如果动态申请的权限没有进行在清单文件中注册,那么框架会抛出异常,因为如果不这么做,是可以进行申请权限,但是不会出现授权弹窗,直接被系统拒绝,并且系统不会给出任何弹窗和提示,并且这个问题在每个机型上面都是**必现的**。 diff --git a/XXPermissions.apk b/XXPermissions.apk index 286bf18..bab510c 100644 Binary files a/XXPermissions.apk and b/XXPermissions.apk differ diff --git a/app/build.gradle b/app/build.gradle index 8245df8..5e24595 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.hjq.permissions.demo" minSdkVersion 14 targetSdkVersion 30 - versionCode 1100 - versionName "11.0" + versionCode 1120 + versionName "11.2" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git a/library/build.gradle b/library/build.gradle index 3586f8e..4778b8d 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -5,8 +5,8 @@ android { defaultConfig { minSdkVersion 11 - versionCode 1100 - versionName "11.0" + versionCode 1120 + versionName "11.2" } // 使用 JDK 1.8 @@ -18,6 +18,13 @@ android { lintOptions { abortOnError false } + + android.libraryVariants.all { variant -> + // aar 输出文件名配置 + variant.outputs.all { output -> + outputFileName = "xxpermissions-${android.defaultConfig.versionName}.aar" + } + } } dependencies { diff --git a/library/src/main/java/com/hjq/permissions/Permission.java b/library/src/main/java/com/hjq/permissions/Permission.java index b48d296..1190598 100644 --- a/library/src/main/java/com/hjq/permissions/Permission.java +++ b/library/src/main/java/com/hjq/permissions/Permission.java @@ -41,7 +41,7 @@ private Permission() {} /** 相机权限 */ public static final String CAMERA = "android.permission.CAMERA"; - /** 录音权限 */ + /** 麦克风权限 */ public static final String RECORD_AUDIO = "android.permission.RECORD_AUDIO"; /** 获取精确位置 */ @@ -63,7 +63,14 @@ private Permission() {} /** 修改日历 */ public static final String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR"; - /** 读取照片中的地理位置(需要 Android 10.0 及以上)*/ + /** + * 读取照片中的地理位置(需要 Android 10.0 及以上) + * + * 需要注意的是,如果这个权限申请成功了但是不能正常读取照片的地理信息,那么需要先申请存储权限: + * + * 如果项目 targetSdkVersion <= 29 需要申请 {@link Permission.Group#STORAGE} + * 如果项目 targetSdkVersion >= 30 需要申请 {@link Permission#MANAGE_EXTERNAL_STORAGE} + */ public static final String ACCESS_MEDIA_LOCATION = "android.permission.ACCESS_MEDIA_LOCATION"; /** 读取电话状态(这个权限在某些手机上面是申请失败的) */ diff --git a/library/src/main/java/com/hjq/permissions/PermissionChecker.java b/library/src/main/java/com/hjq/permissions/PermissionChecker.java index bc4e89d..d842a9d 100644 --- a/library/src/main/java/com/hjq/permissions/PermissionChecker.java +++ b/library/src/main/java/com/hjq/permissions/PermissionChecker.java @@ -173,6 +173,11 @@ static void checkLocationPermission(List requestPermissions) { return; } + if (requestPermissions.contains(Permission.ACCESS_COARSE_LOCATION) && !requestPermissions.contains(Permission.ACCESS_FINE_LOCATION)) { + // 申请后台定位权限可以不包含模糊定位权限,但是一定要包含精确定位权限,否则后台定位权限会无法申请,也就是会导致无法弹出授权弹窗 + throw new IllegalArgumentException("The application for background location permissions must include precise location permissions"); + } + for (String permission : requestPermissions) { if (Permission.ACCESS_FINE_LOCATION.equals(permission) || Permission.ACCESS_COARSE_LOCATION.equals(permission) diff --git a/library/src/main/java/com/hjq/permissions/PermissionFragment.java b/library/src/main/java/com/hjq/permissions/PermissionFragment.java index 572ceae..5fa374b 100644 --- a/library/src/main/java/com/hjq/permissions/PermissionFragment.java +++ b/library/src/main/java/com/hjq/permissions/PermissionFragment.java @@ -235,18 +235,15 @@ public void requestDangerousPermission() { // Android 10 定位策略发生改变,申请后台定位权限的前提是要有前台定位权限(授予了精确或者模糊任一权限) if (PermissionUtils.isAndroid10() && allPermissions.contains(Permission.ACCESS_BACKGROUND_LOCATION)) { locationPermission = new ArrayList<>(); - if (allPermissions.contains(Permission.ACCESS_COARSE_LOCATION) && - !PermissionUtils.isGrantedPermission(activity, Permission.ACCESS_COARSE_LOCATION)) { + if (allPermissions.contains(Permission.ACCESS_COARSE_LOCATION)) { locationPermission.add(Permission.ACCESS_COARSE_LOCATION); } - if (allPermissions.contains(Permission.ACCESS_FINE_LOCATION) && - !PermissionUtils.isGrantedPermission(activity, Permission.ACCESS_FINE_LOCATION)) { + if (allPermissions.contains(Permission.ACCESS_FINE_LOCATION)) { locationPermission.add(Permission.ACCESS_FINE_LOCATION); } } - // 如果不需要申请前台定位权限就直接申请危险权限 if (locationPermission == null || locationPermission.isEmpty()) { requestPermissions(allPermissions.toArray(new String[allPermissions.size() - 1]), getArguments().getInt(REQUEST_CODE)); return; @@ -332,15 +329,6 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in continue; } - // 重新检查 Android 11 后台定位权限 - if (PermissionUtils.isAndroid11() && - Permission.ACCESS_BACKGROUND_LOCATION.equals(permission)) { - // 这个权限是后台定位权限并且当前手机版本是 Android 11 及以上,那么就需要重新进行检测 - // 因为只要申请这个后台定位权限,grantResults 数组总对这个权限申请的结果返回 -1(拒绝) - grantResults[i] = PermissionUtils.getPermissionStatus(activity, permission); - continue; - } - // 重新检查 Android 10.0 的三个新权限 if (!PermissionUtils.isAndroid10() && (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission) || diff --git a/library/src/main/java/com/hjq/permissions/PermissionUtils.java b/library/src/main/java/com/hjq/permissions/PermissionUtils.java index 03b686a..cfe345e 100644 --- a/library/src/main/java/com/hjq/permissions/PermissionUtils.java +++ b/library/src/main/java/com/hjq/permissions/PermissionUtils.java @@ -93,7 +93,7 @@ static boolean isGrantedStoragePermission(Context context) { if (isAndroid11()) { return Environment.isExternalStorageManager(); } - return XXPermissions.isGranted(context, Permission.Group.STORAGE); + return isGrantedPermissions(context, asArrayList(Permission.Group.STORAGE)); } /** @@ -188,6 +188,10 @@ static boolean isGrantedPermissions(Context context, List permissions) { return true; } + if (permissions == null || permissions.isEmpty()) { + return false; + } + for (String permission : permissions) { if (!isGrantedPermission(context, permission)) { return false; @@ -252,18 +256,23 @@ static boolean isGrantedPermission(Context context, String permission) { // 检测 10.0 的三个新权限 if (!isAndroid10()) { - if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission) || - Permission.ACCESS_MEDIA_LOCATION.equals(permission)) { - return true; + + if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission)) { + return context.checkSelfPermission(Permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; } if (Permission.ACTIVITY_RECOGNITION.equals(permission)) { return context.checkSelfPermission(Permission.BODY_SENSORS) == PackageManager.PERMISSION_GRANTED; } + + if (Permission.ACCESS_MEDIA_LOCATION.equals(permission)) { + return true; + } } // 检测 9.0 的一个新权限 if (!isAndroid9()) { + if (Permission.ACCEPT_HANDOVER.equals(permission)) { return true; } @@ -271,6 +280,7 @@ static boolean isGrantedPermission(Context context, String permission) { // 检测 8.0 的两个新权限 if (!isAndroid8()) { + if (Permission.ANSWER_PHONE_CALLS.equals(permission)) { return true; } @@ -325,31 +335,37 @@ static boolean isPermissionPermanentDenied(Activity activity, String permission) return false; } - // 重新检测后台定位权限是否永久拒绝 if (isAndroid10()) { - if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission) && - getPermissionStatus(activity, Permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_DENIED) { - return isPermissionPermanentDenied(activity, Permission.ACCESS_COARSE_LOCATION) || - isPermissionPermanentDenied(activity, Permission.ACCESS_FINE_LOCATION); + // 重新检测后台定位权限是否永久拒绝 + if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission) && + !isGrantedPermission(activity, Permission.ACCESS_BACKGROUND_LOCATION) && + !isGrantedPermission(activity, Permission.ACCESS_FINE_LOCATION)) { + return !activity.shouldShowRequestPermissionRationale(Permission.ACCESS_FINE_LOCATION); } } // 检测 10.0 的三个新权限 if (!isAndroid10()) { - if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission) || - Permission.ACCESS_MEDIA_LOCATION.equals(permission)) { - return false; + + if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission)) { + return !isGrantedPermission(activity, Permission.ACCESS_FINE_LOCATION) && + !activity.shouldShowRequestPermissionRationale(Permission.ACCESS_FINE_LOCATION); } if (Permission.ACTIVITY_RECOGNITION.equals(permission)) { - return activity.checkSelfPermission(Permission.BODY_SENSORS) == PackageManager.PERMISSION_DENIED && - !activity.shouldShowRequestPermissionRationale(permission); + return !isGrantedPermission(activity, Permission.BODY_SENSORS) && + !activity.shouldShowRequestPermissionRationale(Permission.BODY_SENSORS); + } + + if (Permission.ACCESS_MEDIA_LOCATION.equals(permission)) { + return false; } } // 检测 9.0 的一个新权限 if (!isAndroid9()) { + if (Permission.ACCEPT_HANDOVER.equals(permission)) { return false; } @@ -357,17 +373,18 @@ static boolean isPermissionPermanentDenied(Activity activity, String permission) // 检测 8.0 的两个新权限 if (!isAndroid8()) { + if (Permission.ANSWER_PHONE_CALLS.equals(permission)) { return true; } if (Permission.READ_PHONE_NUMBERS.equals(permission)) { - return activity.checkSelfPermission(Permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED && - !activity.shouldShowRequestPermissionRationale(permission); + return !isGrantedPermission(activity, Permission.READ_PHONE_STATE) && + !activity.shouldShowRequestPermissionRationale(Permission.READ_PHONE_STATE); } } - return activity.checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED && + return !isGrantedPermission(activity, permission) && !activity.shouldShowRequestPermissionRationale(permission); } @@ -424,6 +441,17 @@ static ArrayList asArrayList(T... array) { return list; } + static ArrayList asArrayLists(T[]... arrays) { + ArrayList list = new ArrayList<>(); + if (arrays == null || arrays.length == 0) { + return list; + } + for (T[] ts : arrays) { + list.addAll(asArrayList(ts)); + } + return list; + } + /** * 获得随机的 RequestCode */ diff --git a/library/src/main/java/com/hjq/permissions/XXPermissions.java b/library/src/main/java/com/hjq/permissions/XXPermissions.java index 81568a3..2efab63 100644 --- a/library/src/main/java/com/hjq/permissions/XXPermissions.java +++ b/library/src/main/java/com/hjq/permissions/XXPermissions.java @@ -7,7 +7,6 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; -import java.util.ArrayList; import java.util.List; /** @@ -98,24 +97,17 @@ private XXPermissions(Context context) { mContext = context; } - /** - * 添加权限 - */ - public XXPermissions permission(String permission) { - if (mPermissions == null) { - mPermissions = new ArrayList<>(1); - } - mPermissions.add(permission); - return this; - } - /** * 添加权限组 */ - public XXPermissions permission(String[] permissions) { + public XXPermissions permission(String... permissions) { return permission(PermissionUtils.asArrayList(permissions)); } + public XXPermissions permission(String[]... permissions) { + return permission(PermissionUtils.asArrayLists(permissions)); + } + public XXPermissions permission(List permissions) { if (mPermissions == null) { mPermissions = permissions; @@ -179,12 +171,12 @@ public void request(OnPermissionCallback callback) { /** * 判断一个或多个权限是否全部授予了 */ - public static boolean isGranted(Context context, String permission) { - return PermissionUtils.isGrantedPermission(context, permission); + public static boolean isGranted(Context context, String... permissions) { + return isGranted(context, PermissionUtils.asArrayList(permissions)); } - public static boolean isGranted(Context context, String[] permissions) { - return isGranted(context, PermissionUtils.asArrayList(permissions)); + public static boolean isGranted(Context context, String[]... permissions) { + return isGranted(context, PermissionUtils.asArrayLists(permissions)); } public static boolean isGranted(Context context, List permissions) { @@ -194,15 +186,18 @@ public static boolean isGranted(Context context, List permissions) { /** * 获取没有授予的权限 */ - public static List getDenied(Context context, String[] permissions) { + public static List getDenied(Context context, String... permissions) { return getDenied(context, PermissionUtils.asArrayList(permissions)); } + public static List getDenied(Context context, String[]... permissions) { + return getDenied(context, PermissionUtils.asArrayLists(permissions)); + } + public static List getDenied(Context context, List permissions) { return PermissionUtils.getDeniedPermissions(context, permissions); } - /** * 判断某个权限是否是特殊权限 */ @@ -213,12 +208,12 @@ public static boolean isSpecial(String permission) { /** * 判断一个或多个权限是否被永久拒绝了(注意不能在请求权限之前调用,应该在 {@link OnPermissionCallback#onDenied(List, boolean)} 方法中调用) */ - public static boolean isPermanentDenied(Activity activity, String permission) { - return PermissionUtils.isPermissionPermanentDenied(activity, permission); + public static boolean isPermanentDenied(Activity activity, String... permissions) { + return isPermanentDenied(activity, PermissionUtils.asArrayList(permissions)); } - public static boolean isPermanentDenied(Activity activity, String[] permissions) { - return isPermanentDenied(activity, PermissionUtils.asArrayList(permissions)); + public static boolean isPermanentDenied(Activity activity, String[]... permissions) { + return isPermanentDenied(activity, PermissionUtils.asArrayLists(permissions)); } public static boolean isPermanentDenied(Activity activity, List permissions) { @@ -229,12 +224,12 @@ public static void startPermissionActivity(Context context) { startPermissionActivity(context, (List) null); } - public static void startPermissionActivity(Context context, String permission) { - startPermissionActivity(context, PermissionUtils.asArrayList(permission)); + public static void startPermissionActivity(Context context, String... permissions) { + startPermissionActivity(context, PermissionUtils.asArrayList(permissions)); } - public static void startPermissionActivity(Context context, String[] permissions) { - startPermissionActivity(context, PermissionUtils.asArrayList(permissions)); + public static void startPermissionActivity(Context context, String[]... permissions) { + startPermissionActivity(context, PermissionUtils.asArrayLists(permissions)); } /** @@ -249,16 +244,18 @@ public static void startPermissionActivity(Context context, List permiss return; } Intent intent = PermissionSettingPage.getSmartPermissionIntent(context, permissions); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (!(context instanceof Activity)) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } context.startActivity(intent); } - public static void startPermissionActivity(Activity activity, String permission) { - startPermissionActivity(activity, PermissionUtils.asArrayList(permission)); + public static void startPermissionActivity(Activity activity, String... permissions) { + startPermissionActivity(activity, PermissionUtils.asArrayList(permissions)); } - public static void startPermissionActivity(Activity activity, String[] permissions) { - startPermissionActivity(activity, PermissionUtils.asArrayList(permissions)); + public static void startPermissionActivity(Activity activity, String[]... permissions) { + startPermissionActivity(activity, PermissionUtils.asArrayLists(permissions)); } public static void startPermissionActivity(Activity activity, List permissions) { @@ -269,12 +266,12 @@ public static void startPermissionActivity(Fragment fragment) { startPermissionActivity(fragment, (List) null); } - public static void startPermissionActivity(Fragment fragment, String permissions) { + public static void startPermissionActivity(Fragment fragment, String... permissions) { startPermissionActivity(fragment, PermissionUtils.asArrayList(permissions)); } - public static void startPermissionActivity(Fragment fragment, String[] permissions) { - startPermissionActivity(fragment, PermissionUtils.asArrayList(permissions)); + public static void startPermissionActivity(Fragment fragment, String[]... permissions) { + startPermissionActivity(fragment, PermissionUtils.asArrayLists(permissions)); } /**