Skip to content

Commit

Permalink
精简不断请求权限的功能逻辑
Browse files Browse the repository at this point in the history
优化部分代码命名及代码注释
优化 Android 11 权限页跳转逻辑
针对 Activity 在后台申请权限的情况进行优化
  • Loading branch information
getActivity committed Oct 11, 2020
1 parent f6e929b commit b1ac001
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 113 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

```groovy
dependencies {
implementation 'com.hjq:xxpermissions:8.6'
implementation 'com.hjq:xxpermissions:8.8'
}
```

Expand Down Expand Up @@ -171,7 +171,7 @@ XXPermissions.with(MainActivity.this)

#### 作者的其他开源项目

* 架构工程[AndroidProject](https://github.com/getActivity/AndroidProject)
* 安卓架构[AndroidProject](https://github.com/getActivity/AndroidProject)

* 网络框架:[EasyHttp](https://github.com/getActivity/EasyHttp)

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 86
versionName "8.6"
versionCode 88
versionName "8.8"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand All @@ -31,7 +31,7 @@ dependencies {
implementation 'com.google.android.material:material:1.3.0-alpha02'

// 吐司工具类:https://github.com/getActivity/ToastUtils
implementation 'com.hjq:toast:8.6'
implementation 'com.hjq:toast:8.8'
// 内存泄漏捕捉:https://github.com/square/leakcanary
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'
}
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

<uses-permission android:name="android.permission.RECORD_AUDIO" />

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/com/hjq/permissions/demo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ protected void onCreate(Bundle savedInstanceState) {
findViewById(R.id.btn_main_request_5).setOnClickListener(this);
findViewById(R.id.btn_main_request_6).setOnClickListener(this);
findViewById(R.id.btn_main_request_7).setOnClickListener(this);

findViewById(R.id.btn_main_app_details).setOnClickListener(this);
}

Expand Down Expand Up @@ -90,7 +89,7 @@ public void noPermission(List<String> denied, boolean never) {
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(MainActivity.this, denied);
} else {
ToastUtils.show("获取录音和日历权限失败");
ToastUtils.show("获取权限失败");
}
}
});
Expand Down
6 changes: 3 additions & 3 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
defaultConfig {
minSdkVersion 11
targetSdkVersion 23
versionCode 86
versionName "8.6"
versionCode 88
versionName "8.8"
}

