Skip to content

Commit

Permalink
新增支持自定义权限设置页跳转请求码
Browse files Browse the repository at this point in the history
优化权限常量注释及抑制项目代码警告
  • Loading branch information
getActivity committed Jul 5, 2021
1 parent 00f7fc1 commit a047b5c
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 23 deletions.
2 changes: 1 addition & 1 deletion HelpDoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ public class PermissionActivity extends AppCompatActivity implements OnPermissio

* 其实不止华为有问题,小米同样有问题,有很多人跟我反馈过同一个问题,XXPermissions 跳转到国产手机权限设置页,用户正常授予了权限之后返回仍然检测到权限仍然是拒绝的状态,这个问题反馈的次数很多,但是迟迟不能排查到原因,终于在最后一次得到答案了,[有人](https://github.com/getActivity/XXPermissions/issues/38)帮我排查到是 miui 优化开关的问题(小米手机 ---> 开发者选项 ---> 启用 miui 优化),那么问题来了,这个开关有什么作用?是如何影响到 XXPermissions 的?

* 首先这个问题要从 XXPermissions 跳转到国产手机设置页的原理讲起,从谷歌提供的原生 API 我们最多只能跳转到应用详情页,并不能直接跳转到权限设置页,而需要用户在应用详情页再次点击才能进入权限设置页。如果从用户体验的角度上看待这个问题,肯定是直接跳转到权限设置页是最好的,但是这种方式是不受谷歌支持的,当然也有方法实现,网上都有一个通用的答案,就是直接捕获某个品牌手机的权限设置页 `Activity` 包名然后进行跳转。这种想法的起点是好的,但是存在许多问题,并不能保证每个品牌的所有机型都能适配到位,手机产商更改这个 `Activity` 的包名的次数和频率比较高,在最近发布的一些新的华为机型上面几乎已经全部失效,也就是 `startActivity` 的时候会报 `ActivityNotFoundException` 或 `SecurityException ` 异常,当然这些异常是可以被捕捉到的,但是仅仅只能捕获到崩溃,一些非崩溃的行为我们并不能从中得知和处理,例如我刚刚讲过的华为和小米的问题,这些问题并不能导致崩溃,但是会导致功能出现异常。
* 首先这个问题要从 XXPermissions 跳转到国产手机设置页的原理讲起,从谷歌提供的原生 API 我们最多只能跳转到应用详情页,并不能直接跳转到权限设置页,而需要用户在应用详情页再次点击才能进入权限设置页。如果从用户体验的角度上看待这个问题,肯定是直接跳转到权限设置页是最好的,但是这种方式是不受谷歌支持的,当然也有方法实现,网上都有一个通用的答案,就是直接捕获某个品牌手机的权限设置页 `Activity` 包名然后进行跳转。这种想法的起点是好的,但是存在许多问题,并不能保证每个品牌的所有机型都能适配到位,手机产商更改这个 `Activity` 的包名的次数和频率比较高,在最近发布的一些新的华为机型上面几乎已经全部失效,也就是 `startActivity` 的时候会报 `ActivityNotFoundException` 或 `SecurityException` 异常,当然这些异常是可以被捕捉到的,但是仅仅只能捕获到崩溃,一些非崩溃的行为我们并不能从中得知和处理,例如我刚刚讲过的华为和小米的问题,这些问题并不能导致崩溃,但是会导致功能出现异常。

* 而 miui 优化开关是小米工程师预留的切换 miui 和原生的功能开关,例如在这个开关开启的时候,在应用详情页点击权限管理会跳转到小米的权限设置页,如果这个开关是关闭状态(默认是开启状态),在应用详情页点击权限管理会跳转到谷歌原生的权限设置页,具体效果如图:

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ android {
dependencies {
// 权限请求框架:https://github.com/getActivity/XXPermissions
implementation 'com.github.getActivity:XXPermissions:11.5'
implementation 'com.github.getActivity:XXPermissions:11.6'
}
```

Expand Down Expand Up @@ -151,8 +151,8 @@ public class XxxActivity extends AppCompatActivity {

| 功能及细节 | [XXPermissions](https://github.com/getActivity/XXPermissions) | [AndPermission](https://github.com/yanzhenjie/AndPermission) | [RxPermissions](https://github.com/tbruyelle/RxPermissions) | [PermissionsDispatcher](https://github.com/permissions-dispatcher/PermissionsDispatcher) | [EasyPermissions](https://github.com/googlesamples/easypermissions) | [PermissionX](https://github.com/guolindev/PermissionX) | [AndroidUtilCode](https://github.com/Blankj/AndroidUtilCode) |
| :--------: | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: |
| 对应版本 | 11.0 | 2.0.3 | 0.12 | 4.8.0 | 3.0.0 | 1.4.0 | 1.30.5 |
| 框架体积 | [27 KB](https://bintray.com/getactivity/maven/xxpermissions#files/com/hjq/xxpermissions) | [127 KB](https://mvnrepository.com/artifact/com.yanzhenjie/permission) | [28 KB](https://jitpack.io/#com.github.tbruyelle/rxpermissions) | [91 KB](https://bintray.com/hotchemi/org.permissionsdispatcher/permissionsdispatcher-processor#files/org/permissionsdispatcher/permissionsdispatcher-processor) | [48 KB](https://bintray.com/easygoogle/EasyPermissions/easypermissions#files/pub/devrel/easypermissions) | [32 KB](https://bintray.com/guolindev/maven/permissionx#files/com/permissionx/guolindev/permissionx) | [483 KB](https://bintray.com/blankj/maven/UtilCode#files/com/blankj/utilcode) |
| 对应版本 | 11.6 | 2.0.3 | 0.12 | 4.8.0 | 3.0.0 | 1.4.0 | 1.30.5 |
| 框架体积 | [28 KB](https://bintray.com/getactivity/maven/xxpermissions#files/com/hjq/xxpermissions) | [127 KB](https://mvnrepository.com/artifact/com.yanzhenjie/permission) | [28 KB](https://jitpack.io/#com.github.tbruyelle/rxpermissions) | [91 KB](https://bintray.com/hotchemi/org.permissionsdispatcher/permissionsdispatcher-processor#files/org/permissionsdispatcher/permissionsdispatcher-processor) | [48 KB](https://bintray.com/easygoogle/EasyPermissions/easypermissions#files/pub/devrel/easypermissions) | [32 KB](https://bintray.com/guolindev/maven/permissionx#files/com/permissionx/guolindev/permissionx) | [483 KB](https://bintray.com/blankj/maven/UtilCode#files/com/blankj/utilcode) |
| 安装包权限 ||||||||
| 悬浮窗权限 ||||||||
| 通知栏权限 ||||||||
Expand Down
Binary file modified XXPermissions.apk
Binary file not shown.
6 changes: 3 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "com.hjq.permissions.demo"
minSdkVersion 14
targetSdkVersion 30
versionCode 1150
versionName "11.5"
versionCode 1160
versionName "11.6"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

Expand Down Expand Up @@ -43,7 +43,7 @@ dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'

// 吐司框架:https://github.com/getActivity/ToastUtils
implementation 'com.github.getActivity:ToastUtils:9.2'
implementation 'com.github.getActivity:ToastUtils:9.5'

// 内存泄漏检测:https://github.com/square/leakcanary
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ buildscript {
maven { url 'https://jitpack.io' }
mavenCentral()
google()
// noinspection JcenterRepositoryObsolete
jcenter()
}
dependencies {
Expand All @@ -24,6 +25,7 @@ allprojects {
maven { url 'https://jitpack.io' }
mavenCentral()
google()
// noinspection JcenterRepositoryObsolete
jcenter()
}
}
Expand Down
4 changes: 2 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ android {

defaultConfig {
minSdkVersion 11
versionCode 1150
versionName "11.5"
versionCode 1160
versionName "11.6"
}

// 使用 JDK 1.8
Expand Down
23 changes: 19 additions & 4 deletions library/src/main/java/com/hjq/permissions/Permission.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@ private Permission() {}
*/
public static final String MANAGE_EXTERNAL_STORAGE = "android.permission.MANAGE_EXTERNAL_STORAGE";

/** 安装应用权限(特殊权限,需要 Android 8.0 及以上) */
/**
* 安装应用权限(特殊权限,需要 Android 8.0 及以上)
*
* Android 11 特性调整,安装外部来源应用需要重启 App:https://cloud.tencent.com/developer/news/637591
*/
public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";

/** 通知栏权限(特殊权限,需要 Android 6.0 及以上,注意此权限不需要在清单文件中注册也能申请) */
public static final String NOTIFICATION_SERVICE = "android.permission.NOTIFICATION_SERVICE";

/** 悬浮窗权限(特殊权限,需要 Android 6.0 及以上) */
/**
* 悬浮窗权限(特殊权限,需要 Android 6.0 及以上)
*
* 在 Android 10 及之前的版本能跳转到应用悬浮窗设置页面,而在 Android 11 及之后的版本只能跳转到系统设置悬浮窗管理列表了
* 具体详情请看官方文档解释:https://developer.android.google.cn/reference/android/provider/Settings#ACTION_MANAGE_OVERLAY_PERMISSION
*/
public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";

/** 系统设置权限(特殊权限,需要 Android 6.0 及以上) */
Expand Down Expand Up @@ -66,14 +75,20 @@ private Permission() {}
/**
* 读取照片中的地理位置(需要 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";

/** 读取电话状态(这个权限在某些手机上面是申请失败的) */
/**
* 读取电话状态
*
* 需要注意的是:这个权限在某些手机上面是没办法获取到的,因为某些系统禁止应用获得该权限
* 所以你要是申请了这个权限之后没有弹授权框,而是直接回调授权失败方法
* 请不要惊慌,这个不是 Bug、不是 Bug、不是 Bug,而是正常现象
*/
public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
/** 拨打电话 */
public static final String CALL_PHONE = "android.permission.CALL_PHONE";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ static void optimizeDeprecatedPermission(List<String> requestPermissions) {
if (requestPermissions.contains(Permission.READ_EXTERNAL_STORAGE) ||
requestPermissions.contains(Permission.WRITE_EXTERNAL_STORAGE)) {
// 检测是否有旧版的存储权限,有的话直接抛出异常,请不要自己动态申请这两个权限
throw new IllegalArgumentException("Please do not apply for these two permissions dynamically");
throw new IllegalArgumentException("If you have applied for MANAGE_EXTERNAL_STORAGE permissions, " +
"do not apply for the READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions");
}

if (!PermissionUtils.isAndroid11()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ static <T> ArrayList<T> asArrayList(T... array) {
return list;
}

@SafeVarargs
static <T> ArrayList<T> asArrayLists(T[]... arrays) {
ArrayList<T> list = new ArrayList<>();
if (arrays == null || arrays.length == 0) {
Expand Down
33 changes: 24 additions & 9 deletions library/src/main/java/com/hjq/permissions/XXPermissions.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* time : 2018/06/15
* desc : Android 危险权限请求类
*/
@SuppressWarnings("deprecation, unused")
@SuppressWarnings({"unused", "deprecation"})
public final class XXPermissions {

/** 权限设置页跳转请求码 */
Expand All @@ -23,10 +23,10 @@ public final class XXPermissions {
/** 权限请求拦截器 */
private static IPermissionInterceptor sPermissionInterceptor;

/** 调试模式 */
/** 当前是否为调试模式 */
private static Boolean sDebugMode;

/** 分区存储 */
/** 是否适配了分区存储 */
private static boolean sScopedStorage;

/**
Expand Down Expand Up @@ -270,13 +270,18 @@ public static void startPermissionActivity(Activity activity, String[]... permis
startPermissionActivity(activity, PermissionUtils.asArrayLists(permissions));
}

public static void startPermissionActivity(Activity activity, List<String> permissions) {
startPermissionActivity(activity, permissions, REQUEST_CODE);
}

/**
* 跳转到应用权限设置页
*
* @param permissions 没有授予或者被拒绝的权限组
* @param requestCode Activity 跳转请求码
*/
public static void startPermissionActivity(Activity activity, List<String> permissions) {
activity.startActivityForResult(PermissionSettingPage.getSmartPermissionIntent(activity, permissions), REQUEST_CODE);
public static void startPermissionActivity(Activity activity, List<String> permissions, int requestCode) {
activity.startActivityForResult(PermissionSettingPage.getSmartPermissionIntent(activity, permissions), requestCode);
}

/* android.app.Fragment */
Expand All @@ -293,17 +298,22 @@ public static void startPermissionActivity(Fragment fragment, String[]... permis
startPermissionActivity(fragment, PermissionUtils.asArrayLists(permissions));
}

public static void startPermissionActivity(Fragment fragment, List<String> permissions) {
startPermissionActivity(fragment, permissions, REQUEST_CODE);
}

/**
* 跳转到应用权限设置页
*
* @param permissions 没有授予或者被拒绝的权限组
* @param requestCode Activity 跳转请求码
*/
public static void startPermissionActivity(Fragment fragment, List<String> permissions) {
public static void startPermissionActivity(Fragment fragment, List<String> permissions, int requestCode) {
Activity activity = fragment.getActivity();
if (activity == null) {
return;
}
fragment.startActivityForResult(PermissionSettingPage.getSmartPermissionIntent(activity, permissions), REQUEST_CODE);
fragment.startActivityForResult(PermissionSettingPage.getSmartPermissionIntent(activity, permissions), requestCode);
}

/* android.support.v4.app.Fragment */
Expand All @@ -320,16 +330,21 @@ public static void startPermissionActivity(android.support.v4.app.Fragment fragm
startPermissionActivity(fragment, PermissionUtils.asArrayLists(permissions));
}

public static void startPermissionActivity(android.support.v4.app.Fragment fragment, List<String> permissions) {
startPermissionActivity(fragment, permissions, REQUEST_CODE);
}

/**
* 跳转到应用权限设置页
*
* @param permissions 没有授予或者被拒绝的权限组
* @param requestCode Activity 跳转请求码
*/
public static void startPermissionActivity(android.support.v4.app.Fragment fragment, List<String> permissions) {
public static void startPermissionActivity(android.support.v4.app.Fragment fragment, List<String> permissions, int requestCode) {
Activity activity = fragment.getActivity();
if (activity == null) {
return;
}
fragment.startActivityForResult(PermissionSettingPage.getSmartPermissionIntent(activity, permissions), REQUEST_CODE);
fragment.startActivityForResult(PermissionSettingPage.getSmartPermissionIntent(activity, permissions), requestCode);
}
}

0 comments on commit a047b5c

Please sign in to comment.