diff --git a/HelpDoc-en.md b/HelpDoc-en.md index 4dae2d3..5081cad 100644 --- a/HelpDoc-en.md +++ b/HelpDoc-en.md @@ -123,7 +123,7 @@ XXPermissions.with(MainActivity.this) #### What should I do if the dialog box pops up before and after the permission application -* An interceptor interface is provided inside the framework. It is enough to implement the interface provided [ IPermissionInterceptor ](/library/src/main/java/com/hjq/permissions/IPermissionInterceptor.java) in the framework. For specific implementation, please refer to the [ PermissionInterceptor ](app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java) class provided in Demo. It is recommended to download the source code and read it, and then introduce the code into the project +* An interceptor interface is provided inside the framework. It is enough to implement the interface provided [OnPermissionInterceptor](/library/src/main/java/com/hjq/permissions/OnPermissionInterceptor.java) in the framework. For specific implementation, please refer to the [ PermissionInterceptor ](app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java) class provided in Demo. It is recommended to download the source code and read it, and then introduce the code into the project * The way to use interception is also very simple. There are two specific settings, one for local settings and the other for global settings. diff --git a/HelpDoc-zh.md b/HelpDoc-zh.md index 08bd013..12bb3e2 100644 --- a/HelpDoc-zh.md +++ b/HelpDoc-zh.md @@ -129,7 +129,7 @@ XXPermissions.with(MainActivity.this) #### 我想在申请前和申请后统一弹对话框该怎么处理 -* 框架内部有提供一个拦截器接口,通过实现框架中提供的 [IPermissionInterceptor](/library/src/main/java/com/hjq/permissions/IPermissionInterceptor.java) 接口即可,具体实现可参考 Demo 中提供的 [PermissionInterceptor](app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java) 类,建议下载源码后进行阅读,再将代码引入到项目中 +* 框架内部有提供一个拦截器接口,通过实现框架中提供的 [OnPermissionInterceptor](/library/src/main/java/com/hjq/permissions/OnPermissionInterceptor.java) 接口即可,具体实现可参考 Demo 中提供的 [PermissionInterceptor](app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java) 类,建议下载源码后进行阅读,再将代码引入到项目中 * 使用拦截的方式也很简单,具体有两种设置方式,一种针对局部设置,另外一种是全局设置 @@ -334,10 +334,10 @@ context.startActivity(intent); #### 如何应对国内某些应用商店在明确拒绝权限后 48 小时内不允许再次申请的问题 -* 首先这种属于业务逻辑的问题,框架本身是不会做这种事情的,但并非不能实现,这得益于框架良好的设计,框架内部提供了一个叫 IPermissionInterceptor 的拦截器类,当前有权限申请的时候,会走 requestPermissions 方法的回调,你可以重写这个方法的逻辑,先去判断要申请的权限是否在 48 小时内已经申请过了一次了,如果没有的话,就走权限申请的流程,如果有的话,那么就直接回调权限申请失败的方法。 +* 首先这种属于业务逻辑的问题,框架本身是不会做这种事情的,但并非不能实现,这得益于框架良好的设计,框架内部提供了一个叫 OnPermissionInterceptor 的拦截器类,当前有权限申请的时候,会走 requestPermissions 方法的回调,你可以重写这个方法的逻辑,先去判断要申请的权限是否在 48 小时内已经申请过了一次了,如果没有的话,就走权限申请的流程,如果有的话,那么就直接回调权限申请失败的方法。 ```java -public final class PermissionInterceptor implements IPermissionInterceptor { +public final class PermissionInterceptor implements OnPermissionInterceptor { private static final String SP_NAME_PERMISSION_REQUEST_TIME_RECORD = "permission_request_time_record"; @@ -359,7 +359,7 @@ public final class PermissionInterceptor implements IPermissionInterceptor { } sharedPreferences.edit().putLong(permissionKey, System.currentTimeMillis()).apply(); // 如果之前没有申请过权限,或者距离上次申请已经超过了 48 个小时,则进行申请权限 - IPermissionInterceptor.super.requestPermissions(activity, allPermissions, callback); + OnPermissionInterceptor.super.requestPermissions(activity, allPermissions, callback); } @Override diff --git a/README-en.md b/README-en.md index c7acec6..bbadfcd 100644 --- a/README-en.md +++ b/README-en.md @@ -6,7 +6,7 @@ * project address: [Github](https://github.com/getActivity/XXPermissions) -* [Click here to download demo apk directly](https://github.com/getActivity/XXPermissions/releases/download/18.5/XXPermissions.apk) +* [Click here to download demo apk directly](https://github.com/getActivity/XXPermissions/releases/download/18.6/XXPermissions.apk) ![](picture/en/demo_request_permission_activity.jpg) ![](picture/en/demo_request_single_permission.jpg) ![](picture/en/demo_request_group_permission.jpg) @@ -55,7 +55,7 @@ android { dependencies { // Permission request framework:https://github.com/getActivity/XXPermissions - implementation 'com.github.getActivity:XXPermissions:18.5' + implementation 'com.github.getActivity:XXPermissions:18.6' } ``` @@ -190,7 +190,7 @@ XXPermissions.startPermissionActivity(Fragment fragment, String... permissions, // Setting not to trigger error detection mechanism (global setting) XXPermissions.setCheckMode(false); // Set permission request interceptor (global setting) -XXPermissions.setInterceptor(new IPermissionInterceptor() {}); +XXPermissions.setInterceptor(new OnPermissionInterceptor() {}); ``` #### Framework proguard rules @@ -217,7 +217,7 @@ XXPermissions.setInterceptor(new IPermissionInterceptor() {}); | Adaptation details | [XXPermissions](https://github.com/getActivity/XXPermissions) | [AndPermission](https://github.com/yanzhenjie/AndPermission) | [PermissionX](https://github.com/guolindev/PermissionX) | [AndroidUtilCode-PermissionUtils](https://github.com/Blankj/AndroidUtilCode) | [PermissionsDispatcher](https://github.com/permissions-dispatcher/PermissionsDispatcher) | [RxPermissions](https://github.com/tbruyelle/RxPermissions) | [EasyPermissions](https://github.com/googlesamples/easypermissions) | |:-------------------------------------------------------------:| :----------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------: | -| Corresponding version | 18.5 | 2.0.3 | 1.7.1 | 1.31.0 | 4.9.2 | 0.12 | 3.0.0 | +| Corresponding version | 18.6 | 2.0.3 | 1.7.1 | 1.31.0 | 4.9.2 | 0.12 | 3.0.0 | | Number of issues | [![](https://img.shields.io/github/issues/getActivity/XXPermissions.svg)](https://github.com/getActivity/XXPermissions/issues) | [![](https://img.shields.io/github/issues/yanzhenjie/AndPermission.svg)](https://github.com/yanzhenjie/AndPermission/issues) | [![](https://img.shields.io/github/issues/guolindev/PermissionX.svg)](https://github.com/guolindev/PermissionX/issues) | [![](https://img.shields.io/github/issues/Blankj/AndroidUtilCode.svg)](https://github.com/Blankj/AndroidUtilCode/issues) | [![](https://img.shields.io/github/issues/permissions-dispatcher/PermissionsDispatcher.svg)](https://github.com/permissions-dispatcher/PermissionsDispatcher/issues) | [![](https://img.shields.io/github/issues/tbruyelle/RxPermissions.svg)](https://github.com/tbruyelle/RxPermissions/issues) | [![](https://img.shields.io/github/issues/googlesamples/easypermissions.svg)](https://github.com/googlesamples/easypermissions/issues) | | Framework volume | 85 KB | 127 KB | 97 KB | 500 KB | 99 KB | 28 KB | 48 KB | | Framework Maintenance Status | **In maintenance** | stop maintenance | **In maintenance** | stop maintenance | stop maintenance | stop maintenance | stop maintenance | diff --git a/README.md b/README.md index 82e7b63..ce60131 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ * 博文地址:[一句代码搞定权限请求,从未如此简单](https://www.jianshu.com/p/c69ff8a445ed) -* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/XXPermissions/releases/download/18.5/XXPermissions.apk) +* 可以扫码下载 Demo 进行演示或者测试,如果扫码下载不了的,[点击此处可直接下载](https://github.com/getActivity/XXPermissions/releases/download/18.6/XXPermissions.apk) ![](picture/zh/download_demo_apk_qr_code.png) @@ -61,7 +61,7 @@ android { dependencies { // 权限请求框架:https://github.com/getActivity/XXPermissions - implementation 'com.github.getActivity:XXPermissions:18.5' + implementation 'com.github.getActivity:XXPermissions:18.6' } ``` @@ -196,7 +196,7 @@ XXPermissions.startPermissionActivity(Fragment fragment, String... permissions, // 设置不触发错误检测机制(全局设置) XXPermissions.setCheckMode(false); // 设置权限申请拦截器(全局设置) -XXPermissions.setInterceptor(new IPermissionInterceptor() {}); +XXPermissions.setInterceptor(new OnPermissionInterceptor() {}); ``` #### 框架混淆规则 @@ -223,7 +223,7 @@ XXPermissions.setInterceptor(new IPermissionInterceptor() {}); | 适配细节 | [XXPermissions](https://github.com/getActivity/XXPermissions) | [AndPermission](https://github.com/yanzhenjie/AndPermission) | [PermissionX](https://github.com/guolindev/PermissionX) | [AndroidUtilCode-PermissionUtils](https://github.com/Blankj/AndroidUtilCode) | [PermissionsDispatcher](https://github.com/permissions-dispatcher/PermissionsDispatcher) | [RxPermissions](https://github.com/tbruyelle/RxPermissions) | [EasyPermissions](https://github.com/googlesamples/easypermissions) | | :--------: | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: | -| 对应版本 | 18.5 | 2.0.3 | 1.7.1 | 1.31.0 | 4.9.2 | 0.12 | 3.0.0 | +| 对应版本 | 18.6 | 2.0.3 | 1.7.1 | 1.31.0 | 4.9.2 | 0.12 | 3.0.0 | | issues 数 | [![](https://img.shields.io/github/issues/getActivity/XXPermissions.svg)](https://github.com/getActivity/XXPermissions/issues) | [![](https://img.shields.io/github/issues/yanzhenjie/AndPermission.svg)](https://github.com/yanzhenjie/AndPermission/issues) | [![](https://img.shields.io/github/issues/guolindev/PermissionX.svg)](https://github.com/guolindev/PermissionX/issues) | [![](https://img.shields.io/github/issues/Blankj/AndroidUtilCode.svg)](https://github.com/Blankj/AndroidUtilCode/issues) | [![](https://img.shields.io/github/issues/permissions-dispatcher/PermissionsDispatcher.svg)](https://github.com/permissions-dispatcher/PermissionsDispatcher/issues) | [![](https://img.shields.io/github/issues/tbruyelle/RxPermissions.svg)](https://github.com/tbruyelle/RxPermissions/issues) | [![](https://img.shields.io/github/issues/googlesamples/easypermissions.svg)](https://github.com/googlesamples/easypermissions/issues) | | 框架体积 | 85 KB | 127 KB | 97 KB | 500 KB | 99 KB | 28 KB | 48 KB | | 框架维护状态 |**维护中**| 停止维护 | 停止维护 | 停止维护 | 停止维护 | 停止维护 | 停止维护 | @@ -438,18 +438,6 @@ XXPermissions.setInterceptor(new IPermissionInterceptor() {}); ![](https://raw.githubusercontent.com/getActivity/Donate/master/picture/pay_ali.png) ![](https://raw.githubusercontent.com/getActivity/Donate/master/picture/pay_wechat.png) -#### 广告区 - -* 我现在任腾讯云服务器推广大使,大家如果有购买服务器的需求,可以通过下面的链接购买 - -[![](https://upload-dianshi-1255598498.file.myqcloud.com/upload/nodir/345X200-9ae456f58874df499adf7c331c02cb0fed12b81d.jpg)](https://curl.qcloud.com/A6cYskvv) - -[【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中](https://curl.qcloud.com/A6cYskvv) - -[![](https://upload-dianshi-1255598498.file.myqcloud.com/345-200-b28f7dee9552f4241ea6a543f15a9798049701d4.jpg)](https://curl.qcloud.com/up4fQsdn) - -[【腾讯云】中小企业福利专场,多款刚需产品,满足企业通用场景需求](https://curl.qcloud.com/up4fQsdn) - ## License ```text diff --git a/app/build.gradle b/app/build.gradle index 5180b68..a77f3ec 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.hjq.permissions.demo" minSdkVersion 16 targetSdkVersion 34 - versionCode 1805 - versionName "18.5" + versionCode 1806 + versionName "18.6" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -61,7 +61,7 @@ dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' // 吐司框架:https://github.com/getActivity/Toaster - implementation 'com.github.getActivity:Toaster:12.5' + implementation 'com.github.getActivity:Toaster:12.6' // 内存泄漏检测:https://github.com/square/leakcanary debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c7fc4e2..a6d315c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -30,9 +30,6 @@ - - - @@ -103,6 +100,11 @@ + + + \ No newline at end of file diff --git a/app/src/main/java/com/hjq/permissions/demo/MainActivity.java b/app/src/main/java/com/hjq/permissions/demo/MainActivity.java index 760e042..e45eeda 100644 --- a/app/src/main/java/com/hjq/permissions/demo/MainActivity.java +++ b/app/src/main/java/com/hjq/permissions/demo/MainActivity.java @@ -77,19 +77,19 @@ public void onClick(View view) { if (viewId == R.id.btn_main_request_single_permission) { XXPermissions.with(this) - .permission(Permission.CAMERA) - .interceptor(new PermissionInterceptor()) - .request(new OnPermissionCallback() { - - @Override - public void onGranted(@NonNull List permissions, boolean allGranted) { - if (!allGranted) { - return; - } - toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + .permission(Permission.CAMERA) + .interceptor(new PermissionInterceptor()) + .request(new OnPermissionCallback() { + + @Override + public void onGranted(@NonNull List permissions, boolean allGranted) { + if (!allGranted) { + return; } - }); + toast(String.format(getString(R.string.demo_obtain_permission_success_hint), + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); + } + }); } else if (viewId == R.id.btn_main_request_group_permission) { @@ -105,7 +105,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -125,7 +125,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -143,7 +143,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -160,7 +160,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); addCountStepListener(); } }); @@ -190,7 +190,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); } @@ -219,7 +219,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); } @@ -252,7 +252,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); new Thread(new Runnable() { @Override public void run() { @@ -293,7 +293,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); } @@ -325,7 +325,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); } @@ -344,7 +344,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -361,7 +361,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -378,7 +378,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -395,7 +395,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -422,7 +422,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); } @@ -441,7 +441,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { toggleNotificationListenerService(); } @@ -461,7 +461,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -478,7 +478,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -495,7 +495,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -512,7 +512,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -529,7 +529,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -546,7 +546,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); } }); @@ -563,7 +563,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { return; } toast(String.format(getString(R.string.demo_obtain_permission_success_hint), - PermissionNameConvert.getPermissionString(MainActivity.this, permissions))); + PermissionNameConvert.getPermissionNames(MainActivity.this, permissions))); getAppList(); } }); diff --git a/app/src/main/java/com/hjq/permissions/demo/PermissionDescriptionConvert.java b/app/src/main/java/com/hjq/permissions/demo/PermissionDescriptionConvert.java new file mode 100644 index 0000000..8cb6a1d --- /dev/null +++ b/app/src/main/java/com/hjq/permissions/demo/PermissionDescriptionConvert.java @@ -0,0 +1,38 @@ +package com.hjq.permissions.demo; + +import android.content.Context; +import android.support.annotation.NonNull; +import java.util.List; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/XXPermissions + * time : 2023/01/02 + * desc : 权限描述转换器 + */ +public final class PermissionDescriptionConvert { + + /** + * 获取权限描述 + */ + public static String getPermissionDescription(Context context, List permissions) { + StringBuilder stringBuilder = new StringBuilder(); + List permissionNames = PermissionNameConvert.permissionsToNames(context, permissions); + for (String permissionName : permissionNames) { + stringBuilder.append(permissionName) + .append(context.getString(R.string.common_permission_colon)) + .append(permissionsToDescription(context, permissionName)) + .append("\n"); + } + return stringBuilder.toString().trim(); + } + + /** + * 将权限名称列表转换成对应权限描述 + */ + @NonNull + public static String permissionsToDescription(Context context, String permissionName) { + // 请根据权限名称转换成对应权限说明 + return "用于 xxx 业务"; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java b/app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java index c23dbf0..f97fa6c 100644 --- a/app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java +++ b/app/src/main/java/com/hjq/permissions/demo/PermissionInterceptor.java @@ -19,14 +19,13 @@ import android.view.WindowManager; import android.widget.PopupWindow; import android.widget.TextView; -import com.hjq.permissions.IPermissionInterceptor; +import com.hjq.permissions.OnPermissionInterceptor; import com.hjq.permissions.OnPermissionCallback; import com.hjq.permissions.OnPermissionPageCallback; import com.hjq.permissions.Permission; import com.hjq.permissions.PermissionFragment; import com.hjq.permissions.XXPermissions; import com.hjq.toast.Toaster; -import java.util.ArrayList; import java.util.List; /** @@ -35,7 +34,7 @@ * time : 2021/01/04 * desc : 权限申请拦截器 */ -public final class PermissionInterceptor implements IPermissionInterceptor { +public final class PermissionInterceptor implements OnPermissionInterceptor { public static final Handler HANDLER = new Handler(Looper.getMainLooper()); @@ -45,11 +44,26 @@ public final class PermissionInterceptor implements IPermissionInterceptor { /** 权限申请说明 Popup */ private PopupWindow mPermissionPopup; + /** 权限说明文案 */ + @Nullable + private String mPermissionDescription; + + public PermissionInterceptor() { + this(null); + } + + public PermissionInterceptor(@Nullable String permissionDescription) { + mPermissionDescription = permissionDescription; + } + @Override public void launchPermissionRequest(@NonNull Activity activity, @NonNull List allPermissions, @Nullable OnPermissionCallback callback) { mRequestFlag = true; List deniedPermissions = XXPermissions.getDenied(activity, allPermissions); - String message = activity.getString(R.string.common_permission_message, PermissionNameConvert.getPermissionString(activity, deniedPermissions)); + + if (TextUtils.isEmpty(mPermissionDescription)) { + mPermissionDescription = generatePermissionDescription(activity, deniedPermissions); + } ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); int activityOrientation = activity.getResources().getConfiguration().orientation; @@ -73,7 +87,7 @@ public void launchPermissionRequest(@NonNull Activity activity, @NonNull List(allPermissions), this, callback); + PermissionFragment.launch(activity, allPermissions, this, callback); // 延迟 300 毫秒是为了避免出现 PopupWindow 显示然后立马消失的情况 // 因为框架没有办法在还没有申请权限的情况下,去判断权限是否永久拒绝了,必须要在发起权限申请之后 // 所以只能通过延迟显示 PopupWindow 来做这件事,如果 300 毫秒内权限申请没有结束,证明本次申请的权限没有永久拒绝 @@ -85,17 +99,17 @@ public void launchPermissionRequest(@NonNull Activity activity, @NonNull List= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed())) { return; } - showPopupWindow(activity, decorView, message); + showPopupWindow(activity, decorView, mPermissionDescription); }, 300); } else { // 注意:这里的 Dialog 只是示例,没有用 DialogFragment 来处理 Dialog 生命周期 new AlertDialog.Builder(activity) - .setTitle(R.string.common_permission_description) - .setMessage(message) + .setTitle(R.string.common_permission_description_title) + .setMessage(mPermissionDescription) .setCancelable(false) .setPositiveButton(R.string.common_permission_granted, (dialog, which) -> { dialog.dismiss(); - PermissionFragment.launch(activity, new ArrayList<>(allPermissions), + PermissionFragment.launch(activity, allPermissions, PermissionInterceptor.this, callback); }) .setNegativeButton(R.string.common_permission_denied, (dialog, which) -> { @@ -172,6 +186,13 @@ public void finishPermissionRequest(@NonNull Activity activity, @NonNull List permissions) { + return PermissionDescriptionConvert.getPermissionDescription(context, permissions); + } + private void showPopupWindow(Activity activity, ViewGroup decorView, String message) { if (mPermissionPopup == null) { View contentView = LayoutInflater.from(activity) diff --git a/app/src/main/java/com/hjq/permissions/demo/PermissionNameConvert.java b/app/src/main/java/com/hjq/permissions/demo/PermissionNameConvert.java index ad7646e..479a1c3 100644 --- a/app/src/main/java/com/hjq/permissions/demo/PermissionNameConvert.java +++ b/app/src/main/java/com/hjq/permissions/demo/PermissionNameConvert.java @@ -18,7 +18,7 @@ public final class PermissionNameConvert { /** * 获取权限名称 */ - public static String getPermissionString(Context context, List permissions) { + public static String getPermissionNames(Context context, List permissions) { return listToString(context, permissionsToNames(context, permissions)); } @@ -66,7 +66,7 @@ public static List permissionsToNames(Context context, List perm } case Permission.READ_MEDIA_IMAGES: case Permission.READ_MEDIA_VIDEO: - case Permission.READ_MEDIA_VISUAL_USER_SELECTED:{ + case Permission.READ_MEDIA_VISUAL_USER_SELECTED: { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { String hint = context.getString(R.string.common_permission_image_and_video); if (!permissionNames.contains(hint)) { diff --git a/app/src/main/res/layout/permission_description_popup.xml b/app/src/main/res/layout/permission_description_popup.xml index 9fc77cf..6a62ae9 100644 --- a/app/src/main/res/layout/permission_description_popup.xml +++ b/app/src/main/res/layout/permission_description_popup.xml @@ -20,7 +20,7 @@ android:layout_marginLeft="15dp" android:layout_marginTop="12dp" android:layout_marginRight="15dp" - android:text="@string/common_permission_description" + android:text="@string/common_permission_description_title" android:textColor="#333333" android:textSize="14sp" android:textStyle="bold" /> @@ -34,8 +34,9 @@ android:layout_marginRight="15dp" android:layout_marginBottom="12dp" android:textColor="#666666" + android:lineSpacingExtra="3dp" android:textSize="13sp" - tools:text="@string/common_permission_message" /> + tools:text="xxx" /> diff --git a/app/src/main/res/values-zh/strings_permission.xml b/app/src/main/res/values-zh/strings_permission.xml index 32add92..fe1629a 100644 --- a/app/src/main/res/values-zh/strings_permission.xml +++ b/app/src/main/res/values-zh/strings_permission.xml @@ -1,8 +1,7 @@ - 权限说明 - 使用此功能需要先授予%s + 权限说明 授予 取消 @@ -21,6 +20,7 @@ 权限 + 日历权限 相机权限 diff --git a/app/src/main/res/values/strings_permission.xml b/app/src/main/res/values/strings_permission.xml index d0d9542..5315877 100644 --- a/app/src/main/res/values/strings_permission.xml +++ b/app/src/main/res/values/strings_permission.xml @@ -1,8 +1,7 @@ - Permission description - %s needs to be granted to use this feature + Permission description Granted Denied @@ -21,6 +20,7 @@ permission , + : calendar permission camera permission diff --git a/library/build.gradle b/library/build.gradle index 5d8c31c..13a03c1 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -5,8 +5,8 @@ android { defaultConfig { minSdkVersion 14 - versionCode 1805 - versionName "18.5" + versionCode 1806 + versionName "18.6" } // 使用 JDK 1.8 diff --git a/library/src/main/java/com/hjq/permissions/AndroidManifestInfo.java b/library/src/main/java/com/hjq/permissions/AndroidManifestInfo.java index 9135d84..f3ac377 100644 --- a/library/src/main/java/com/hjq/permissions/AndroidManifestInfo.java +++ b/library/src/main/java/com/hjq/permissions/AndroidManifestInfo.java @@ -26,6 +26,7 @@ final class AndroidManifestInfo { final List permissionInfoList = new ArrayList<>(); /** Application 节点信息 */ + @Nullable ApplicationInfo applicationInfo; /** Activity 节点信息 */ diff --git a/library/src/main/java/com/hjq/permissions/AndroidManifestParser.java b/library/src/main/java/com/hjq/permissions/AndroidManifestParser.java index aad50cc..67b6a03 100644 --- a/library/src/main/java/com/hjq/permissions/AndroidManifestParser.java +++ b/library/src/main/java/com/hjq/permissions/AndroidManifestParser.java @@ -44,6 +44,8 @@ final class AndroidManifestParser { private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supportsPictureInPicture"; private static final String ATTR_PERMISSION = "permission"; + private AndroidManifestParser() {} + /** * 解析 apk 包中的清单文件 * @@ -53,54 +55,52 @@ final class AndroidManifestParser { @NonNull static AndroidManifestInfo parseAndroidManifest(@NonNull Context context, int apkCookie) throws IOException, XmlPullParserException { AndroidManifestInfo manifestInfo = new AndroidManifestInfo(); - XmlResourceParser parser = context.getAssets(). - openXmlResourceParser(apkCookie, ANDROID_MANIFEST_FILE_NAME); - do { - // 当前节点必须为标签头部 - if (parser.getEventType() != XmlResourceParser.START_TAG) { - continue; - } + try (XmlResourceParser parser = context.getAssets(). + openXmlResourceParser(apkCookie, ANDROID_MANIFEST_FILE_NAME)) { - String tagName = parser.getName(); + do { + // 当前节点必须为标签头部 + if (parser.getEventType() != XmlResourceParser.START_TAG) { + continue; + } - if (TextUtils.equals(TAG_MANIFEST, tagName)) { - manifestInfo.packageName = parser.getAttributeValue(null, ATTR_PACKAGE); - } + String tagName = parser.getName(); - if (TextUtils.equals(TAG_USES_SDK, tagName)) { - manifestInfo.usesSdkInfo = parseUsesSdkFromXml(parser); - } + if (TextUtils.equals(TAG_MANIFEST, tagName)) { + manifestInfo.packageName = parser.getAttributeValue(null, ATTR_PACKAGE); + } - if (TextUtils.equals(TAG_USES_PERMISSION, tagName) || - TextUtils.equals(TAG_USES_PERMISSION_SDK_23, tagName) || - TextUtils.equals(TAG_USES_PERMISSION_SDK_M, tagName)) { - AndroidManifestInfo.PermissionInfo permissionInfo = parsePermissionFromXml(parser); - manifestInfo.permissionInfoList.add(permissionInfo); - } + if (TextUtils.equals(TAG_USES_SDK, tagName)) { + manifestInfo.usesSdkInfo = parseUsesSdkFromXml(parser); + } - if (TextUtils.equals(TAG_APPLICATION, tagName)) { - manifestInfo.applicationInfo = parseApplicationFromXml(parser); - } + if (TextUtils.equals(TAG_USES_PERMISSION, tagName) || + TextUtils.equals(TAG_USES_PERMISSION_SDK_23, tagName) || + TextUtils.equals(TAG_USES_PERMISSION_SDK_M, tagName)) { + manifestInfo.permissionInfoList.add(parsePermissionFromXml(parser)); + } - if (TextUtils.equals(TAG_ACTIVITY, tagName) || - TextUtils.equals(TAG_ACTIVITY_ALIAS, tagName)) { - AndroidManifestInfo.ActivityInfo activityInfo = parseActivityFromXml(parser); - manifestInfo.activityInfoList.add(activityInfo); - } + if (TextUtils.equals(TAG_APPLICATION, tagName)) { + manifestInfo.applicationInfo = parseApplicationFromXml(parser); + } - if (TextUtils.equals(TAG_SERVICE, tagName)) { - AndroidManifestInfo.ServiceInfo serviceInfo = parseServerFromXml(parser); - manifestInfo.serviceInfoList.add(serviceInfo); - } + if (TextUtils.equals(TAG_ACTIVITY, tagName) || + TextUtils.equals(TAG_ACTIVITY_ALIAS, tagName)) { + manifestInfo.activityInfoList.add(parseActivityFromXml(parser)); + } - } while (parser.next() != XmlResourceParser.END_DOCUMENT); + if (TextUtils.equals(TAG_SERVICE, tagName)) { + manifestInfo.serviceInfoList.add(parseServerFromXml(parser)); + } - parser.close(); + } while (parser.next() != XmlResourceParser.END_DOCUMENT); + } return manifestInfo; } + @NonNull private static AndroidManifestInfo.UsesSdkInfo parseUsesSdkFromXml(@NonNull XmlResourceParser parser) { AndroidManifestInfo.UsesSdkInfo usesSdkInfo = new AndroidManifestInfo.UsesSdkInfo(); usesSdkInfo.minSdkVersion = parser.getAttributeIntValue(ANDROID_NAMESPACE_URI, @@ -108,6 +108,7 @@ private static AndroidManifestInfo.UsesSdkInfo parseUsesSdkFromXml(@NonNull XmlR return usesSdkInfo; } + @NonNull private static AndroidManifestInfo.PermissionInfo parsePermissionFromXml(@NonNull XmlResourceParser parser) { AndroidManifestInfo.PermissionInfo permissionInfo = new AndroidManifestInfo.PermissionInfo(); permissionInfo.name = parser.getAttributeValue(ANDROID_NAMESPACE_URI, ATTR_NAME); @@ -118,6 +119,7 @@ private static AndroidManifestInfo.PermissionInfo parsePermissionFromXml(@NonNul return permissionInfo; } + @NonNull private static AndroidManifestInfo.ApplicationInfo parseApplicationFromXml(@NonNull XmlResourceParser parser) { AndroidManifestInfo.ApplicationInfo applicationInfo = new AndroidManifestInfo.ApplicationInfo(); applicationInfo.name = parser.getAttributeValue(ANDROID_NAMESPACE_URI, ATTR_NAME); @@ -126,6 +128,7 @@ private static AndroidManifestInfo.ApplicationInfo parseApplicationFromXml(@NonN return applicationInfo; } + @NonNull private static AndroidManifestInfo.ActivityInfo parseActivityFromXml(@NonNull XmlResourceParser parser) { AndroidManifestInfo.ActivityInfo activityInfo = new AndroidManifestInfo.ActivityInfo(); activityInfo.name = parser.getAttributeValue(ANDROID_NAMESPACE_URI, ATTR_NAME); @@ -134,6 +137,7 @@ private static AndroidManifestInfo.ActivityInfo parseActivityFromXml(@NonNull Xm return activityInfo; } + @NonNull private static AndroidManifestInfo.ServiceInfo parseServerFromXml(@NonNull XmlResourceParser parser) { AndroidManifestInfo.ServiceInfo serviceInfo = new AndroidManifestInfo.ServiceInfo(); serviceInfo.name = parser.getAttributeValue(ANDROID_NAMESPACE_URI, ATTR_NAME); diff --git a/library/src/main/java/com/hjq/permissions/IPermissionInterceptor.java b/library/src/main/java/com/hjq/permissions/OnPermissionInterceptor.java similarity index 94% rename from library/src/main/java/com/hjq/permissions/IPermissionInterceptor.java rename to library/src/main/java/com/hjq/permissions/OnPermissionInterceptor.java index 82ebc70..5fd2b41 100644 --- a/library/src/main/java/com/hjq/permissions/IPermissionInterceptor.java +++ b/library/src/main/java/com/hjq/permissions/OnPermissionInterceptor.java @@ -4,7 +4,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import java.util.ArrayList; import java.util.List; /** @@ -13,7 +12,7 @@ * time : 2020/12/26 * desc : 权限请求拦截器 */ -public interface IPermissionInterceptor { +public interface OnPermissionInterceptor { /** * 发起权限申请(可在此处先弹 Dialog 再申请权限,如果用户已经授予权限,则不会触发此回调) @@ -23,7 +22,7 @@ public interface IPermissionInterceptor { */ default void launchPermissionRequest(@NonNull Activity activity, @NonNull List allPermissions, @Nullable OnPermissionCallback callback) { - PermissionFragment.launch(activity, new ArrayList<>(allPermissions), this, callback); + PermissionFragment.launch(activity, allPermissions, this, callback); } /** diff --git a/library/src/main/java/com/hjq/permissions/PermissionFragment.java b/library/src/main/java/com/hjq/permissions/PermissionFragment.java index 6da06dd..15a37ac 100644 --- a/library/src/main/java/com/hjq/permissions/PermissionFragment.java +++ b/library/src/main/java/com/hjq/permissions/PermissionFragment.java @@ -3,6 +3,7 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.Fragment; +import android.app.FragmentManager; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -36,32 +37,38 @@ public final class PermissionFragment extends Fragment implements Runnable { /** * 开启权限申请 */ - public static void launch(@NonNull Activity activity, @NonNull ArrayList permissions, - @NonNull IPermissionInterceptor interceptor, @Nullable OnPermissionCallback callback) { + public static void launch(@NonNull Activity activity, @NonNull List permissions, + @NonNull OnPermissionInterceptor interceptor, @Nullable OnPermissionCallback callback) { PermissionFragment fragment = new PermissionFragment(); - Bundle bundle = new Bundle(); int requestCode; + Random random = new Random(); // 请求码随机生成,避免随机产生之前的请求码,必须进行循环判断 do { // 新版本的 Support 库限制请求码必须小于 65536 // 旧版本的 Support 库限制请求码必须小于 256 - requestCode = new Random().nextInt((int) Math.pow(2, 8)); + requestCode = random.nextInt((int) Math.pow(2, 8)); } while (REQUEST_CODE_ARRAY.contains(requestCode)); // 标记这个请求码已经被占用 REQUEST_CODE_ARRAY.add(requestCode); + + Bundle bundle = new Bundle(); bundle.putInt(REQUEST_CODE, requestCode); - bundle.putStringArrayList(REQUEST_PERMISSIONS, permissions); + if (permissions instanceof ArrayList) { + bundle.putStringArrayList(REQUEST_PERMISSIONS, (ArrayList) permissions); + } else { + bundle.putStringArrayList(REQUEST_PERMISSIONS, new ArrayList<>(permissions)); + } fragment.setArguments(bundle); // 设置保留实例,不会因为屏幕方向或配置变化而重新创建 fragment.setRetainInstance(true); // 设置权限申请标记 fragment.setRequestFlag(true); // 设置权限回调监听 - fragment.setCallBack(callback); + fragment.setOnPermissionCallback(callback); // 设置权限请求拦截器 - fragment.setInterceptor(interceptor); + fragment.setOnPermissionInterceptor(interceptor); // 绑定到 Activity 上面 - fragment.attachActivity(activity); + fragment.attachByActivity(activity); } /** 是否申请了特殊权限 */ @@ -79,7 +86,7 @@ public static void launch(@NonNull Activity activity, @NonNull ArrayList /** 权限请求拦截器 */ @Nullable - private IPermissionInterceptor mInterceptor; + private OnPermissionInterceptor mInterceptor; /** Activity 屏幕方向 */ private int mScreenOrientation; @@ -87,21 +94,29 @@ public static void launch(@NonNull Activity activity, @NonNull ArrayList /** * 绑定 Activity */ - public void attachActivity(@NonNull Activity activity) { - activity.getFragmentManager().beginTransaction().add(this, this.toString()).commitAllowingStateLoss(); + public void attachByActivity(@NonNull Activity activity) { + FragmentManager fragmentManager = activity.getFragmentManager(); + if (fragmentManager == null) { + return; + } + fragmentManager.beginTransaction().add(this, this.toString()).commitAllowingStateLoss(); } /** * 解绑 Activity */ - public void detachActivity(@NonNull Activity activity) { - activity.getFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss(); + public void detachByActivity(@NonNull Activity activity) { + FragmentManager fragmentManager = activity.getFragmentManager(); + if (fragmentManager == null) { + return; + } + fragmentManager.beginTransaction().remove(this).commitAllowingStateLoss(); } /** * 设置权限监听回调监听 */ - public void setCallBack(@Nullable OnPermissionCallback callback) { + public void setOnPermissionCallback(@Nullable OnPermissionCallback callback) { mCallBack = callback; } @@ -115,7 +130,7 @@ public void setRequestFlag(boolean flag) { /** * 设置权限请求拦截器 */ - public void setInterceptor(@Nullable IPermissionInterceptor interceptor) { + public void setOnPermissionInterceptor(@Nullable OnPermissionInterceptor interceptor) { mInterceptor = interceptor; } @@ -162,7 +177,7 @@ public void onResume() { // 如果当前 Fragment 是通过系统重启应用触发的,则不进行权限申请 if (!mRequestFlag) { - detachActivity(getActivity()); + detachByActivity(getActivity()); return; } @@ -290,15 +305,15 @@ public void requestDangerousPermission() { /** * 拆分两次请求权限(有些情况下,需要先申请 A 权限,才能再申请 B 权限) */ - public void splitTwiceRequestPermission(@NonNull Activity activity, @NonNull ArrayList allPermissions, - @NonNull ArrayList firstPermissions, int requestCode) { + public void splitTwiceRequestPermission(@NonNull Activity activity, @NonNull List allPermissions, + @NonNull List firstPermissions, int requestCode) { ArrayList secondPermissions = new ArrayList<>(allPermissions); for (String permission : firstPermissions) { secondPermissions.remove(permission); } - PermissionFragment.launch(activity, firstPermissions, new IPermissionInterceptor() {}, new OnPermissionCallback() { + PermissionFragment.launch(activity, firstPermissions, new OnPermissionInterceptor() {}, new OnPermissionCallback() { @Override public void onGranted(@NonNull List permissions, boolean allGranted) { @@ -311,7 +326,7 @@ public void onGranted(@NonNull List permissions, boolean allGranted) { // 为什么延迟时间是 150 毫秒? 经过实践得出 100 还是有概率会出现失败,但是换成 150 试了很多次就都没有问题了 long delayMillis = AndroidVersion.isAndroid13() ? 150 : 0; PermissionUtils.postDelayed(() -> PermissionFragment.launch(activity, secondPermissions, - new IPermissionInterceptor() {}, new OnPermissionCallback() { + new OnPermissionInterceptor() {}, new OnPermissionCallback() { @Override public void onGranted(@NonNull List permissions, boolean allGranted) { @@ -360,10 +375,7 @@ public void onDenied(@NonNull List permissions, boolean doNotAskAgain) { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { // Github issue 地址:https://github.com/getActivity/XXPermissions/issues/236 - if (permissions == null || grantResults == null) { - return; - } - if (permissions.length == 0 || grantResults.length == 0) { + if (permissions == null || permissions.length == 0 || grantResults == null || grantResults.length == 0) { return; } @@ -377,7 +389,7 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in OnPermissionCallback callback = mCallBack; mCallBack = null; - IPermissionInterceptor interceptor = mInterceptor; + OnPermissionInterceptor interceptor = mInterceptor; mInterceptor = null; // 优化权限回调结果 @@ -389,7 +401,7 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in // 释放对这个请求码的占用 REQUEST_CODE_ARRAY.remove((Integer) requestCode); // 将 Fragment 从 Activity 移除 - detachActivity(activity); + detachByActivity(activity); // 获取已授予的权限 List grantedPermissions = PermissionApi.getGrantedPermissions(allPermissions, grantResults); diff --git a/library/src/main/java/com/hjq/permissions/PermissionPageFragment.java b/library/src/main/java/com/hjq/permissions/PermissionPageFragment.java index 48cda05..8fbdf2a 100644 --- a/library/src/main/java/com/hjq/permissions/PermissionPageFragment.java +++ b/library/src/main/java/com/hjq/permissions/PermissionPageFragment.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.app.Fragment; +import android.app.FragmentManager; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; @@ -25,20 +26,24 @@ public final class PermissionPageFragment extends Fragment implements Runnable { /** * 开启权限申请 */ - public static void beginRequest(@NonNull Activity activity, @NonNull ArrayList permissions, + public static void launch(@NonNull Activity activity, @NonNull List permissions, @Nullable OnPermissionPageCallback callback) { PermissionPageFragment fragment = new PermissionPageFragment(); Bundle bundle = new Bundle(); - bundle.putStringArrayList(REQUEST_PERMISSIONS, permissions); + if (permissions instanceof ArrayList) { + bundle.putStringArrayList(REQUEST_PERMISSIONS, (ArrayList) permissions); + } else { + bundle.putStringArrayList(REQUEST_PERMISSIONS, new ArrayList<>(permissions)); + } fragment.setArguments(bundle); // 设置保留实例,不会因为屏幕方向或配置变化而重新创建 fragment.setRetainInstance(true); // 设置权限申请标记 fragment.setRequestFlag(true); // 设置权限回调监听 - fragment.setCallBack(callback); + fragment.setOnPermissionPageCallback(callback); // 绑定到 Activity 上面 - fragment.attachActivity(activity); + fragment.attachByActivity(activity); } /** 权限回调对象 */ @@ -54,21 +59,29 @@ public static void beginRequest(@NonNull Activity activity, @NonNull ArrayList allPermissions = arguments.getStringArrayList(REQUEST_PERMISSIONS); + if (allPermissions == null || allPermissions.isEmpty()) { + return; + } List grantedPermissions = PermissionApi.getGrantedPermissions(activity, allPermissions); if (grantedPermissions.size() == allPermissions.size()) { @@ -155,6 +172,6 @@ public void run() { callback.onDenied(); } - detachActivity(activity); + detachByActivity(activity); } } \ No newline at end of file diff --git a/library/src/main/java/com/hjq/permissions/PermissionUtils.java b/library/src/main/java/com/hjq/permissions/PermissionUtils.java index bc3bc16..9f62bd5 100644 --- a/library/src/main/java/com/hjq/permissions/PermissionUtils.java +++ b/library/src/main/java/com/hjq/permissions/PermissionUtils.java @@ -19,7 +19,9 @@ import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.text.TextUtils; +import android.view.Display; import android.view.Surface; +import android.view.WindowManager; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -93,7 +95,7 @@ static boolean checkOpNoThrow(Context context, String opName) { /** * 解决 Android 12 调用 shouldShowRequestPermissionRationale 出现内存泄漏的问题 * Android 12L 和 Android 13 版本经过测试不会出现这个问题,证明 Google 在新版本上已经修复了这个问题 - * 但是对于 Android 12 仍是一个历史遗留问题,这是我们所有应用开发者不得不面对的一个事情 + * 但是对于 Android 12 仍是一个历史遗留问题,这是我们所有 Android App 开发者不得不面对的一个事情 * * issues 地址:https://github.com/getActivity/XXPermissions/issues/133 */ @@ -130,15 +132,13 @@ static void postActivityResult(@NonNull List permissions, @NonNull Runna } else { delayMillis = 500; } - } else if (PhoneRomUtils.isMiui()) { - // 经过测试,发现小米 Android 11 及以上的版本,申请这个权限需要 1 秒钟才能判断到 + } else if (PhoneRomUtils.isMiui() && AndroidVersion.isAndroid11() && + PermissionUtils.containsPermission(permissions, Permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { + // 经过测试,发现小米 Android 11 及以上的版本,申请这个权限需要 1000 毫秒才能判断到(测试了 800 毫秒还不行) // 因为在 Android 10 的时候,这个特殊权限弹出的页面小米还是用谷歌原生的 // 然而在 Android 11 之后的,这个权限页面被小米改成了自己定制化的页面 // 测试了原生的模拟器和 vivo 云测并发现没有这个问题,所以断定这个 Bug 就是小米特有的 - if (AndroidVersion.isAndroid11() && - PermissionUtils.containsPermission(permissions, Permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { - delayMillis = 1000; - } + delayMillis = 1000; } postDelayed(runnable, delayMillis); } @@ -174,9 +174,7 @@ static AndroidManifestInfo getAndroidManifestInfo(Context context) { androidManifestInfo.packageName)) { return null; } - } catch (IOException e) { - e.printStackTrace(); - } catch (XmlPullParserException e) { + } catch (IOException | XmlPullParserException e) { e.printStackTrace(); } @@ -344,9 +342,9 @@ static boolean isScopedStorage(@NonNull Context context) { try { String metaKey = "ScopedStorage"; Bundle metaData = context.getPackageManager().getApplicationInfo( - context.getPackageName(), PackageManager.GET_META_DATA).metaData; + context.getPackageName(), PackageManager.GET_META_DATA).metaData; if (metaData != null && metaData.containsKey(metaKey)) { - return Boolean.parseBoolean(String.valueOf(metaData.get(metaKey))); + return metaData.getBoolean(metaKey); } } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); @@ -386,13 +384,22 @@ static void lockActivityOrientation(@NonNull Activity activity) { * 判断 Activity 是否反方向旋转了 */ static boolean isActivityReverse(@NonNull Activity activity) { - // 获取 Activity 旋转的角度 - int activityRotation; + Display display = null; if (AndroidVersion.isAndroid11()) { - activityRotation = activity.getDisplay().getRotation(); + display = activity.getDisplay(); } else { - activityRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); + WindowManager windowManager = activity.getWindowManager(); + if (windowManager != null) { + display = windowManager.getDefaultDisplay(); + } } + + if (display == null) { + return false; + } + + // 获取 Activity 旋转的角度 + int activityRotation = display.getRotation(); switch (activityRotation) { case Surface.ROTATION_180: case Surface.ROTATION_270: diff --git a/library/src/main/java/com/hjq/permissions/StartActivityManager.java b/library/src/main/java/com/hjq/permissions/StartActivityManager.java index 4022183..9037e45 100644 --- a/library/src/main/java/com/hjq/permissions/StartActivityManager.java +++ b/library/src/main/java/com/hjq/permissions/StartActivityManager.java @@ -63,7 +63,7 @@ static boolean startActivity(@NonNull android.support.v4.app.Fragment fragment, return startActivity(new StartActivityDelegateSupportFragmentImpl(fragment), intent); } - static boolean startActivity(@NonNull IStartActivityDelegate delegate, @NonNull Intent intent) { + static boolean startActivity(@NonNull StartActivityDelegate delegate, @NonNull Intent intent) { try { delegate.startActivity(intent); return true; @@ -89,7 +89,7 @@ static boolean startActivityForResult(@NonNull android.support.v4.app.Fragment f return startActivityForResult(new StartActivityDelegateSupportFragmentImpl(fragment), intent, requestCode); } - static boolean startActivityForResult(@NonNull IStartActivityDelegate delegate, @NonNull Intent intent, int requestCode) { + static boolean startActivityForResult(@NonNull StartActivityDelegate delegate, @NonNull Intent intent, int requestCode) { try { delegate.startActivityForResult(intent, requestCode); return true; @@ -103,14 +103,14 @@ static boolean startActivityForResult(@NonNull IStartActivityDelegate delegate, } } - private interface IStartActivityDelegate { + private interface StartActivityDelegate { void startActivity(@NonNull Intent intent); void startActivityForResult(@NonNull Intent intent, int requestCode); } - private static class StartActivityDelegateContextImpl implements IStartActivityDelegate { + private static class StartActivityDelegateContextImpl implements StartActivityDelegate { private final Context mContext; @@ -134,7 +134,7 @@ public void startActivityForResult(@NonNull Intent intent, int requestCode) { } } - private static class StartActivityDelegateActivityImpl implements IStartActivityDelegate { + private static class StartActivityDelegateActivityImpl implements StartActivityDelegate { private final Activity mActivity; @@ -153,7 +153,7 @@ public void startActivityForResult(@NonNull Intent intent, int requestCode) { } } - private static class StartActivityDelegateFragmentImpl implements IStartActivityDelegate { + private static class StartActivityDelegateFragmentImpl implements StartActivityDelegate { private final Fragment mFragment; @@ -172,7 +172,7 @@ public void startActivityForResult(@NonNull Intent intent, int requestCode) { } } - private static class StartActivityDelegateSupportFragmentImpl implements IStartActivityDelegate { + private static class StartActivityDelegateSupportFragmentImpl implements StartActivityDelegate { private final android.support.v4.app.Fragment mFragment; diff --git a/library/src/main/java/com/hjq/permissions/XXPermissions.java b/library/src/main/java/com/hjq/permissions/XXPermissions.java index 44e5cae..cf827bd 100644 --- a/library/src/main/java/com/hjq/permissions/XXPermissions.java +++ b/library/src/main/java/com/hjq/permissions/XXPermissions.java @@ -22,7 +22,7 @@ public final class XXPermissions { public static final int REQUEST_CODE = 1024 + 1; /** 权限请求拦截器 */ - private static IPermissionInterceptor sInterceptor; + private static OnPermissionInterceptor sInterceptor; /** 当前是否为检查模式 */ private static Boolean sCheckMode; @@ -54,16 +54,16 @@ public static void setCheckMode(boolean checkMode) { /** * 设置全局权限请求拦截器 */ - public static void setInterceptor(IPermissionInterceptor interceptor) { + public static void setInterceptor(OnPermissionInterceptor interceptor) { sInterceptor = interceptor; } /** * 获取全局权限请求拦截器 */ - public static IPermissionInterceptor getInterceptor() { + public static OnPermissionInterceptor getInterceptor() { if (sInterceptor == null) { - sInterceptor = new IPermissionInterceptor() {}; + sInterceptor = new OnPermissionInterceptor() {}; } return sInterceptor; } @@ -78,7 +78,7 @@ public static IPermissionInterceptor getInterceptor() { /** 权限请求拦截器 */ @Nullable - private IPermissionInterceptor mInterceptor; + private OnPermissionInterceptor mInterceptor; /** 设置不检查 */ @Nullable @@ -130,7 +130,7 @@ public XXPermissions permission(@Nullable List permissions) { /** * 设置权限请求拦截器 */ - public XXPermissions interceptor(@Nullable IPermissionInterceptor interceptor) { + public XXPermissions interceptor(@Nullable OnPermissionInterceptor interceptor) { mInterceptor = interceptor; return this; } @@ -157,7 +157,7 @@ public void request(@Nullable OnPermissionCallback callback) { final Context context = mContext; - final IPermissionInterceptor interceptor = mInterceptor; + final OnPermissionInterceptor interceptor = mInterceptor; // 权限请求列表(为什么直接不用字段?因为框架要兼容新旧权限,在低版本下会自动添加旧权限申请,为了避免重复添加) final List permissions = new ArrayList<>(mPermissions); @@ -415,7 +415,7 @@ public static void startPermissionActivity(@NonNull Activity activity, StartActivityManager.startActivity(activity, PermissionIntentManager.getApplicationDetailsIntent(activity)); return; } - PermissionPageFragment.beginRequest(activity, (ArrayList) permissions, callback); + PermissionPageFragment.launch(activity, permissions, callback); } /* android.app.Fragment */ @@ -480,7 +480,7 @@ public static void startPermissionActivity(@NonNull Fragment fragment, StartActivityManager.startActivity(fragment, PermissionIntentManager.getApplicationDetailsIntent(activity)); return; } - PermissionPageFragment.beginRequest(activity, (ArrayList) permissions, callback); + PermissionPageFragment.launch(activity, permissions, callback); } /* android.support.v4.app.Fragment */ @@ -545,6 +545,6 @@ public static void startPermissionActivity(@NonNull android.support.v4.app.Fragm StartActivityManager.startActivity(fragment, PermissionIntentManager.getApplicationDetailsIntent(activity)); return; } - PermissionPageFragment.beginRequest(activity, (ArrayList) permissions, callback); + PermissionPageFragment.launch(activity, permissions, callback); } } \ No newline at end of file diff --git a/picture/zh/demo_request_single_permission.jpg b/picture/zh/demo_request_single_permission.jpg index c21b1ca..5014ac4 100644 Binary files a/picture/zh/demo_request_single_permission.jpg and b/picture/zh/demo_request_single_permission.jpg differ