README-en.md
project address: Github
7.0 below, needs to be in build.gradle file addedallprojects {
repositories {
// JitPack remote repository:https://jitpack.io
maven { url 'https://jitpack.io' }
}
}
7.0 or above, needs to be in settings.gradle file addeddependencyResolutionManagement {
repositories {
// JitPack remote repository:https://jitpack.io
maven { url 'https://jitpack.io' }
}
}
build.gradle Add remote dependencies to the fileandroid {
// Support JDK 1.8
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
// Device compatibility framework:https://github.com/getActivity/DeviceCompat
implementation 'com.github.getActivity:DeviceCompat:2.6'
// Permission request framework:https://github.com/getActivity/XXPermissions
implementation 'com.github.getActivity:XXPermissions:28.2'
}
dependencies {
// Device compatibility framework:https://github.com/getActivity/DeviceCompat
implementation 'com.github.getActivity:DeviceCompat:2.3'
// Permission request framework:https://github.com/getActivity/XXPermissions
implementation 'com.github.getActivity:XXPermissions:26.8'
}
Option 2: If your project is still in the Support phase and it's not convenient to migrate to AndroidX yet, but you want to use the latest version of the framework, you can use the JetifierStandalone tool provided by Google to convert the aar packages from the released Release versions into Support-compatible aar packages using reverse mode.
You can choose either of the above two options, but it's still not recommended. These are only stopgap measures, not long-term solutions. Subsequent versions of the framework will no longer support Support projects. The best approach is to migrate your project to AndroidX.
AndroidManifest.xmljoin in<manifest>
<application>
<!-- Inform XXPermissions that the current project has adapted to the scoped storage feature -->
<meta-data
android:name="ScopedStorage"
android:value="true" />
</application>
</manifest>
If the current project does not adapt to this feature, then this step can be ignored
It should be noted that this option is used by the framework to determine whether the current project is adapted to scoped storage. It should be noted that if your project has been adapted to the scoped storage feature, you can useREAD_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGETo apply for permission, if your project has not yet adapted to the partition feature, even if you applyREAD_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGEThe permissions will also cause the files on the external storage to be unable to be read normally. If your project is not suitable for scoped storage, please useMANAGE_EXTERNAL_STORAGETo apply for permission, so that the files on the external storage can be read normally. If you want to know more about the features of Android 10 partition storage, you canClick here to view and learn.
The framework has automatically added the framework's obfuscation rules for you internally. When you add the framework's dependent remote libraries, the framework's obfuscation rules will also be carried into your project. You don't need to add them manually yourself. Specific obfuscation rule content Click here to view
XXPermissions.with(this)
// Request multiple permission
.permission(PermissionLists.getRecordAudioPermission())
.permission(PermissionLists.getCameraPermission())
// Setting does not trigger error detection mechanism (local setting)
//.unchecked()
.request(new OnPermissionCallback() {
@Override
public void onResult(@NonNull List<IPermission> grantedList, @NonNull List<IPermission> deniedList) {
boolean allGranted = deniedList.isEmpty();
if (!allGranted) {
// Determine whether the permissions that failed requests have been checked by the user to no longer ask
boolean doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList);
// The logic for failing to handle permission requests here
// ......
return;
}
// The logic for handling permission requests here is successful
// ......
}
});
XXPermissions.with(this)
// Request multiple permission
.permission(PermissionLists.getRecordAudioPermission())
.permission(PermissionLists.getCameraPermission())
// Setting does not trigger error detection mechanism (local setting)
//.unchecked()
.request { grantedList, deniedList ->
val allGranted = deniedList.isEmpty()
if (!allGranted) {
// Determine whether the permissions that failed requests have been checked by the user to no longer ask
val doNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(activity, deniedList)
// The logic for failing to handle permission requests here
// ......
return@request
}
// The logic for handling permission requests here is successful
// ......
}
// Check if a single permission is granted
XXPermissions.isGrantedPermission(@NonNull Context context, @NonNull IPermission permission);
XXPermissions.isGrantedPermissions(@NonNull Context context, @NonNull IPermission[] permissions);
XXPermissions.isGrantedPermissions(@NonNull Context context, @NonNull List<IPermission> permissions);
// Get the granted permissions from a permission list
XXPermissions.getGrantedPermissions(@NonNull Context context, @NonNull IPermission[] permissions);
XXPermissions.getGrantedPermissions(@NonNull Context context, @NonNull List<IPermission> permissions);
// Get the denied permissions from a permission list
XXPermissions.getDeniedPermissions(@NonNull Context context, @NonNull IPermission[] permissions);
XXPermissions.getDeniedPermissions(@NonNull Context context, @NonNull List<IPermission> permissions);
// Determine whether the two permissions are equal
XXPermissions.equalsPermission(@NonNull IPermission permission, @NonNull IPermission permission2);
XXPermissions.equalsPermission(@NonNull IPermission permission, @NonNull String permissionName);
XXPermissions.equalsPermission(@NonNull String permissionName1, @NonNull String permissionName2);
// Determine whether a certain permission is included in the permission list
XXPermissions.containsPermission(@NonNull List<IPermission> permissions, @NonNull IPermission permission);
XXPermissions.containsPermission(@NonNull List<IPermission> permissions, @NonNull String permissionName);
// Check if a permission is a health permission
XXPermissions.isHealthPermission(@NonNull IPermission permission);
// Check if a permission has been denied with the "Never ask again" option selected
// (Must be called within the permission request callback to be effective)
XXPermissions.isDoNotAskAgainPermission(@NonNull Activity activity, @NonNull IPermission permission);
XXPermissions.isDoNotAskAgainPermissions(@NonNull Activity activity, @NonNull IPermission[] permissions);
XXPermissions.isDoNotAskAgainPermissions(@NonNull Activity activity, @NonNull List<IPermission> permissions);
// Navigate to the permission settings page (Context version)
XXPermissions.startPermissionActivity(@NonNull Context context);
XXPermissions.startPermissionActivity(@NonNull Context context, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull Context context, @NonNull List<IPermission> permissions);
// Navigate to the permission settings page (Activity version)
XXPermissions.startPermissionActivity(@NonNull Activity activity);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull List<IPermission> permissions);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull List<IPermission> permissions, @IntRange(from = 1, to = 65535) int requestCode);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull IPermission permission, @Nullable OnPermissionCallback callback);
XXPermissions.startPermissionActivity(@NonNull Activity activity, @NonNull List<IPermission> permissions, @Nullable OnPermissionCallback callback);
// Navigate to the permission settings page (Android Fragment version)
XXPermissions.startPermissionActivity(@NonNull Fragment fragment);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull List<IPermission> permissions);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull List<IPermission> permissions, @IntRange(from = 1, to = 65535) int requestCode);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull IPermission permission, @Nullable OnPermissionCallback callback);
XXPermissions.startPermissionActivity(@NonNull Fragment fragment, @NonNull List<IPermission> permissions, @Nullable OnPermissionCallback callback);
// Navigate to the permission settings page (AndroidX Fragment version)
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull IPermission... permissions);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull List<IPermission> permissions);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull List<IPermission> permissions, @IntRange(from = 1, to = 65535) int requestCode);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull IPermission permission, @Nullable OnPermissionCallback callback);
XXPermissions.startPermissionActivity(@NonNull androidx.fragment.app.Fragment xFragment, @NonNull List<IPermission> permissions, @Nullable OnPermissionCallback callback);
// Set the permission description provider (Global setting)
XXPermissions.setPermissionDescription(Class<? extends OnPermissionDescription> clazz);
// Set the permission request interceptor (Global setting)
XXPermissions.setPermissionInterceptor(Class<? extends OnPermissionInterceptor> clazz);
// Set whether to enable error detection mode (Global setting)
XXPermissions.setCheckMode(boolean checkMode);
| Adaptation details | XXPermissions | AndPermission | PermissionX | AndroidUtilCode-PermissionUtils | PermissionsDispatcher | RxPermissions | EasyPermissions | Dexter |
|---|---|---|---|---|---|---|---|---|
| Corresponding version | 28.2 | 2.0.3 | 1.8.1 | 1.31.0 | 4.9.2 | 0.12 | 3.0.0 | 6.2.3 |
| Number of issues | ||||||||
| Framework Maintenance Status | In maintenance | stop maintenance | stop maintenance | stop maintenance | stop maintenance | stop maintenance | stop maintenance | stop maintenance |
SCHEDULE_EXACT_ALARM | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
MANAGE_EXTERNAL_STORAGE | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
REQUEST_INSTALL_PACKAGES | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
PICTURE_IN_PICTURE | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
SYSTEM_ALERT_WINDOW | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
WRITE_SETTINGS | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
NOTIFICATION_SERVICE | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
NOTIFICATION_SERVICE(Channel) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
BIND_NOTIFICATION_LISTENER_SERVICE | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
ACCESS_NOTIFICATION_POLICY | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
PACKAGE_USAGE_STATS | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
USE_FULL_SCREEN_INTENT | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
BIND_VPN_SERVICE | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
BIND_ACCESSIBILITY_SERVICE | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
BIND_DEVICE_ADMIN | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
MANAGE_MEDIA | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Intent Extreme Jump Fallback Mechanism | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Compatibility with Permission Request API Crash Issues | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Avoiding System Permission Callback Null Pointer Issues | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Automatic Permission Split Requests | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Framework Completely Separates UI Layer | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Core Logic and Specific Permissions Completely Decoupled | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
| Automatic Background Permission Adaptation | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Support for Cross-Platform Environment Calls | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ |
| Callback Lifecycle Synchronized with Host | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Support for Custom Permission Requests | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| New Version Permissions Support Backward Compatibility | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Screen Rotation Scenario Adaptation | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Background Permission Request Scenario Adaptation | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Fix Android 12 Memory Leak Issue | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Support for Code Error Detection | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Take the lead: the first permission request framework adapted to Android 16
Concise and easy to use: using the method of chain call, only one line of code is needed to use
Comprehensive support: the first and only permission request framework that adapts to all Android versions
Overcoming technical difficulties: the first framework to solve system memory leaks in Android 12 for permission applications
Adapt to extreme situations: No matter how extreme and harsh the environment is to apply for permissions, the framework is still strong
Downward Compatibility: New permissions can be applied normally in the old system, and the framework will automatically adapt without the caller's adaptation
Automatic error detection: If an error occurs, the framework will actively throw an exception to the caller (only judged under Debug, and kill the bug in the cradle)
Android middle office: AndroidProject
Android middle office kt version: AndroidProject-Kotlin
Toast framework: Toaster
Network framework: EasyHttp
Title bar framework: TitleBar
Floating window framework: EasyWindow
Device compatibility framework:DeviceCompat
Shape view framework: ShapeView
Shape drawable framework: ShapeDrawable
Language switching framework: Multi Languages
Gson parsing fault tolerance: GsonFactory
Logcat viewing framework: Logcat
Nested scrolling layout framework:NestedScrollLayout
Android cmd tools:AndroidCmdTools
Android version guide: AndroidVersionAdapter
Android code standard: AndroidCodeStandard
Android resource summary:AndroidIndex
Android open source leaderboard: AndroidGithubBoss
Studio boutique plugins: StudioPlugins
Emoji collection: EmojiPackage
China provinces json: ProvinceJson
Markdown documentation:MarkdownDoc
Copyright 2018 Huang JinQun
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.