lintOptions {
Expand All @@ -20,7 +20,7 @@ publish {
userOrg = 'getactivity'
groupId = 'com.hjq'
artifactId = 'xxpermissions'
version = '8.6'
version = '8.8'
description = 'Android 6.0 permissions adaptation framework'
website = "https://github.com/getActivity/XXPermissions"
}
Expand Down
1 change: 1 addition & 0 deletions library/src/main/java/com/hjq/permissions/Permission.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* time : 2018/06/15
* desc : 权限请求实体类,参考 {@link Manifest.permission}
* doc : https://developer.android.google.cn/reference/android/Manifest.permission?hl=zh_cn
* https://developer.android.google.cn/guide/topics/permissions/overview?hl=zh-cn#normal-dangerous
*/
public final class Permission {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ static Intent getIntent(Context context) {
} else if (MARK.contains("meizu")) {
intent = meizu(context);
}

if (intent == null) {
intent = PermissionSettingPage.getApplicationDetailsIntent(context);
}
return intent;
}

Expand Down
137 changes: 69 additions & 68 deletions library/src/main/java/com/hjq/permissions/PermissionFragment.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.hjq.permissions;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
Expand All @@ -20,24 +21,27 @@
* time : 2018/06/15
* desc : 权限请求处理类
*/
public final class PermissionFragment extends Fragment implements Runnable {
@TargetApi(Build.VERSION_CODES.M)
public final class PermissionFragment extends Fragment {

/** 全局的 Handler 对象 */
private static final Handler HANDLER = new Handler(Looper.getMainLooper());
/** 请求的权限 */
private static final String PERMISSION_GROUP = "permission_group";
/** 请求码(自动生成) */
private static final String REQUEST_CODE = "request_code";
/** 是否不断请求 */
private static final String REQUEST_CONSTANT = "request_constant";
/** 回调对象存放 */
private static SparseArray<SoftReference<OnPermission>> sCallbacks = new SparseArray<>();

/** 是否已经回调了,避免安装权限和悬浮窗同时请求导致的重复回调 */
private boolean mCallback;
/** 是否申请了特殊权限 */
private boolean mSpecialRequest;

public static PermissionFragment newInstance(ArrayList<String> permissions, boolean constant) {
/** 是否申请了危险权限 */
private boolean mDangerousRequest;

public static PermissionFragment newInstance(ArrayList<String> permissions) {
PermissionFragment fragment = new PermissionFragment();
fragment.setRetainInstance(true);
Bundle bundle = new Bundle();
int requestCode;
// 请求码随机生成,避免随机产生之前的请求码,必须进行循环判断
Expand All @@ -46,7 +50,6 @@ public static PermissionFragment newInstance(ArrayList<String> permissions, bool
} while (sCallbacks.get(requestCode) != null);
bundle.putInt(REQUEST_CODE, requestCode);
bundle.putStringArrayList(PERMISSION_GROUP, permissions);
bundle.putBoolean(REQUEST_CONSTANT, constant);
fragment.setArguments(bundle);
return fragment;
}
Expand All @@ -60,16 +63,32 @@ public void prepareRequest(Activity activity, OnPermission callback) {
activity.getFragmentManager().beginTransaction().add(this, activity.getClass().getName()).commitAllowingStateLoss();
}

@SuppressLint("InlinedApi")
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

List<String> permissions = getArguments().getStringArrayList(PERMISSION_GROUP);
public void onResume() {
super.onResume();
if (!mSpecialRequest) {
mSpecialRequest = true;
// 如果在 Activity 不可见的状态下添加 Fragment 并且去申请权限会导致授权对话框显示不出来
// 所以必须要在 Fragment 的 onResume 来申请权限,这样就可以保证应用回到前台的时候才去申请权限
requestSpecialPermission();
}
}

if (permissions == null) {
return;
/**
* 申请危险权限
*/
public void requestDangerousPermission() {
ArrayList<String> permissions = getArguments().getStringArrayList(PERMISSION_GROUP);
if (permissions != null && permissions.size() > 0) {
requestPermissions(permissions.toArray(new String[permissions.size() - 1]), getArguments().getInt(REQUEST_CODE));
}
}

/**
* 申请特殊权限
*/
public void requestSpecialPermission() {
List<String> permissions = getArguments().getStringArrayList(PERMISSION_GROUP);

// 是否需要申请特殊权限
boolean requestSpecialPermission = false;
Expand Down Expand Up @@ -113,19 +132,7 @@ public void onActivityCreated(Bundle savedInstanceState) {

// 当前必须没有跳转到悬浮窗或者安装权限界面
if (!requestSpecialPermission) {
requestPermission();
}
}

/**
* 请求权限
*/
public void requestPermission() {
if (PermissionUtils.isAndroid6()) {
ArrayList<String> permissions = getArguments().getStringArrayList(PERMISSION_GROUP);
if (permissions != null && permissions.size() > 0) {
requestPermissions(permissions.toArray(new String[permissions.size() - 1]), getArguments().getInt(REQUEST_CODE));
}
requestDangerousPermission();
}
}

Expand All @@ -148,25 +155,26 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in
if (PermissionUtils.isSpecialPermission(permission)) {
// 如果这个权限是特殊权限,那么就重新进行权限检测
grantResults[i] = PermissionUtils.isPermissionGranted(getActivity(), permission) ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED;
} else {
if (!PermissionUtils.isAndroid10()) {
// 重新检查 Android 10.0 的三个新权限
if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission) ||
Permission.ACTIVITY_RECOGNITION.equals(permission) ||
Permission.ACCESS_MEDIA_LOCATION.equals(permission)) {
// 如果当前版本不符合最低要求,那么就重新进行权限检测
grantResults[i] = PermissionUtils.isPermissionGranted(getActivity(), permission) ?
PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED;
}
continue;
}

if (!PermissionUtils.isAndroid10()) {
// 重新检查 Android 10.0 的三个新权限
if (Permission.ACCESS_BACKGROUND_LOCATION.equals(permission) ||
Permission.ACTIVITY_RECOGNITION.equals(permission) ||
Permission.ACCESS_MEDIA_LOCATION.equals(permission)) {
// 如果当前版本不符合最低要求,那么就重新进行权限检测
grantResults[i] = PermissionUtils.isPermissionGranted(getActivity(), permission) ?
PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED;
}
if (!PermissionUtils.isAndroid8()) {
// 重新检查 Android 8.0 的两个新权限
if (Permission.ANSWER_PHONE_CALLS.equals(permission) ||
Permission.READ_PHONE_NUMBERS.equals(permission)) {
// 如果当前版本不符合最低要求,那么就重新进行权限检测
grantResults[i] = PermissionUtils.isPermissionGranted(getActivity(), permission) ?
PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED;
}
}
if (!PermissionUtils.isAndroid8()) {
// 重新检查 Android 8.0 的两个新权限
if (Permission.ANSWER_PHONE_CALLS.equals(permission) ||
Permission.READ_PHONE_NUMBERS.equals(permission)) {
// 如果当前版本不符合最低要求,那么就重新进行权限检测
grantResults[i] = PermissionUtils.isPermissionGranted(getActivity(), permission) ?
PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED;
}
}
}
Expand All @@ -182,15 +190,6 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in
// 获取拒绝权限
List<String> failPermissions = PermissionUtils.getDeniedPermission(permissions, grantResults);

// 检查是否开启了继续申请模式,如果是则检查没有授予的权限是否还能继续申请
if (getArguments().getBoolean(REQUEST_CONSTANT)
&& PermissionUtils.isRequestDeniedPermission(getActivity(), failPermissions)) {

// 如果有的话就继续申请权限,直到用户授权或者永久拒绝
requestPermission();
return;
}

// 代表申请的权限中有不同意授予的,如果有某个权限被永久拒绝就返回true给开发人员,让开发者引导用户去设置界面开启权限
callback.noPermission(failPermissions, PermissionUtils.isPermissionPermanentDenied(getActivity(), failPermissions));

Expand All @@ -202,24 +201,26 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in

// 权限回调结束后要删除集合中的对象,避免重复请求
sCallbacks.remove(requestCode);
getFragmentManager().beginTransaction().remove(this).commit();
getFragmentManager().beginTransaction().remove(this).commitAllowingStateLoss();
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!mCallback && requestCode == getArguments().getInt(REQUEST_CODE) ) {
mCallback = true;
if (!mDangerousRequest && requestCode == getArguments().getInt(REQUEST_CODE) ) {
mDangerousRequest = true;
// 需要延迟执行,不然有些华为机型授权了但是获取不到权限
HANDLER.postDelayed(this, 500);
}
}

@Override
public void run() {
// 如果用户离开太久,会导致 Activity 被回收掉,所以这里要判断当前 Fragment 是否有被添加到 Activity(可在开发者模式中开启不保留活动复现崩溃的 Bug)
if (isAdded()) {
// 请求其他危险权限
requestPermission();
HANDLER.postDelayed(new Runnable() {
@Override
public void run() {
// 如果用户离开太久,会导致 Activity 被回收掉
// 所以这里要判断当前 Fragment 是否有被添加到 Activity
// 可在开发者模式中开启不保留活动来复现这个 Bug
if (isAdded()) {
// 请求其他危险权限
requestDangerousPermission();
}
}
}, 500);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,21 @@ static Intent getSmartPermissionIntent(Context context, List<String> deniedPermi
} else {
return getApplicationDetailsIntent(context);
}
} else {
// 跳转到应用详情界面
return PermissionSettingPage.getApplicationDetailsIntent(context);
} else if (deniedPermissions.size() == 3) {
if (deniedPermissions.contains(Permission.MANAGE_EXTERNAL_STORAGE) &&
deniedPermissions.contains(Permission.READ_EXTERNAL_STORAGE) &&
deniedPermissions.contains(Permission.WRITE_EXTERNAL_STORAGE)) {
if (PermissionUtils.isAndroid11()) {
return getStoragePermissionIntent(context);
} else {
return PermissionDetailsPage.getIntent(context);
}
}
}
} else {
// 跳转到具体的权限设置界面
Intent intent = PermissionDetailsPage.getIntent(context);

if (intent == null) {
intent = PermissionSettingPage.getApplicationDetailsIntent(context);
}
return intent;
return PermissionSettingPage.getApplicationDetailsIntent(context);
} else {
return PermissionDetailsPage.getIntent(context);
}
}

Expand Down Expand Up @@ -133,7 +136,8 @@ static Intent getSettingPermissionIntent(Context context) {
static Intent getStoragePermissionIntent(Context context) {
Intent intent = null;
if (PermissionUtils.isAndroid11()) {
intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + context.getPackageName()));
}
if (intent == null || !PermissionUtils.hasActivityIntent(context, intent)) {
intent = getApplicationDetailsIntent(context);
Expand Down
Loading

0 comments on commit b1ac001

Please sign in to comment.