Showing preview only (365K chars total). Download the full file or copy to clipboard to get everything.
Repository: yanzhenjie/AndPermission
Branch: master
Commit: 00bedd6a3a93
Files: 143
Total size: 323.5 KB
Directory structure:
gitextract_hhydg_6p/
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── build.gradle
├── config.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── permission/
│ ├── .gitignore
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── aidl/
│ │ └── com/
│ │ └── yanzhenjie/
│ │ └── permission/
│ │ └── bridge/
│ │ └── IBridge.aidl
│ ├── java/
│ │ └── com/
│ │ └── yanzhenjie/
│ │ └── permission/
│ │ ├── Action.java
│ │ ├── AndPermission.java
│ │ ├── Boot.java
│ │ ├── FileProvider.java
│ │ ├── Rationale.java
│ │ ├── RequestExecutor.java
│ │ ├── bridge/
│ │ │ ├── BridgeActivity.java
│ │ │ ├── BridgeRequest.java
│ │ │ ├── BridgeService.java
│ │ │ ├── Messenger.java
│ │ │ ├── RequestExecutor.java
│ │ │ └── RequestManager.java
│ │ ├── checker/
│ │ │ ├── CalendarReadTest.java
│ │ │ ├── CalendarWriteTest.java
│ │ │ ├── CallLogReadTest.java
│ │ │ ├── CallLogWriteTest.java
│ │ │ ├── CameraTest.java
│ │ │ ├── ContactsReadTest.java
│ │ │ ├── ContactsWriteTest.java
│ │ │ ├── DoubleChecker.java
│ │ │ ├── LocationCoarseTest.java
│ │ │ ├── LocationFineTest.java
│ │ │ ├── PermissionChecker.java
│ │ │ ├── PermissionTest.java
│ │ │ ├── PhoneStateReadTest.java
│ │ │ ├── RecordAudioTest.java
│ │ │ ├── SensorActivityTest.java
│ │ │ ├── SensorHeartTest.java
│ │ │ ├── SipTest.java
│ │ │ ├── SmsReadTest.java
│ │ │ ├── StandardChecker.java
│ │ │ ├── StorageReadTest.java
│ │ │ ├── StorageWriteTest.java
│ │ │ └── StrictChecker.java
│ │ ├── install/
│ │ │ ├── BaseRequest.java
│ │ │ ├── InstallRequest.java
│ │ │ ├── NRequest.java
│ │ │ ├── NRequestFactory.java
│ │ │ ├── ORequest.java
│ │ │ └── ORequestFactory.java
│ │ ├── notify/
│ │ │ ├── BaseRequest.java
│ │ │ ├── NRequest.java
│ │ │ ├── NRequestFactory.java
│ │ │ ├── Notify.java
│ │ │ ├── ORequest.java
│ │ │ ├── ORequestFactory.java
│ │ │ ├── PermissionRequest.java
│ │ │ ├── listener/
│ │ │ │ ├── BaseRequest.java
│ │ │ │ ├── J1Request.java
│ │ │ │ ├── J1RequestFactory.java
│ │ │ │ ├── J2Request.java
│ │ │ │ ├── J2RequestFactory.java
│ │ │ │ └── ListenerRequest.java
│ │ │ └── option/
│ │ │ └── NotifyOption.java
│ │ ├── option/
│ │ │ └── Option.java
│ │ ├── overlay/
│ │ │ ├── BaseRequest.java
│ │ │ ├── LRequest.java
│ │ │ ├── LRequestFactory.java
│ │ │ ├── MRequest.java
│ │ │ ├── MRequestFactory.java
│ │ │ ├── OverlayRequest.java
│ │ │ └── setting/
│ │ │ ├── LSettingPage.java
│ │ │ └── MSettingPage.java
│ │ ├── runtime/
│ │ │ ├── BaseRequest.java
│ │ │ ├── LRequest.java
│ │ │ ├── LRequestFactory.java
│ │ │ ├── MRequest.java
│ │ │ ├── MRequestFactory.java
│ │ │ ├── Permission.java
│ │ │ ├── PermissionDef.java
│ │ │ ├── PermissionRequest.java
│ │ │ ├── Runtime.java
│ │ │ ├── option/
│ │ │ │ └── RuntimeOption.java
│ │ │ └── setting/
│ │ │ ├── AllRequest.java
│ │ │ ├── SettingPage.java
│ │ │ └── SettingRequest.java
│ │ ├── setting/
│ │ │ ├── Setting.java
│ │ │ └── write/
│ │ │ ├── BaseRequest.java
│ │ │ ├── LWriteRequest.java
│ │ │ ├── LWriteRequestFactory.java
│ │ │ ├── MWriteRequest.java
│ │ │ ├── MWriteRequestFactory.java
│ │ │ └── WriteRequest.java
│ │ ├── source/
│ │ │ ├── ActivitySource.java
│ │ │ ├── ContextSource.java
│ │ │ ├── FragmentSource.java
│ │ │ ├── Source.java
│ │ │ ├── WrapperSource.java
│ │ │ └── XFragmentSource.java
│ │ ├── task/
│ │ │ ├── TaskExecutor.java
│ │ │ └── WaitDialog.java
│ │ └── util/
│ │ └── StringUtils.java
│ └── res/
│ ├── drawable/
│ │ └── permission_shape_wait_background.xml
│ ├── layout/
│ │ └── permission_dialog_wait.xml
│ ├── values/
│ │ ├── dimens.xml
│ │ ├── string.xml
│ │ └── style.xml
│ ├── values-v21/
│ │ └── style.xml
│ ├── values-zh/
│ │ └── string.xml
│ ├── values-zh-RHK/
│ │ └── string.xml
│ ├── values-zh-RTW/
│ │ └── string.xml
│ └── xml/
│ └── permission_file_paths.xml
├── sample/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── assets/
│ │ └── android.apk
│ ├── java/
│ │ └── com/
│ │ └── yanzhenjie/
│ │ └── permission/
│ │ └── sample/
│ │ ├── App.java
│ │ ├── InstallRationale.java
│ │ ├── NotifyListenerRationale.java
│ │ ├── NotifyRationale.java
│ │ ├── OverlayRationale.java
│ │ ├── RuntimeRationale.java
│ │ ├── WriteSettingRationale.java
│ │ ├── app/
│ │ │ ├── MainActivity.java
│ │ │ └── NotifyListenerService.java
│ │ ├── util/
│ │ │ ├── FileUtils.java
│ │ │ └── IOUtils.java
│ │ └── widget/
│ │ ├── AlertWindow.java
│ │ └── LauncherView.java
│ └── res/
│ ├── layout/
│ │ ├── activity_main.xml
│ │ └── window_launcher.xml
│ └── values/
│ ├── array_string.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.iml
/.idea/
/build/
.gradle
/local.properties
.DS_Store
/captures
.externalNativeBuild
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to AndPermission
First off, thanks for taking the time to contribute.
The following is a set of guidelines for contributing to AndPermission. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
1. All your actions in AndPermission should be in English, not in other languages.
2. Please keep AndPermission the existing code style, not according to your habits.
3. Just modify the code you are sure need to be optimized, not all the different code from your ideas.
4. Before launching a pull request, you should test your commit code adequately.
5. Please commit new code to the [dev](https://github.com/yanzhenjie/AndPermission/tree/dev) branch instead of the master branch.
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Zhenjie Yan
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.
================================================
FILE: README.md
================================================
# AndPermission
1. Request for runtime permissions.
2. Share private files.
3. Request to install unknown source apk.
`android.permission.REQUEST_INSTALL_PACKAGES`
4. Request to draw at the top of other apps.
`android.permission.SYSTEM_ALERT_WINDOW`
5. Request to show notifications.
6. Request to access notifications.
`android.permission.BIND_NOTIFICATION_LISTENER_SERVICE`
7. Request to modify system setting.
`android.permission.WRITE_SETTINGS`
```java
AndPermission.with(this)
.runtime()
.permission(Permission.Group.STORAGE)
.onGranted(permissions -> {
// Storage permission are allowed.
})
.onDenied(permissions -> {
// Storage permission are not allowed.
})
.start();
```
For documentation and additional information see [the website](https://yanzhenjie.com/AndPermission).
## Download
It only supports androidx, add dependencies in your gradle:
```groovy
implementation 'com.yanzhenjie:permission:2.0.3'
```
AndPermission requires at minimum Android 4.0(Api level 14) .
## Contributing
Before submitting pull requests, contributors must abide by the [agreement](CONTRIBUTING.md) .
## License
```text
Copyright 2019 Zhenjie Yan
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.
```
================================================
FILE: build.gradle
================================================
apply from: "config.gradle"
buildscript {
repositories {
google()
jcenter {url 'https://maven.aliyun.com/repository/jcenter'}
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
}
}
allprojects {
repositories {
google()
jcenter {url 'https://maven.aliyun.com/repository/jcenter'}
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: config.gradle
================================================
ext {
plugins = [application: 'com.android.application',
library : 'com.android.library',
maven : 'com.github.dcendents.android-maven',
bintray : 'com.jfrog.bintray']
android = [applicationId : "com.yanzhenjie.permission.sample",
compileSdkVersion: 29,
buildToolsVersion: "29.0.2",
minSdkVersion : 14,
targetSdkVersion : 29,
versionCode : 108,
versionName : "2.0.3"]
bintray = [version : "2.0.3",
siteUrl : 'https://github.com/yanzhenjie/AndPermission',
gitUrl : 'https://github.com/yanzhenjie/AndPermission.git',
group : "com.yanzhenjie",
packaging : 'aar',
name : 'Permission',
description : 'Permission manager for Android',
licenseName : 'The Apache Software License, Version 2.0',
licenseUrl : 'http://www.apache.org/licenses/LICENSE-2.0.txt',
developerId : 'yanzhenjie',
developerName : 'yanzhenjie',
developerEmail: 'im.yanzhenjie@gmail.com',
binrayLibrary : "permission",
bintrayRepo : "maven",
bintrayUser : 'yolanda',
bintrayLicense: "Apache-2.0"]
dependencies = [
fragment: 'androidx.appcompat:appcompat:1.1.0'
]
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
================================================
FILE: gradle.properties
================================================
android.useAndroidX=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: permission/.gitignore
================================================
/build
================================================
FILE: permission/build.gradle
================================================
apply plugin: rootProject.ext.plugins.library
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
}
resourcePrefix 'permission'
}
dependencies {
api rootProject.ext.dependencies.fragment
}
================================================
FILE: permission/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 Zhenjie Yan
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yanzhenjie.permission">
<permission
android:name="${applicationId}.andpermission.bridge"
android:permissionGroup="${applicationId}.andpermission"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.andpermission.bridge" />
<application>
<service
android:name=".bridge.BridgeService"
android:exported="false"
android:permission="${applicationId}.andpermission.bridge"
android:process=":permission">
<intent-filter>
<action android:name="${applicationId}.andpermission.bridge" />
</intent-filter>
</service>
<activity
android:name=".bridge.BridgeActivity"
android:configChanges="orientation"
android:exported="false"
android:permission="${applicationId}.andpermission.bridge"
android:process=":permission"
android:theme="@style/Permission.Theme.Activity.Transparent" />
<provider
android:name=".FileProvider"
android:authorities="${applicationId}.file.path.share"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/permission_file_paths" />
</provider>
</application>
</manifest>
================================================
FILE: permission/src/main/aidl/com/yanzhenjie/permission/bridge/IBridge.aidl
================================================
package com.yanzhenjie.permission.bridge;
interface IBridge {
/**
* Request for permissions.
*/
void requestAppDetails(in String suffix);
/**
* Request for permissions.
*/
void requestPermission(in String suffix, in String[] permissions);
/**
* Request for package install.
*/
void requestInstall(in String suffix);
/**
* Request for overlay.
*/
void requestOverlay(in String suffix);
/**
* Request for alert window.
*/
void requestAlertWindow(in String suffix);
/**
* Request for notify.
*/
void requestNotify(in String suffix);
/**
* Request for notification listener.
*/
void requestNotificationListener(in String suffix);
/**
* Request for write system setting.
*/
void requestWriteSetting(in String suffix);
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/Action.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission;
/**
* Created by Zhenjie Yan on 2018/1/1.
*/
public interface Action<T> {
/**
* An action.
*
* @param data the data.
*/
void onAction(T data);
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/AndPermission.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import androidx.fragment.app.Fragment;
import com.yanzhenjie.permission.checker.DoubleChecker;
import com.yanzhenjie.permission.checker.PermissionChecker;
import com.yanzhenjie.permission.option.Option;
import com.yanzhenjie.permission.source.ActivitySource;
import com.yanzhenjie.permission.source.ContextSource;
import com.yanzhenjie.permission.source.FragmentSource;
import com.yanzhenjie.permission.source.Source;
import com.yanzhenjie.permission.source.XFragmentSource;
import java.io.File;
import java.util.List;
/**
* Created by Zhenjie Yan on 2016/9/9.
*/
public class AndPermission {
private static final String ACTION_BRIDGE_SUFFIX = ".andpermission.bridge";
public static String bridgeAction(Context context, String suffix) {
return context.getPackageName() + ACTION_BRIDGE_SUFFIX + (TextUtils.isEmpty(suffix) ? "" : "." + suffix);
}
/**
* With context.
*
* @param context {@link Context}.
* @return {@link Option}.
*/
public static Option with(Context context) {
return new Boot(getContextSource(context));
}
/**
* With {@link Fragment}.
*
* @param fragment {@link Fragment}.
* @return {@link Option}.
*/
public static Option with(Fragment fragment) {
return new Boot(new XFragmentSource(fragment));
}
/**
* With {@link android.app.Fragment}.
*
* @param fragment {@link android.app.Fragment}.
* @return {@link Option}.
*/
public static Option with(android.app.Fragment fragment) {
return new Boot(new FragmentSource(fragment));
}
/**
* With activity.
*
* @param activity {@link Activity}.
* @return {@link Option}.
*/
public static Option with(Activity activity) {
return new Boot(new ActivitySource(activity));
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param context {@link Context}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(Context context, List<String> deniedPermissions) {
return hasAlwaysDeniedPermission(getContextSource(context), deniedPermissions);
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param fragment {@link Fragment}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(Fragment fragment, List<String> deniedPermissions) {
return hasAlwaysDeniedPermission(new XFragmentSource(fragment), deniedPermissions);
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param fragment {@link android.app.Fragment}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(android.app.Fragment fragment, List<String> deniedPermissions) {
return hasAlwaysDeniedPermission(new FragmentSource(fragment), deniedPermissions);
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param activity {@link Activity}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(Activity activity, List<String> deniedPermissions) {
return hasAlwaysDeniedPermission(new ActivitySource(activity), deniedPermissions);
}
/**
* Has always been denied permission.
*/
private static boolean hasAlwaysDeniedPermission(Source source, List<String> deniedPermissions) {
for (String permission : deniedPermissions) {
if (!source.isShowRationalePermission(permission)) {
return true;
}
}
return false;
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param context {@link Context}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(Context context, String... deniedPermissions) {
return hasAlwaysDeniedPermission(getContextSource(context), deniedPermissions);
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param fragment {@link Fragment}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(Fragment fragment, String... deniedPermissions) {
return hasAlwaysDeniedPermission(new XFragmentSource(fragment), deniedPermissions);
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param fragment {@link android.app.Fragment}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(android.app.Fragment fragment, String... deniedPermissions) {
return hasAlwaysDeniedPermission(new FragmentSource(fragment), deniedPermissions);
}
/**
* Some privileges permanently disabled, may need to set up in the execute.
*
* @param activity {@link Activity}.
* @param deniedPermissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasAlwaysDeniedPermission(Activity activity, String... deniedPermissions) {
return hasAlwaysDeniedPermission(new ActivitySource(activity), deniedPermissions);
}
/**
* Has always been denied permission.
*/
private static boolean hasAlwaysDeniedPermission(Source source, String... deniedPermissions) {
for (String permission : deniedPermissions) {
if (!source.isShowRationalePermission(permission)) {
return true;
}
}
return false;
}
/**
* Classic permission checker.
*/
private static final PermissionChecker PERMISSION_CHECKER = new DoubleChecker();
/**
* Judgment already has the target permission.
*
* @param context {@link Context}.
* @param permissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasPermissions(Context context, String... permissions) {
return PERMISSION_CHECKER.hasPermission(context, permissions);
}
/**
* Judgment already has the target permission.
*
* @param fragment {@link Fragment}.
* @param permissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasPermissions(Fragment fragment, String... permissions) {
return hasPermissions(fragment.getActivity(), permissions);
}
/**
* Judgment already has the target permission.
*
* @param fragment {@link android.app.Fragment}.
* @param permissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasPermissions(android.app.Fragment fragment, String... permissions) {
return hasPermissions(fragment.getActivity(), permissions);
}
/**
* Judgment already has the target permission.
*
* @param activity {@link Activity}.
* @param permissions one or more permissions.
* @return true, other wise is false.
*/
public static boolean hasPermissions(Activity activity, String... permissions) {
return PERMISSION_CHECKER.hasPermission(activity, permissions);
}
/**
* Judgment already has the target permission.
*
* @param context {@link Context}.
* @param permissions one or more permission groups.
* @return true, other wise is false.
*/
public static boolean hasPermissions(Context context, String[]... permissions) {
for (String[] permission : permissions) {
boolean hasPermission = PERMISSION_CHECKER.hasPermission(context, permission);
if (!hasPermission) return false;
}
return true;
}
/**
* Judgment already has the target permission.
*
* @param fragment {@link Fragment}.
* @param permissions one or more permission groups.
* @return true, other wise is false.
*/
public static boolean hasPermissions(Fragment fragment, String[]... permissions) {
return hasPermissions(fragment.getActivity(), permissions);
}
/**
* Judgment already has the target permission.
*
* @param fragment {@link android.app.Fragment}.
* @param permissions one or more permission groups.
* @return true, other wise is false.
*/
public static boolean hasPermissions(android.app.Fragment fragment, String[]... permissions) {
return hasPermissions(fragment.getActivity(), permissions);
}
/**
* Judgment already has the target permission.
*
* @param activity {@link Activity}.
* @param permissions one or more permission groups.
* @return true, other wise is false.
*/
public static boolean hasPermissions(Activity activity, String[]... permissions) {
for (String[] permission : permissions) {
boolean hasPermission = PERMISSION_CHECKER.hasPermission(activity, permission);
if (!hasPermission) return false;
}
return true;
}
/**
* Get compatible Android 7.0 and lower versions of Uri.
*
* @param context {@link Context}.
* @param file apk file.
* @return uri.
*/
public static Uri getFileUri(Context context, File file) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return FileProvider.getUriForFile(context, context.getPackageName() + ".file.path.share", file);
}
return Uri.fromFile(file);
}
/**
* Get compatible Android 7.0 and lower versions of Uri.
*
* @param fragment {@link Fragment}.
* @param file apk file.
* @return uri.
*/
public static Uri getFileUri(Fragment fragment, File file) {
return getFileUri(fragment.getContext(), file);
}
/**
* Get compatible Android 7.0 and lower versions of Uri.
*
* @param fragment {@link android.app.Fragment}.
* @param file apk file.
* @return uri.
*/
public static Uri getFileUri(android.app.Fragment fragment, File file) {
return getFileUri(fragment.getActivity(), file);
}
private static Source getContextSource(Context context) {
if (context instanceof Activity) {
return new ActivitySource((Activity) context);
} else if (context instanceof ContextWrapper) {
return getContextSource(((ContextWrapper) context).getBaseContext());
}
return new ContextSource(context);
}
private AndPermission() {
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/Boot.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission;
import android.os.Build;
import com.yanzhenjie.permission.install.InstallRequest;
import com.yanzhenjie.permission.install.NRequestFactory;
import com.yanzhenjie.permission.install.ORequestFactory;
import com.yanzhenjie.permission.notify.Notify;
import com.yanzhenjie.permission.notify.option.NotifyOption;
import com.yanzhenjie.permission.option.Option;
import com.yanzhenjie.permission.overlay.LRequestFactory;
import com.yanzhenjie.permission.overlay.MRequestFactory;
import com.yanzhenjie.permission.overlay.OverlayRequest;
import com.yanzhenjie.permission.runtime.Runtime;
import com.yanzhenjie.permission.runtime.option.RuntimeOption;
import com.yanzhenjie.permission.setting.Setting;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/4/28.
*/
public class Boot implements Option {
private static final InstallRequestFactory INSTALL_REQUEST_FACTORY;
private static final OverlayRequestFactory OVERLAY_REQUEST_FACTORY;
static {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
INSTALL_REQUEST_FACTORY = new ORequestFactory();
} else {
INSTALL_REQUEST_FACTORY = new NRequestFactory();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
OVERLAY_REQUEST_FACTORY = new MRequestFactory();
} else {
OVERLAY_REQUEST_FACTORY = new LRequestFactory();
}
}
public interface InstallRequestFactory {
/**
* Create apk installer request.
*/
InstallRequest create(Source source);
}
public interface OverlayRequestFactory {
/**
* Create overlay request.
*/
OverlayRequest create(Source source);
}
private Source mSource;
public Boot(Source source) {
this.mSource = source;
}
@Override
public RuntimeOption runtime() {
return new Runtime(mSource);
}
@Override
public InstallRequest install() {
return INSTALL_REQUEST_FACTORY.create(mSource);
}
@Override
public OverlayRequest overlay() {
return OVERLAY_REQUEST_FACTORY.create(mSource);
}
@Override
public NotifyOption notification() {
return new Notify(mSource);
}
@Override
public Setting setting() {
return new Setting(mSource);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/FileProvider.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
import android.text.TextUtils;
import android.webkit.MimeTypeMap;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
/**
* <p>Copied from the support library v27.1.1.</p>
* Created by Zhenjie Yan on 2018/4/28.
*/
public class FileProvider extends ContentProvider {
private static final String[] COLUMNS = {OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE};
private static final String META_DATA_FILE_PROVIDER_PATHS = "android.support.FILE_PROVIDER_PATHS";
private static final String TAG_ROOT_PATH = "root-path";
private static final String TAG_FILES_PATH = "files-path";
private static final String TAG_CACHE_PATH = "cache-path";
private static final String TAG_EXTERNAL = "external-path";
private static final String TAG_EXTERNAL_FILES = "external-files-path";
private static final String TAG_EXTERNAL_CACHE = "external-cache-path";
private static final String TAG_EXTERNAL_MEDIA = "external-media-path";
private static final String ATTR_NAME = "name";
private static final String ATTR_PATH = "path";
private static final File DEVICE_ROOT = new File("/");
private static final HashMap<String, PathStrategy> sCache = new HashMap<>();
private PathStrategy mStrategy;
@Override
public boolean onCreate() {
return true;
}
@Override
public void attachInfo(Context context, ProviderInfo info) {
super.attachInfo(context, info);
if (info.exported) {
throw new SecurityException("Provider must not be exported");
}
if (!info.grantUriPermissions) {
throw new SecurityException("Provider must grant uri permissions");
}
mStrategy = getPathStrategy(context, info.authority);
}
public static Uri getUriForFile(Context context, String authority, File file) {
final PathStrategy strategy = getPathStrategy(context, authority);
return strategy.getUriForFile(file);
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
final File file = mStrategy.getFileForUri(uri);
if (projection == null) {
projection = COLUMNS;
}
String[] cols = new String[projection.length];
Object[] values = new Object[projection.length];
int i = 0;
for (String col : projection) {
if (OpenableColumns.DISPLAY_NAME.equals(col)) {
cols[i] = OpenableColumns.DISPLAY_NAME;
values[i++] = file.getName();
} else if (OpenableColumns.SIZE.equals(col)) {
cols[i] = OpenableColumns.SIZE;
values[i++] = file.length();
}
}
cols = copyOf(cols, i);
values = copyOf(values, i);
final MatrixCursor cursor = new MatrixCursor(cols, 1);
cursor.addRow(values);
return cursor;
}
@Override
public String getType(Uri uri) {
final File file = mStrategy.getFileForUri(uri);
final int lastDot = file.getName().lastIndexOf('.');
if (lastDot >= 0) {
final String extension = file.getName().substring(lastDot + 1);
final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mime != null) {
return mime;
}
}
return "application/octet-stream";
}
@Override
public Uri insert(Uri uri, ContentValues values) {
throw new UnsupportedOperationException("No external inserts");
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException("No external updates");
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
final File file = mStrategy.getFileForUri(uri);
return file.delete() ? 1 : 0;
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
final File file = mStrategy.getFileForUri(uri);
final int fileMode = modeToMode(mode);
return ParcelFileDescriptor.open(file, fileMode);
}
private static PathStrategy getPathStrategy(Context context, String authority) {
PathStrategy strategy;
synchronized (sCache) {
strategy = sCache.get(authority);
if (strategy == null) {
try {
strategy = parsePathStrategy(context, authority);
} catch (IOException e) {
throw new IllegalArgumentException(
"Failed to parse " + META_DATA_FILE_PROVIDER_PATHS + " meta-data", e);
} catch (XmlPullParserException e) {
throw new IllegalArgumentException(
"Failed to parse " + META_DATA_FILE_PROVIDER_PATHS + " meta-data", e);
}
sCache.put(authority, strategy);
}
}
return strategy;
}
private static PathStrategy parsePathStrategy(Context context, String authority)
throws IOException, XmlPullParserException {
final SimplePathStrategy strategy = new SimplePathStrategy(authority);
final ProviderInfo info = context.getPackageManager()
.resolveContentProvider(authority, PackageManager.GET_META_DATA);
final XmlResourceParser in = info.loadXmlMetaData(context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS);
if (in == null) {
throw new IllegalArgumentException("Missing " + META_DATA_FILE_PROVIDER_PATHS + " meta-data");
}
int type;
while ((type = in.next()) != END_DOCUMENT) {
if (type == START_TAG) {
final String tag = in.getName();
final String name = in.getAttributeValue(null, ATTR_NAME);
String path = in.getAttributeValue(null, ATTR_PATH);
File target = null;
if (TAG_ROOT_PATH.equals(tag)) {
target = DEVICE_ROOT;
} else if (TAG_FILES_PATH.equals(tag)) {
target = context.getFilesDir();
} else if (TAG_CACHE_PATH.equals(tag)) {
target = context.getCacheDir();
} else if (TAG_EXTERNAL.equals(tag)) {
target = Environment.getExternalStorageDirectory();
} else if (TAG_EXTERNAL_FILES.equals(tag)) {
File[] externalFilesDirs = getExternalFilesDirs(context, null);
if (externalFilesDirs.length > 0) {
target = externalFilesDirs[0];
}
} else if (TAG_EXTERNAL_CACHE.equals(tag)) {
File[] externalCacheDirs = getExternalCacheDirs(context);
if (externalCacheDirs.length > 0) {
target = externalCacheDirs[0];
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && TAG_EXTERNAL_MEDIA.equals(tag)) {
File[] externalMediaDirs = context.getExternalMediaDirs();
if (externalMediaDirs.length > 0) {
target = externalMediaDirs[0];
}
}
if (target != null) {
strategy.addRoot(name, buildPath(target, path));
}
}
}
return strategy;
}
interface PathStrategy {
Uri getUriForFile(File file);
File getFileForUri(Uri uri);
}
static class SimplePathStrategy implements PathStrategy {
private final String mAuthority;
private final HashMap<String, File> mRoots = new HashMap<String, File>();
SimplePathStrategy(String authority) {
mAuthority = authority;
}
void addRoot(String name, File root) {
if (TextUtils.isEmpty(name)) {
throw new IllegalArgumentException("Name must not be empty");
}
try {
root = root.getCanonicalFile();
} catch (IOException e) {
throw new IllegalArgumentException("Failed to resolve canonical path for " + root, e);
}
mRoots.put(name, root);
}
@Override
public Uri getUriForFile(File file) {
String path;
try {
path = file.getCanonicalPath();
} catch (IOException e) {
throw new IllegalArgumentException("Failed to resolve canonical path for " + file);
}
Map.Entry<String, File> mostSpecific = null;
for (Map.Entry<String, File> root : mRoots.entrySet()) {
final String rootPath = root.getValue().getPath();
boolean invalidMost = mostSpecific == null ||
rootPath.length() > mostSpecific.getValue().getPath().length();
if (path.startsWith(rootPath) && invalidMost) {
mostSpecific = root;
}
}
if (mostSpecific == null) {
throw new IllegalArgumentException("Failed to find configured root that contains " + path);
}
final String rootPath = mostSpecific.getValue().getPath();
if (rootPath.endsWith("/")) {
path = path.substring(rootPath.length());
} else {
path = path.substring(rootPath.length() + 1);
}
path = Uri.encode(mostSpecific.getKey()) + '/' + Uri.encode(path, "/");
return new Uri.Builder().scheme("content").authority(mAuthority).encodedPath(path).build();
}
@Override
public File getFileForUri(Uri uri) {
String path = uri.getEncodedPath();
final int splitIndex = path.indexOf('/', 1);
final String tag = Uri.decode(path.substring(1, splitIndex));
path = Uri.decode(path.substring(splitIndex + 1));
final File root = mRoots.get(tag);
if (root == null) {
throw new IllegalArgumentException("Unable to find configured root for " + uri);
}
File file = new File(root, path);
try {
file = file.getCanonicalFile();
} catch (IOException e) {
throw new IllegalArgumentException("Failed to resolve canonical path for " + file);
}
if (!file.getPath().startsWith(root.getPath())) {
throw new SecurityException("Resolved path jumped beyond configured root");
}
return file;
}
}
private static int modeToMode(String mode) {
int modeBits;
if ("r".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
} else if ("w".equals(mode) || "wt".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE;
} else if ("wa".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_APPEND;
} else if ("rw".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_CREATE;
} else if ("rwt".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE;
} else {
throw new IllegalArgumentException("Invalid mode: " + mode);
}
return modeBits;
}
private static File buildPath(File base, String... segments) {
File cur = base;
for (String segment : segments) {
if (segment != null) {
cur = new File(cur, segment);
}
}
return cur;
}
private static String[] copyOf(String[] original, int newLength) {
final String[] result = new String[newLength];
System.arraycopy(original, 0, result, 0, newLength);
return result;
}
private static Object[] copyOf(Object[] original, int newLength) {
final Object[] result = new Object[newLength];
System.arraycopy(original, 0, result, 0, newLength);
return result;
}
private static File[] getExternalFilesDirs(Context context, String type) {
if (Build.VERSION.SDK_INT >= 19) {
return context.getExternalFilesDirs(type);
} else {
return new File[] {context.getExternalFilesDir(type)};
}
}
public static File[] getExternalCacheDirs(Context context) {
if (Build.VERSION.SDK_INT >= 19) {
return context.getExternalCacheDirs();
} else {
return new File[] {context.getExternalCacheDir()};
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/Rationale.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission;
import android.content.Context;
/**
* Created by Zhenjie Yan on 2016/9/10.
*/
public interface Rationale<T> {
/**
* Show rationale to user.
*
* @param context context.
* @param data the data.
* @param executor executor.
*/
void showRationale(Context context, T data, RequestExecutor executor);
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/RequestExecutor.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission;
/**
* <p>Request executor.</p>
* Created by Zhenjie Yan on 2016/9/10.
*/
public interface RequestExecutor {
/**
* Go request permission.
*/
void execute();
/**
* Cancel the operation.
*/
void cancel();
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeActivity.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.bridge;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.view.KeyEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.yanzhenjie.permission.overlay.setting.LSettingPage;
import com.yanzhenjie.permission.overlay.setting.MSettingPage;
import com.yanzhenjie.permission.source.ActivitySource;
import com.yanzhenjie.permission.source.Source;
/**
* <p>
* Request permission.
* </p>
* Created by Zhenjie Yan on 2017/4/27.
*/
public final class BridgeActivity extends Activity {
private static final String KEY_TYPE = "KEY_TYPE";
private static final String KEY_PERMISSIONS = "KEY_PERMISSIONS";
private static final String KEY_ACTION_SUFFIX = "KEY_ACTION_SUFFIX";
/**
* Request for permissions.
*/
static void requestAppDetails(Source source, String suffix) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_APP_DETAILS);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
/**
* Request for permissions.
*/
static void requestPermission(Source source, String suffix, String[] permissions) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_PERMISSION);
intent.putExtra(KEY_PERMISSIONS, permissions);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
/**
* Request for package install.
*/
static void requestInstall(Source source, String suffix) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_INSTALL);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
/**
* Request for overlay.
*/
static void requestOverlay(Source source, String suffix) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_OVERLAY);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
/**
* Request for alert window.
*/
static void requestAlertWindow(Source source, String suffix) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_ALERT_WINDOW);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
/**
* Request for notify.
*/
static void requestNotify(Source source, String suffix) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_NOTIFY);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
/**
* Request for notification listener.
*/
static void requestNotificationListener(Source source, String suffix) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_NOTIFY_LISTENER);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
/**
* Request for write system setting.
*/
static void requestWriteSetting(Source source, String suffix) {
Intent intent = new Intent(source.getContext(), BridgeActivity.class);
intent.putExtra(KEY_TYPE, BridgeRequest.TYPE_WRITE_SETTING);
intent.putExtra(KEY_ACTION_SUFFIX, suffix);
source.startActivity(intent);
}
private String mActionSuffix;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) return;
Intent intent = getIntent();
int operation = intent.getIntExtra(KEY_TYPE, -1);
mActionSuffix = intent.getStringExtra(KEY_ACTION_SUFFIX);
switch (operation) {
case BridgeRequest.TYPE_APP_DETAILS: {
Intent appDetailsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
appDetailsIntent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(appDetailsIntent, BridgeRequest.TYPE_APP_DETAILS);
break;
}
case BridgeRequest.TYPE_PERMISSION: {
String[] permissions = intent.getStringArrayExtra(KEY_PERMISSIONS);
requestPermissions(permissions, BridgeRequest.TYPE_PERMISSION);
break;
}
case BridgeRequest.TYPE_INSTALL: {
Intent manageIntent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
manageIntent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(manageIntent, BridgeRequest.TYPE_INSTALL);
break;
}
case BridgeRequest.TYPE_OVERLAY: {
MSettingPage settingPage = new MSettingPage(new ActivitySource(this));
settingPage.start(BridgeRequest.TYPE_OVERLAY);
break;
}
case BridgeRequest.TYPE_ALERT_WINDOW: {
LSettingPage settingPage = new LSettingPage(new ActivitySource(this));
settingPage.start(BridgeRequest.TYPE_ALERT_WINDOW);
break;
}
case BridgeRequest.TYPE_NOTIFY: {
Intent settingIntent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
settingIntent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
settingIntent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(settingIntent, BridgeRequest.TYPE_NOTIFY);
break;
}
case BridgeRequest.TYPE_NOTIFY_LISTENER: {
Intent settingIntent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
settingIntent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(settingIntent, BridgeRequest.TYPE_NOTIFY_LISTENER);
break;
}
case BridgeRequest.TYPE_WRITE_SETTING: {
Intent settingIntent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
settingIntent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(settingIntent, BridgeRequest.TYPE_WRITE_SETTING);
break;
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Messenger.send(this, mActionSuffix);
finish();
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
super.startActivityForResult(intent, requestCode);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Messenger.send(this, mActionSuffix);
finish();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
return super.onKeyDown(keyCode, event);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeRequest.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.bridge;
import com.yanzhenjie.permission.source.Source;
import java.util.List;
/**
* Created by Zhenjie Yan on 2/13/19.
*/
public final class BridgeRequest {
public static final int TYPE_APP_DETAILS = 1;
public static final int TYPE_PERMISSION = 2;
public static final int TYPE_INSTALL = 3;
public static final int TYPE_OVERLAY = 4;
public static final int TYPE_ALERT_WINDOW = 5;
public static final int TYPE_NOTIFY = 6;
public static final int TYPE_NOTIFY_LISTENER = 7;
public static final int TYPE_WRITE_SETTING = 8;
private final Source mSource;
private int mType;
private Callback mCallback;
private List<String> mPermissions;
public BridgeRequest(Source source) {
this.mSource = source;
}
public Source getSource() {
return mSource;
}
public int getType() {
return mType;
}
public void setType(int type) {
mType = type;
}
public Callback getCallback() {
return mCallback;
}
public void setCallback(Callback callback) {
mCallback = callback;
}
public List<String> getPermissions() {
return mPermissions;
}
public void setPermissions(List<String> permissions) {
mPermissions = permissions;
}
public interface Callback {
void onCallback();
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeService.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.bridge;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import androidx.annotation.Nullable;
import com.yanzhenjie.permission.source.ContextSource;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2019-08-30.
*/
public class BridgeService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mStub.asBinder();
}
private IBridge.Stub mStub = new IBridge.Stub() {
private Source mSource = new ContextSource(BridgeService.this);
@Override
public void requestAppDetails(String suffix) throws RemoteException {
BridgeActivity.requestAppDetails(mSource, suffix);
}
@Override
public void requestPermission(String suffix, String[] permissions) throws RemoteException {
BridgeActivity.requestPermission(mSource, suffix, permissions);
}
@Override
public void requestInstall(String suffix) throws RemoteException {
BridgeActivity.requestInstall(mSource, suffix);
}
@Override
public void requestOverlay(String suffix) throws RemoteException {
BridgeActivity.requestOverlay(mSource, suffix);
}
@Override
public void requestAlertWindow(String suffix) throws RemoteException {
BridgeActivity.requestAlertWindow(mSource, suffix);
}
@Override
public void requestNotify(String suffix) throws RemoteException {
BridgeActivity.requestNotify(mSource, suffix);
}
@Override
public void requestNotificationListener(String suffix) throws RemoteException {
BridgeActivity.requestNotificationListener(mSource, suffix);
}
@Override
public void requestWriteSetting(String suffix) throws RemoteException {
BridgeActivity.requestWriteSetting(mSource, suffix);
}
};
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/Messenger.java
================================================
/*
* Copyright © 2018 Zhenjie Yan.
*
* 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.
*/
package com.yanzhenjie.permission.bridge;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import com.yanzhenjie.permission.AndPermission;
/**
* Created by Zhenjie Yan on 2018/6/9.
*/
class Messenger extends BroadcastReceiver {
public static void send(Context context, String suffix) {
Intent broadcast = new Intent(AndPermission.bridgeAction(context, suffix));
context.sendBroadcast(broadcast);
}
private final Context mContext;
private final Callback mCallback;
public Messenger(Context context, Callback callback) {
this.mContext = context;
this.mCallback = callback;
}
public void register(String suffix) {
IntentFilter filter = new IntentFilter(AndPermission.bridgeAction(mContext, suffix));
mContext.registerReceiver(this, filter);
}
public void unRegister() {
mContext.unregisterReceiver(this);
}
@Override
public void onReceive(Context context, Intent intent) {
mCallback.onCallback();
}
public interface Callback {
void onCallback();
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/RequestExecutor.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.bridge;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import com.yanzhenjie.permission.AndPermission;
import java.util.List;
/**
* Created by Zhenjie Yan on 2/13/19.
*/
final class RequestExecutor extends Thread implements Messenger.Callback {
private BridgeRequest mRequest;
private Messenger mMessenger;
public RequestExecutor(BridgeRequest request) {
this.mRequest = request;
}
@Override
public void run() {
Context context = mRequest.getSource().getContext();
mMessenger = new Messenger(context, this);
mMessenger.register(getName());
Intent intent = new Intent();
intent.setAction(AndPermission.bridgeAction(context, null));
intent.setPackage(context.getPackageName());
context.bindService(intent, mConnection, Service.BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
IBridge iBridge = IBridge.Stub.asInterface(iBinder);
try {
executeCurrent(iBridge);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
private void executeCurrent(IBridge iBridge) throws RemoteException {
switch (mRequest.getType()) {
case BridgeRequest.TYPE_APP_DETAILS: {
iBridge.requestAppDetails(getName());
break;
}
case BridgeRequest.TYPE_PERMISSION: {
List<String> permissions = mRequest.getPermissions();
String[] array = permissions.toArray(new String[0]);
iBridge.requestPermission(getName(), array);
break;
}
case BridgeRequest.TYPE_INSTALL: {
iBridge.requestInstall(getName());
break;
}
case BridgeRequest.TYPE_OVERLAY: {
iBridge.requestOverlay(getName());
break;
}
case BridgeRequest.TYPE_ALERT_WINDOW: {
iBridge.requestAlertWindow(getName());
break;
}
case BridgeRequest.TYPE_NOTIFY: {
iBridge.requestNotify(getName());
break;
}
case BridgeRequest.TYPE_NOTIFY_LISTENER: {
iBridge.requestNotificationListener(getName());
break;
}
case BridgeRequest.TYPE_WRITE_SETTING: {
iBridge.requestWriteSetting(getName());
break;
}
}
}
@Override
public void onCallback() {
synchronized (this) {
mMessenger.unRegister();
mRequest.getCallback().onCallback();
mRequest.getSource().getContext().unbindService(mConnection);
mMessenger = null;
mRequest = null;
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/RequestManager.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.bridge;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Created by Zhenjie Yan on 2/13/19.
*/
public class RequestManager {
private static RequestManager sManager;
public static RequestManager get() {
if (sManager == null) {
synchronized (RequestManager.class) {
if (sManager == null) {
sManager = new RequestManager();
}
}
}
return sManager;
}
private final Executor mExecutor;
private RequestManager() {
this.mExecutor = Executors.newCachedThreadPool();
}
public void add(BridgeRequest request) {
mExecutor.execute(new RequestExecutor(request));
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CalendarReadTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.CalendarContract;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class CalendarReadTest implements PermissionTest {
private ContentResolver mResolver;
CalendarReadTest(Context context) {
mResolver = context.getContentResolver();
}
@Override
public boolean test() throws Throwable {
String[] projection = new String[] {CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME};
Cursor cursor = mResolver.query(CalendarContract.Calendars.CONTENT_URI, projection, null, null, null);
if (cursor != null) {
try {
CursorTest.read(cursor);
} finally {
cursor.close();
}
return true;
} else {
return false;
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CalendarWriteTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.graphics.Color;
import android.net.Uri;
import android.provider.CalendarContract;
import com.yanzhenjie.permission.util.StringUtils;
import java.util.TimeZone;
/**
* Created by Zhenjie Yan on 2018/1/15.
*/
class CalendarWriteTest implements PermissionTest {
private static final String NAME = StringUtils.hexToText("5045524D495353494F4E");
private static final String ACCOUNT = StringUtils.hexToText("7065726D697373696F6E40676D61696C2E636F6D");
private ContentResolver mResolver;
CalendarWriteTest(Context context) {
this.mResolver = context.getContentResolver();
}
@Override
public boolean test() throws Throwable {
try {
TimeZone timeZone = TimeZone.getDefault();
ContentValues value = new ContentValues();
value.put(CalendarContract.Calendars.NAME, NAME);
value.put(CalendarContract.Calendars.ACCOUNT_NAME, ACCOUNT);
value.put(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL);
value.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, NAME);
value.put(CalendarContract.Calendars.VISIBLE, 1);
value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.getID());
value.put(CalendarContract.Calendars.OWNER_ACCOUNT, NAME);
value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0);
Uri insertUri = CalendarContract.Calendars.CONTENT_URI.buildUpon()
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, NAME)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL)
.build();
Uri resourceUri = mResolver.insert(insertUri, value);
return ContentUris.parseId(resourceUri) > 0;
} finally {
Uri deleteUri = CalendarContract.Calendars.CONTENT_URI.buildUpon().build();
mResolver.delete(deleteUri, CalendarContract.Calendars.ACCOUNT_NAME + "=?", new String[]{ACCOUNT});
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CallLogReadTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.CallLog;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class CallLogReadTest implements PermissionTest {
private ContentResolver mResolver;
CallLogReadTest(Context context) {
mResolver = context.getContentResolver();
}
@Override
public boolean test() throws Throwable {
String[] projection = new String[] {CallLog.Calls._ID, CallLog.Calls.NUMBER, CallLog.Calls.TYPE};
Cursor cursor = mResolver.query(CallLog.Calls.CONTENT_URI, projection, null, null, null);
if (cursor != null) {
try {
CursorTest.read(cursor);
} finally {
cursor.close();
}
return true;
} else {
return false;
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CallLogWriteTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.provider.CallLog;
/**
* Created by Zhenjie Yan on 2018/1/14.
*/
class CallLogWriteTest implements PermissionTest {
private ContentResolver mResolver;
CallLogWriteTest(Context context) {
this.mResolver = context.getContentResolver();
}
@Override
public boolean test() throws Throwable {
try {
ContentValues content = new ContentValues();
content.put(CallLog.Calls.TYPE, CallLog.Calls.INCOMING_TYPE);
content.put(CallLog.Calls.NUMBER, "1");
content.put(CallLog.Calls.DATE, 20080808);
content.put(CallLog.Calls.NEW, "0");
Uri resourceUri = mResolver.insert(CallLog.Calls.CONTENT_URI, content);
return ContentUris.parseId(resourceUri) > 0;
} finally {
mResolver.delete(CallLog.Calls.CONTENT_URI, CallLog.Calls.NUMBER + "=?", new String[] {"1"});
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CameraTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
/**
* Created by Zhenjie Yan on 2018/1/15.
*/
class CameraTest implements PermissionTest {
private Context mContext;
CameraTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
Camera camera = null;
try {
int cameraCount = Camera.getNumberOfCameras();
if (cameraCount <= 0) return true;
camera = Camera.open(cameraCount - 1);
Camera.Parameters parameters = camera.getParameters();
camera.setParameters(parameters);
camera.setPreviewCallback(PREVIEW_CALLBACK);
camera.startPreview();
return true;
} catch (Throwable e) {
PackageManager packageManager = mContext.getPackageManager();
return !packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA);
} finally {
if (camera != null) {
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
}
}
}
private static final Camera.PreviewCallback PREVIEW_CALLBACK = new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
};
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/ContactsReadTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class ContactsReadTest implements PermissionTest {
private ContentResolver mResolver;
ContactsReadTest(Context context) {
mResolver = context.getContentResolver();
}
@Override
public boolean test() throws Throwable {
String[] projection = new String[] {ContactsContract.Data._ID, ContactsContract.Data.DATA1};
Cursor cursor = mResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null,
null);
if (cursor != null) {
try {
CursorTest.read(cursor);
} finally {
cursor.close();
}
return true;
} else {
return false;
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/ContactsWriteTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import androidx.annotation.Nullable;
/**
* Created by Zhenjie Yan on 2018/1/14.
*/
class ContactsWriteTest implements PermissionTest {
private static final String DISPLAY_NAME = "PERMISSION";
private ContentResolver mResolver;
ContactsWriteTest(ContentResolver resolver) {
this.mResolver = resolver;
}
@Override
public boolean test() throws Throwable {
long[] idArray = insert();
long rawContactId = idArray[0];
long dataId = idArray[1];
if (rawContactId > 0 && dataId > 0) {
return delete(rawContactId, dataId);
}
return false;
}
private long[] insert() {
ContentValues values = new ContentValues();
Uri rawContractUri = mResolver.insert(ContactsContract.RawContacts.CONTENT_URI, values);
long rawContactId = ContentUris.parseId(rawContractUri);
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.DATA1, DISPLAY_NAME);
values.put(ContactsContract.Data.DATA2, DISPLAY_NAME);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
Uri dataUri = mResolver.insert(ContactsContract.Data.CONTENT_URI, values);
long dataId = ContentUris.parseId(dataUri);
return new long[]{rawContactId, dataId};
}
private boolean delete(long rawContactId, long dataId) {
int dataCount = mResolver.delete(ContactsContract.Data.CONTENT_URI, ContactsContract.Data._ID + "=?",
new String[]{Long.toString(dataId)});
int rawContactCount = mResolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.RawContacts._ID + "=?",
new String[]{Long.toString(rawContactId)});
return rawContactCount > 0 && dataCount > 0;
}
private boolean update(long rawContactId) {
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.DATA1, DISPLAY_NAME);
values.put(ContactsContract.Data.DATA2, DISPLAY_NAME);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
Uri dataUri = mResolver.insert(ContactsContract.Data.CONTENT_URI, values);
return ContentUris.parseId(dataUri) > 0;
}
@Nullable
private long[] query() {
Cursor cursor = mResolver.query(ContactsContract.Data.CONTENT_URI,
new String[]{ContactsContract.Data.RAW_CONTACT_ID, ContactsContract.Data._ID},
ContactsContract.Data.MIMETYPE + "=? and " + ContactsContract.Data.DATA1 + "=?",
new String[]{ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, DISPLAY_NAME}, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
long rawContactId = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID));
long dataId = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data._ID));
return new long[]{rawContactId, dataId};
}
}
return null;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/DoubleChecker.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import java.util.List;
/**
* Created by Zhenjie Yan on 2018/1/27.
*/
public final class DoubleChecker implements PermissionChecker {
private static final PermissionChecker STANDARD_CHECKER = new StandardChecker();
private static final PermissionChecker STRICT_CHECKER = new StrictChecker();
@Override
public boolean hasPermission(Context context, String... permissions) {
return STRICT_CHECKER.hasPermission(context, permissions) &&
STANDARD_CHECKER.hasPermission(context, permissions);
}
@Override
public boolean hasPermission(Context context, List<String> permissions) {
return STRICT_CHECKER.hasPermission(context, permissions) &&
STANDARD_CHECKER.hasPermission(context, permissions);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/LocationCoarseTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import java.util.List;
/**
* Created by Zhenjie Yan on 2018/1/14.
*/
class LocationCoarseTest implements PermissionTest {
private Context mContext;
LocationCoarseTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
LocationManager locationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
boolean networkProvider = providers.contains(LocationManager.NETWORK_PROVIDER);
if (networkProvider) {
return true;
}
PackageManager packageManager = mContext.getPackageManager();
boolean networkHardware = packageManager.hasSystemFeature(PackageManager.FEATURE_LOCATION_NETWORK);
if (!networkHardware) return true;
return !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/LocationFineTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import java.util.List;
/**
* Created by Zhenjie Yan on 2018/1/14.
*/
class LocationFineTest implements PermissionTest {
private Context mContext;
LocationFineTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
LocationManager locationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
boolean gpsProvider = providers.contains(LocationManager.GPS_PROVIDER);
boolean passiveProvider = providers.contains(LocationManager.PASSIVE_PROVIDER);
if (gpsProvider || passiveProvider) {
return true;
}
PackageManager packageManager = mContext.getPackageManager();
boolean gpsHardware = packageManager.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
if (!gpsHardware) return true;
return !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/PermissionChecker.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import java.util.List;
/**
* Created by Zhenjie Yan on 2018/1/7.
*/
public interface PermissionChecker {
/**
* Check if the calling context has a set of permissions.
*
* @param context {@link Context}.
* @param permissions one or more permissions.
*
* @return true, other wise is false.
*/
boolean hasPermission(Context context, String... permissions);
/**
* Check if the calling context has a set of permissions.
*
* @param context {@link Context}.
* @param permissions one or more permissions.
*
* @return true, other wise is false.
*/
boolean hasPermission(Context context, List<String> permissions);
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/PermissionTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.database.Cursor;
/**
* Created by Zhenjie Yan on 2018/1/14.
*/
interface PermissionTest {
boolean test() throws Throwable;
class CursorTest {
public static void read(Cursor cursor) {
int count = cursor.getCount();
if (count > 0) {
cursor.moveToFirst();
int type = cursor.getType(0);
switch (type) {
case Cursor.FIELD_TYPE_BLOB:
case Cursor.FIELD_TYPE_NULL: {
break;
}
case Cursor.FIELD_TYPE_INTEGER:
case Cursor.FIELD_TYPE_FLOAT:
case Cursor.FIELD_TYPE_STRING:
default: {
cursor.getString(0);
break;
}
}
}
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/PhoneStateReadTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.telephony.TelephonyManager;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class PhoneStateReadTest implements PermissionTest {
private Context mContext;
PhoneStateReadTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
PackageManager packageManager = mContext.getPackageManager();
if (!packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) return true;
TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) telephonyManager.getDeviceId();
else telephonyManager.getDeviceSoftwareVersion();
return true;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/RecordAudioTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by Zhenjie Yan on 2018/1/14.
*/
class RecordAudioTest implements PermissionTest {
private static final int[] RATES = new int[]{8000, 11025, 22050, 44100};
private Context mContext;
RecordAudioTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
AudioRecord audioRecord = null;
File file = null;
FileOutputStream fos = null;
try {
int[] params = findAudioParameters();
if (params == null) return !existMicrophone(mContext);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, params[0], params[1], params[2], params[3]);
int state = audioRecord.getState();
if (state != AudioRecord.STATE_INITIALIZED) return !existMicrophone(mContext);
int recordState = audioRecord.getRecordingState();
if (recordState != AudioRecord.RECORDSTATE_STOPPED) return true;
audioRecord.startRecording();
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) return true;
File cacheDir = new File(mContext.getCacheDir(), "_andpermission_audio_record_test_");
cacheDir.mkdirs();
file = new File(cacheDir, Long.toString(System.currentTimeMillis()));
if (file.exists()) file.createNewFile();
fos = new FileOutputStream(file);
byte[] buffer = new byte[params[3]];
int len = audioRecord.read(buffer, 0, params[3]);
fos.write(buffer, 0, len);
fos.flush();
} catch (Throwable e) {
return !existMicrophone(mContext);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ignored) {
}
}
if (file != null && file.exists()) {
file.delete();
}
if (audioRecord != null) {
audioRecord.release();
}
}
return true;
}
public static boolean existMicrophone(Context context) {
PackageManager packageManager = context.getPackageManager();
return packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE);
}
public static int[] findAudioParameters() {
for (int rate : RATES) {
for (int channel : new int[]{AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO}) {
for (int format : new int[]{AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT}) {
int buffer = AudioRecord.getMinBufferSize(rate, channel, format);
if (buffer != AudioRecord.ERROR_BAD_VALUE) {
return new int[]{rate, channel, format, buffer};
}
}
}
}
return null;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SensorActivityTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class SensorActivityTest implements PermissionTest {
private Context mContext;
SensorActivityTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
try {
Sensor heartRateSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
sensorManager.registerListener(SENSOR_EVENT_LISTENER, heartRateSensor, 3);
sensorManager.unregisterListener(SENSOR_EVENT_LISTENER, heartRateSensor);
} catch (Throwable e) {
PackageManager packageManager = mContext.getPackageManager();
return !packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR);
}
return true;
}
private static final SensorEventListener SENSOR_EVENT_LISTENER = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SensorHeartTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class SensorHeartTest implements PermissionTest {
private Context mContext;
SensorHeartTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
SensorManager sensorManager = (SensorManager)mContext.getSystemService(Context.SENSOR_SERVICE);
try {
Sensor heartRateSensor = sensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
sensorManager.registerListener(SENSOR_EVENT_LISTENER, heartRateSensor, 3);
sensorManager.unregisterListener(SENSOR_EVENT_LISTENER, heartRateSensor);
} catch (Throwable e) {
PackageManager packageManager = mContext.getPackageManager();
return !packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE);
}
return true;
}
private static final SensorEventListener SENSOR_EVENT_LISTENER = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SipTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
import com.yanzhenjie.permission.util.StringUtils;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class SipTest implements PermissionTest {
private static final String USER = StringUtils.hexToText("5065726D697373696F6E");
private static final String IP = StringUtils.hexToText("3132372E302E302E31");
private static final String PASSWORD = StringUtils.textToHex("70617373776F7264");
private Context mContext;
SipTest(Context context) {
this.mContext = context;
}
@Override
public boolean test() throws Throwable {
if (!SipManager.isApiSupported(mContext)) {
return true;
}
SipManager manager = SipManager.newInstance(mContext);
if (manager == null) {
return true;
}
SipProfile.Builder builder = new SipProfile.Builder(USER, IP);
builder.setPassword(PASSWORD);
SipProfile profile = builder.build();
manager.open(profile);
manager.close(profile.getUriString());
return true;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SmsReadTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.Telephony;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class SmsReadTest implements PermissionTest {
private ContentResolver mResolver;
SmsReadTest(Context context) {
mResolver = context.getContentResolver();
}
@Override
public boolean test() throws Throwable {
String[] projection = new String[] {Telephony.Sms._ID, Telephony.Sms.ADDRESS, Telephony.Sms.PERSON,
Telephony.Sms.BODY};
Cursor cursor = mResolver.query(Telephony.Sms.CONTENT_URI, projection, null, null, null);
if (cursor != null) {
try {
CursorTest.read(cursor);
} finally {
cursor.close();
}
return true;
} else {
return false;
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StandardChecker.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import java.util.Arrays;
import java.util.List;
/**
* Created by Zhenjie Yan on 2018/1/7.
*/
public final class StandardChecker implements PermissionChecker {
private static final int MODE_ASK = 4;
private static final int MODE_COMPAT = 5;
public StandardChecker() {
}
@Override
public boolean hasPermission(Context context, String... permissions) {
return hasPermission(context, Arrays.asList(permissions));
}
@Override
public boolean hasPermission(Context context, List<String> permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
AppOpsManager opsManager = null;
for (String permission : permissions) {
int result = context.checkPermission(permission, android.os.Process.myPid(), android.os.Process.myUid());
if (result == PackageManager.PERMISSION_DENIED) {
return false;
}
String op = AppOpsManager.permissionToOp(permission);
if (TextUtils.isEmpty(op)) {
continue;
}
if (opsManager == null) opsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
result = opsManager.checkOpNoThrow(op, android.os.Process.myUid(), context.getPackageName());
if (result != AppOpsManager.MODE_ALLOWED && result != MODE_ASK && result != MODE_COMPAT) {
return false;
}
}
return true;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StorageReadTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import java.io.File;
/**
* Created by Zhenjie Yan on 2018/1/16.
*/
class StorageReadTest implements PermissionTest {
StorageReadTest() {
}
@Override
public boolean test() throws Throwable {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !Environment.isExternalStorageLegacy()) return true;
if (!TextUtils.equals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState())) return true;
File directory = Environment.getExternalStorageDirectory();
if (!directory.exists()) return true;
long modified = directory.lastModified();
String[] pathList = directory.list();
return modified > 0 && pathList != null;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StorageWriteTest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import java.io.File;
/**
* Created by Zhenjie Yan on 2018/1/16.
*/
class StorageWriteTest implements PermissionTest {
private Context mContext;
StorageWriteTest(Context c) {
mContext = c;
}
@Override
public boolean test() throws Throwable {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !Environment.isExternalStorageLegacy()) return true;
if (!TextUtils.equals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState())) return true;
File directory = mContext.getExternalFilesDir(null);
if (!directory.exists()) return true;
File parent = new File(directory, "Android");
if (parent.exists() && parent.isFile()) {
if (!parent.delete()) return false;
}
if (!parent.exists()) {
if (!parent.mkdirs()) return false;
}
File file = new File(parent, "ANDROID.PERMISSION.TEST");
if (file.exists()) {
return file.delete();
} else {
return file.createNewFile();
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StrictChecker.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.checker;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Build;
import com.yanzhenjie.permission.runtime.Permission;
import java.util.List;
/**
* Created by Zhenjie Yan on 2018/1/7.
*/
public final class StrictChecker implements PermissionChecker {
public StrictChecker() {
}
@Override
public boolean hasPermission(Context context, String... permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return true;
for (String permission : permissions) {
if (!hasPermission(context, permission)) {
return false;
}
}
return true;
}
@Override
public boolean hasPermission(Context context, List<String> permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return true;
for (String permission : permissions) {
if (!hasPermission(context, permission)) {
return false;
}
}
return true;
}
private boolean hasPermission(Context context, String permission) {
try {
switch (permission) {
case Permission.READ_CALENDAR:
return checkReadCalendar(context);
case Permission.WRITE_CALENDAR:
return checkWriteCalendar(context);
case Permission.CAMERA:
return checkCamera(context);
case Permission.READ_CONTACTS:
return checkReadContacts(context);
case Permission.WRITE_CONTACTS:
return checkWriteContacts(context);
case Permission.GET_ACCOUNTS:
return true;
case Permission.ACCESS_COARSE_LOCATION:
return checkCoarseLocation(context);
case Permission.ACCESS_FINE_LOCATION:
return checkFineLocation(context);
case Permission.RECORD_AUDIO:
return checkRecordAudio(context);
case Permission.READ_PHONE_STATE:
return checkReadPhoneState(context);
case Permission.CALL_PHONE:
return true;
case Permission.READ_CALL_LOG:
return checkReadCallLog(context);
case Permission.WRITE_CALL_LOG:
return checkWriteCallLog(context);
case Permission.ADD_VOICEMAIL:
return true;
case Permission.USE_SIP:
return checkSip(context);
case Permission.PROCESS_OUTGOING_CALLS:
return true;
case Permission.BODY_SENSORS:
return checkSensorHeart(context);
case Permission.ACTIVITY_RECOGNITION:
return checkSensorActivity(context);
case Permission.SEND_SMS:
case Permission.RECEIVE_MMS:
return true;
case Permission.READ_SMS:
return checkReadSms(context);
case Permission.RECEIVE_WAP_PUSH:
case Permission.RECEIVE_SMS:
return true;
case Permission.READ_EXTERNAL_STORAGE:
return checkReadStorage();
case Permission.WRITE_EXTERNAL_STORAGE:
return checkWriteStorage(context);
}
} catch (Throwable e) {
return false;
}
return true;
}
private static boolean checkReadCalendar(Context context) throws Throwable {
PermissionTest test = new CalendarReadTest(context);
return test.test();
}
private static boolean checkWriteCalendar(Context context) throws Throwable {
PermissionTest test = new CalendarWriteTest(context);
return test.test();
}
private static boolean checkCamera(Context context) throws Throwable {
PermissionTest test = new CameraTest(context);
return test.test();
}
private static boolean checkReadContacts(Context context) throws Throwable {
PermissionTest test = new ContactsReadTest(context);
return test.test();
}
private static boolean checkWriteContacts(Context context) throws Throwable {
ContentResolver resolver = context.getContentResolver();
PermissionTest test = new ContactsWriteTest(resolver);
return test.test();
}
private static boolean checkCoarseLocation(Context context) throws Throwable {
PermissionTest test = new LocationCoarseTest(context);
return test.test();
}
private static boolean checkFineLocation(Context context) throws Throwable {
PermissionTest test = new LocationFineTest(context);
return test.test();
}
private static boolean checkRecordAudio(Context context) throws Throwable {
PermissionTest test = new RecordAudioTest(context);
return test.test();
}
private static boolean checkReadPhoneState(Context context) throws Throwable {
PermissionTest test = new PhoneStateReadTest(context);
return test.test();
}
private static boolean checkReadCallLog(Context context) throws Throwable {
PermissionTest test = new CallLogReadTest(context);
return test.test();
}
private static boolean checkWriteCallLog(Context context) throws Throwable {
PermissionTest test = new CallLogWriteTest(context);
return test.test();
}
private static boolean checkSip(Context context) throws Throwable {
PermissionTest test = new SipTest(context);
return test.test();
}
private static boolean checkSensorHeart(Context context) throws Throwable {
PermissionTest test = new SensorHeartTest(context);
return test.test();
}
private static boolean checkSensorActivity(Context context) throws Throwable {
PermissionTest test = new SensorActivityTest(context);
return test.test();
}
private static boolean checkReadSms(Context context) throws Throwable {
PermissionTest test = new SmsReadTest(context);
return test.test();
}
private static boolean checkReadStorage() throws Throwable {
PermissionTest test = new StorageReadTest();
return test.test();
}
private static boolean checkWriteStorage(Context context) throws Throwable {
PermissionTest test = new StorageWriteTest(context);
return test.test();
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/install/BaseRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.install;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.AndPermission;
import com.yanzhenjie.permission.Rationale;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.source.Source;
import java.io.File;
/**
* Created by Zhenjie Yan on 2018/6/1.
*/
abstract class BaseRequest implements InstallRequest {
private Source mSource;
private File mFile;
private Rationale<File> mRationale = new Rationale<File>() {
@Override
public void showRationale(Context context, File data, RequestExecutor executor) {
executor.execute();
}
};
private Action<File> mGranted;
private Action<File> mDenied;
BaseRequest(Source source) {
this.mSource = source;
}
@Override
public final InstallRequest file(File file) {
this.mFile = file;
return this;
}
@Override
public final InstallRequest rationale(Rationale<File> rationale) {
this.mRationale = rationale;
return this;
}
@Override
public final InstallRequest onGranted(Action<File> granted) {
this.mGranted = granted;
return this;
}
@Override
public final InstallRequest onDenied(Action<File> denied) {
this.mDenied = denied;
return this;
}
/**
* Why permissions are required.
*/
final void showRationale(RequestExecutor executor) {
mRationale.showRationale(mSource.getContext(), null, executor);
}
/**
* Start the installation.
*/
final void install() {
if (mFile != null) {
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri uri = AndPermission.getFileUri(mSource.getContext(), mFile);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
mSource.startActivity(intent);
}
}
/**
* Callback acceptance status.
*/
final void callbackSucceed() {
if (mGranted != null) {
mGranted.onAction(mFile);
}
}
/**
* Callback rejected state.
*/
final void callbackFailed() {
if (mDenied != null) {
mDenied.onAction(mFile);
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/install/InstallRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.install;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.Rationale;
import java.io.File;
/**
* Created by Zhenjie Yan on 2018/4/28.
*/
public interface InstallRequest {
/**
* The apk file.
*
* @param file apk file.
*/
InstallRequest file(File file);
/**
* Set request rationale.
*/
InstallRequest rationale(Rationale<File> rationale);
/**
* Action to be taken when all permissions are granted.
*/
InstallRequest onGranted(Action<File> granted);
/**
* Action to be taken when all permissions are denied.
*/
InstallRequest onDenied(Action<File> denied);
/**
* Start install.
*/
void start();
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/install/NRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.install;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/4/28.
*/
class NRequest extends BaseRequest {
NRequest(Source source) {
super(source);
}
@Override
public void start() {
callbackSucceed();
install();
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/install/NRequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.install;
import com.yanzhenjie.permission.Boot;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/4/28.
*/
public class NRequestFactory implements Boot.InstallRequestFactory {
@Override
public InstallRequest create(Source source) {
return new NRequest(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/install/ORequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.install;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.bridge.BridgeRequest;
import com.yanzhenjie.permission.bridge.RequestManager;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/4/28.
*/
class ORequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback {
private Source mSource;
ORequest(Source source) {
super(source);
this.mSource = source;
}
@Override
public void start() {
if (mSource.canRequestPackageInstalls()) {
callbackSucceed();
install();
} else {
showRationale(this);
}
}
@Override
public void execute() {
BridgeRequest request = new BridgeRequest(mSource);
request.setType(BridgeRequest.TYPE_INSTALL);
request.setCallback(this);
RequestManager.get().add(request);
}
@Override
public void cancel() {
callbackFailed();
}
@Override
public void onCallback() {
if (mSource.canRequestPackageInstalls()) {
callbackSucceed();
install();
} else {
callbackFailed();
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/install/ORequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.install;
import com.yanzhenjie.permission.Boot;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/4/28.
*/
public class ORequestFactory implements Boot.InstallRequestFactory {
@Override
public InstallRequest create(Source source) {
return new ORequest(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/BaseRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify;
import android.content.Context;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.Rationale;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/6/1.
*/
abstract class BaseRequest implements PermissionRequest {
private Source mSource;
private Rationale<Void> mRationale = new Rationale<Void>() {
@Override
public void showRationale(Context context, Void data, RequestExecutor executor) {
executor.execute();
}
};
private Action<Void> mGranted;
private Action<Void> mDenied;
BaseRequest(Source source) {
this.mSource = source;
}
@Override
public final PermissionRequest rationale(Rationale<Void> rationale) {
this.mRationale = rationale;
return this;
}
@Override
public final PermissionRequest onGranted(Action<Void> granted) {
this.mGranted = granted;
return this;
}
@Override
public final PermissionRequest onDenied(Action<Void> denied) {
this.mDenied = denied;
return this;
}
/**
* Why permissions are required.
*/
final void showRationale(RequestExecutor executor) {
mRationale.showRationale(mSource.getContext(), null, executor);
}
/**
* Callback acceptance status.
*/
final void callbackSucceed() {
if (mGranted != null) {
mGranted.onAction(null);
}
}
/**
* Callback rejected state.
*/
final void callbackFailed() {
if (mDenied != null) {
mDenied.onAction(null);
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/NRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.bridge.BridgeRequest;
import com.yanzhenjie.permission.bridge.RequestManager;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
class NRequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback {
private Source mSource;
NRequest(Source source) {
super(source);
this.mSource = source;
}
@Override
public void start() {
if (mSource.canNotify()) {
callbackSucceed();
} else {
showRationale(this);
}
}
@Override
public void execute() {
BridgeRequest request = new BridgeRequest(mSource);
request.setType(BridgeRequest.TYPE_APP_DETAILS);
request.setCallback(this);
RequestManager.get().add(request);
}
@Override
public void cancel() {
callbackFailed();
}
@Override
public void onCallback() {
if (mSource.canNotify()) {
callbackSucceed();
} else {
callbackFailed();
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/NRequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public class NRequestFactory implements Notify.PermissionRequestFactory {
@Override
public PermissionRequest create(Source source) {
return new NRequest(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/Notify.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify;
import android.os.Build;
import com.yanzhenjie.permission.notify.listener.J1RequestFactory;
import com.yanzhenjie.permission.notify.listener.J2RequestFactory;
import com.yanzhenjie.permission.notify.listener.ListenerRequest;
import com.yanzhenjie.permission.notify.option.NotifyOption;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2/22/19.
*/
public class Notify implements NotifyOption {
private static final PermissionRequestFactory PERMISSION_REQUEST_FACTORY;
private static final ListenerRequestFactory LISTENER_REQUEST_FACTORY;
static {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PERMISSION_REQUEST_FACTORY = new ORequestFactory();
} else {
PERMISSION_REQUEST_FACTORY = new NRequestFactory();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
LISTENER_REQUEST_FACTORY = new J2RequestFactory();
} else {
LISTENER_REQUEST_FACTORY = new J1RequestFactory();
}
}
public interface PermissionRequestFactory {
/**
* Create notify request.
*/
PermissionRequest create(Source source);
}
public interface ListenerRequestFactory {
/**
* Create notification listener request.
*/
ListenerRequest create(Source source);
}
private Source mSource;
public Notify(Source source) {
this.mSource = source;
}
public PermissionRequest permission() {
return PERMISSION_REQUEST_FACTORY.create(mSource);
}
public ListenerRequest listener() {
return LISTENER_REQUEST_FACTORY.create(mSource);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/ORequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.bridge.BridgeRequest;
import com.yanzhenjie.permission.bridge.RequestManager;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
class ORequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback {
private Source mSource;
ORequest(Source source) {
super(source);
this.mSource = source;
}
@Override
public void start() {
if (mSource.canNotify()) {
callbackSucceed();
} else {
showRationale(this);
}
}
@Override
public void execute() {
BridgeRequest request = new BridgeRequest(mSource);
request.setType(BridgeRequest.TYPE_NOTIFY);
request.setCallback(this);
RequestManager.get().add(request);
}
@Override
public void cancel() {
callbackFailed();
}
@Override
public void onCallback() {
if (mSource.canNotify()) {
callbackSucceed();
} else {
callbackFailed();
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/ORequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public class ORequestFactory implements Notify.PermissionRequestFactory {
@Override
public PermissionRequest create(Source source) {
return new ORequest(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/PermissionRequest.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.Rationale;
/**
* Created by Zhenjie Yan on 2/14/19.
*/
public interface PermissionRequest {
/**
* Set request rationale.
*/
PermissionRequest rationale(Rationale<Void> rationale);
/**
* Action to be taken when all permissions are granted.
*/
PermissionRequest onGranted(Action<Void> granted);
/**
* Action to be taken when all permissions are denied.
*/
PermissionRequest onDenied(Action<Void> denied);
/**
* Start install.
*/
void start();
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/BaseRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify.listener;
import android.content.Context;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.Rationale;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/6/1.
*/
abstract class BaseRequest implements ListenerRequest {
private Source mSource;
private Rationale<Void> mRationale = new Rationale<Void>() {
@Override
public void showRationale(Context context, Void data, RequestExecutor executor) {
executor.execute();
}
};
private Action<Void> mGranted;
private Action<Void> mDenied;
BaseRequest(Source source) {
this.mSource = source;
}
@Override
public final ListenerRequest rationale(Rationale<Void> rationale) {
this.mRationale = rationale;
return this;
}
@Override
public final ListenerRequest onGranted(Action<Void> granted) {
this.mGranted = granted;
return this;
}
@Override
public final ListenerRequest onDenied(Action<Void> denied) {
this.mDenied = denied;
return this;
}
/**
* Why permissions are required.
*/
final void showRationale(RequestExecutor executor) {
mRationale.showRationale(mSource.getContext(), null, executor);
}
/**
* Callback acceptance status.
*/
final void callbackSucceed() {
if (mGranted != null) {
mGranted.onAction(null);
}
}
/**
* Callback rejected state.
*/
final void callbackFailed() {
if (mDenied != null) {
mDenied.onAction(null);
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1Request.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify.listener;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
class J1Request extends BaseRequest implements RequestExecutor {
J1Request(Source source) {
super(source);
}
@Override
public void start() {
callbackSucceed();
}
@Override
public void execute() {
// Nothing.
}
@Override
public void cancel() {
// Nothing.
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1RequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify.listener;
import com.yanzhenjie.permission.notify.Notify;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public class J1RequestFactory implements Notify.ListenerRequestFactory {
@Override
public ListenerRequest create(Source source) {
return new J1Request(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2Request.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify.listener;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.bridge.BridgeRequest;
import com.yanzhenjie.permission.bridge.RequestManager;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
class J2Request extends BaseRequest implements RequestExecutor, BridgeRequest.Callback {
private Source mSource;
J2Request(Source source) {
super(source);
this.mSource = source;
}
@Override
public void start() {
if (mSource.canListenerNotification()) {
callbackSucceed();
} else {
showRationale(this);
}
}
@Override
public void execute() {
BridgeRequest request = new BridgeRequest(mSource);
request.setType(BridgeRequest.TYPE_NOTIFY_LISTENER);
request.setCallback(this);
RequestManager.get().add(request);
}
@Override
public void cancel() {
callbackFailed();
}
@Override
public void onCallback() {
if (mSource.canListenerNotification()) {
callbackSucceed();
} else {
callbackFailed();
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2RequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify.listener;
import com.yanzhenjie.permission.notify.Notify;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public class J2RequestFactory implements Notify.ListenerRequestFactory {
@Override
public ListenerRequest create(Source source) {
return new J2Request(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/ListenerRequest.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify.listener;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.Rationale;
/**
* Created by Zhenjie Yan on 2/14/19.
*/
public interface ListenerRequest {
/**
* Set request rationale.
*/
ListenerRequest rationale(Rationale<Void> rationale);
/**
* Action to be taken when all permissions are granted.
*/
ListenerRequest onGranted(Action<Void> granted);
/**
* Action to be taken when all permissions are denied.
*/
ListenerRequest onDenied(Action<Void> denied);
/**
* Start install.
*/
void start();
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/option/NotifyOption.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.notify.option;
import com.yanzhenjie.permission.notify.PermissionRequest;
import com.yanzhenjie.permission.notify.listener.ListenerRequest;
/**
* Created by Zhenjie Yan on 2/14/19.
*/
public interface NotifyOption {
/**
* Handle permissions.
*/
PermissionRequest permission();
/**
* Handle notify listener.
*/
ListenerRequest listener();
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/option/Option.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.option;
import com.yanzhenjie.permission.install.InstallRequest;
import com.yanzhenjie.permission.notify.option.NotifyOption;
import com.yanzhenjie.permission.overlay.OverlayRequest;
import com.yanzhenjie.permission.runtime.option.RuntimeOption;
import com.yanzhenjie.permission.setting.Setting;
/**
* Created by Zhenjie Yan on 2/22/19.
*/
public interface Option {
/**
* Handle runtime permissions.
*/
RuntimeOption runtime();
/**
* Handle request package install permission.
*/
InstallRequest install();
/**
* Handle overlay permission.
*/
OverlayRequest overlay();
/**
* Handle notification permission.
*/
NotifyOption notification();
/**
* Handle system setting.
*/
Setting setting();
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/BaseRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay;
import android.app.Dialog;
import android.content.Context;
import android.os.Build;
import android.view.Window;
import android.view.WindowManager;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.R;
import com.yanzhenjie.permission.Rationale;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/6/1.
*/
abstract class BaseRequest implements OverlayRequest {
private Source mSource;
private Rationale<Void> mRationale = new Rationale<Void>() {
@Override
public void showRationale(Context context, Void data, RequestExecutor executor) {
executor.execute();
}
};
private Action<Void> mGranted;
private Action<Void> mDenied;
BaseRequest(Source source) {
this.mSource = source;
}
@Override
public final OverlayRequest rationale(Rationale<Void> rationale) {
this.mRationale = rationale;
return this;
}
@Override
public final OverlayRequest onGranted(Action<Void> granted) {
this.mGranted = granted;
return this;
}
@Override
public final OverlayRequest onDenied(Action<Void> denied) {
this.mDenied = denied;
return this;
}
/**
* Why permissions are required.
*/
final void showRationale(RequestExecutor executor) {
mRationale.showRationale(mSource.getContext(), null, executor);
}
/**
* Callback acceptance status.
*/
final void callbackSucceed() {
if (mGranted != null) {
mGranted.onAction(null);
}
}
/**
* Callback rejected state.
*/
final void callbackFailed() {
if (mDenied != null) {
mDenied.onAction(null);
}
}
static boolean tryDisplayDialog(Context context) {
Dialog dialog = new Dialog(context, R.style.Permission_Theme_Dialog_Transparent);
Window window = dialog.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
} else {
window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
try {
dialog.show();
} catch (Exception e) {
return false;
} finally {
if (dialog.isShowing()) dialog.dismiss();
}
return true;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/LRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.bridge.BridgeRequest;
import com.yanzhenjie.permission.bridge.RequestManager;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
class LRequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback {
private Source mSource;
LRequest(Source source) {
super(source);
this.mSource = source;
}
@Override
public void start() {
if (tryDisplayDialog(mSource.getContext())) {
callbackSucceed();
} else {
showRationale(this);
}
}
@Override
public void execute() {
BridgeRequest request = new BridgeRequest(mSource);
request.setType(BridgeRequest.TYPE_ALERT_WINDOW);
request.setCallback(this);
RequestManager.get().add(request);
}
@Override
public void cancel() {
callbackFailed();
}
@Override
public void onCallback() {
if (tryDisplayDialog(mSource.getContext())) {
callbackSucceed();
} else {
callbackFailed();
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/LRequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay;
import com.yanzhenjie.permission.Boot;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public class LRequestFactory implements Boot.OverlayRequestFactory {
@Override
public OverlayRequest create(Source source) {
return new LRequest(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/MRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.bridge.BridgeRequest;
import com.yanzhenjie.permission.bridge.RequestManager;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
class MRequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback {
private Source mSource;
MRequest(Source source) {
super(source);
this.mSource = source;
}
@Override
public void start() {
if (mSource.canDrawOverlays()) {
onCallback();
} else {
showRationale(this);
}
}
@Override
public void execute() {
BridgeRequest request = new BridgeRequest(mSource);
request.setType(BridgeRequest.TYPE_OVERLAY);
request.setCallback(this);
RequestManager.get().add(request);
}
@Override
public void cancel() {
callbackFailed();
}
@Override
public void onCallback() {
if (mSource.canDrawOverlays() && tryDisplayDialog(mSource.getContext())) {
callbackSucceed();
} else {
callbackFailed();
}
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/MRequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay;
import com.yanzhenjie.permission.Boot;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public class MRequestFactory implements Boot.OverlayRequestFactory {
@Override
public OverlayRequest create(Source source) {
return new MRequest(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/OverlayRequest.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.Rationale;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public interface OverlayRequest {
/**
* Set request rationale.
*/
OverlayRequest rationale(Rationale<Void> rationale);
/**
* Action to be taken when all permissions are granted.
*/
OverlayRequest onGranted(Action<Void> granted);
/**
* Action to be taken when all permissions are denied.
*/
OverlayRequest onDenied(Action<Void> denied);
/**
* Start request.
*/
void start();
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/setting/LSettingPage.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay.setting;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/29.
*/
public class LSettingPage {
private static final String MARK = Build.MANUFACTURER.toLowerCase();
private Source mSource;
public LSettingPage(Source source) {
this.mSource = source;
}
public void start(int requestCode) {
Intent intent;
if (MARK.contains("huawei")) {
intent = huaweiApi(mSource.getContext());
} else if (MARK.contains("xiaomi")) {
intent = xiaomiApi(mSource.getContext());
} else if (MARK.contains("oppo")) {
intent = oppoApi(mSource.getContext());
} else if (MARK.contains("vivo")) {
intent = vivoApi(mSource.getContext());
} else if (MARK.contains("meizu")) {
intent = meizuApi(mSource.getContext());
} else {
intent = defaultApi(mSource.getContext());
}
try {
mSource.startActivityForResult(intent, requestCode);
} catch (Exception e) {
intent = defaultApi(mSource.getContext());
mSource.startActivityForResult(intent, requestCode);
}
}
private static Intent defaultApi(Context context) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
return intent;
}
private Intent huaweiApi(Context context) {
Intent intent = new Intent();
intent.putExtra("package", context.getPackageName());
intent.putExtra("packageName", context.getPackageName());
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
intent.setClassName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");
if (hasActivity(context, intent)) return intent;
intent.setClassName("com.huawei.systemmanager", "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");
if (hasActivity(context, intent)) return intent;
intent.setClassName("com.huawei.systemmanager", "com.huawei.notificationmanager.ui.NotificationManagmentActivity");
if (hasActivity(context, intent)) return intent;
return defaultApi(context);
}
private Intent xiaomiApi(Context context) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.putExtra("extra_pkgname", context.getPackageName());
if (hasActivity(context, intent)) return intent;
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
if (hasActivity(context, intent)) return intent;
return defaultApi(context);
}
private Intent oppoApi(Context context) {
Intent intent = new Intent();
intent.putExtra("packageName", context.getPackageName());
intent.setClassName("com.color.safecenter",
"com.color.safecenter.permission.floatwindow.FloatWindowListActivity");
if (hasActivity(context, intent)) return intent;
intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity");
if (hasActivity(context, intent)) return intent;
intent.setClassName("com.oppo.safe", "com.oppo.safe.permission.PermissionAppListActivity");
if (hasActivity(context, intent)) return intent;
return defaultApi(context);
}
private Intent vivoApi(Context context) {
Intent intent = new Intent();
intent.setClassName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.FloatWindowManager");
intent.putExtra("packagename", context.getPackageName());
if (hasActivity(context, intent)) return intent;
intent.setClassName("com.iqoo.secure", "com.iqoo.secure.safeguard.SoftPermissionDetailActivity");
if (hasActivity(context, intent)) return intent;
return defaultApi(context);
}
private Intent meizuApi(Context context) {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.putExtra("packageName", context.getPackageName());
intent.setComponent(new ComponentName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity"));
if (hasActivity(context, intent)) return intent;
return defaultApi(context);
}
private static boolean hasActivity(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
return packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/setting/MSettingPage.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.overlay.setting;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/5/30.
*/
public class MSettingPage {
private static final String MARK = Build.MANUFACTURER.toLowerCase();
private Source mSource;
public MSettingPage(Source source) {
this.mSource = source;
}
public void start(int requestCode) {
Intent intent;
if (MARK.contains("meizu")) {
intent = meiZuApi(mSource.getContext());
} else {
intent = defaultApi(mSource.getContext());
}
try {
mSource.startActivityForResult(intent, requestCode);
} catch (Exception e) {
intent = appDetailsApi(mSource.getContext());
mSource.startActivityForResult(intent, requestCode);
}
}
private static Intent appDetailsApi(Context context) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
return intent;
}
private static Intent defaultApi(Context context) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
if (hasActivity(context, intent)) return intent;
return appDetailsApi(context);
}
private static Intent meiZuApi(Context context) {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.putExtra("packageName", context.getPackageName());
intent.setClassName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity");
if (hasActivity(context, intent)) return intent;
return defaultApi(context);
}
private static boolean hasActivity(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
return packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/BaseRequest.java
================================================
/*
* Copyright 2019 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.runtime;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.Rationale;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.checker.PermissionChecker;
import com.yanzhenjie.permission.source.Source;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* Created Zhenjie Yan on 2019-10-10.
*/
abstract class BaseRequest implements PermissionRequest {
private Source mSource;
private Rationale<List<String>> mRationale = new Rationale<List<String>>() {
@Override
public void showRationale(Context context, List<String> data, RequestExecutor executor) {
executor.execute();
}
};
private Action<List<String>> mGranted;
private Action<List<String>> mDenied;
BaseRequest(Source source) {
this.mSource = source;
}
@Override
public PermissionRequest rationale(@NonNull Rationale<List<String>> rationale) {
this.mRationale = rationale;
return this;
}
@Override
public PermissionRequest onGranted(@NonNull Action<List<String>> granted) {
this.mGranted = granted;
return this;
}
@Override
public PermissionRequest onDenied(@NonNull Action<List<String>> denied) {
this.mDenied = denied;
return this;
}
/**
* Why permissions are required.
*/
final void showRationale(List<String> rationaleList, RequestExecutor executor) {
mRationale.showRationale(mSource.getContext(), rationaleList, executor);
}
/**
* Callback acceptance status.
*/
final void callbackSucceed(List<String> grantedList) {
if (mGranted != null) {
mGranted.onAction(grantedList);
}
}
/**
* Callback rejected state.
*/
final void callbackFailed(List<String> deniedList) {
if (mDenied != null) {
mDenied.onAction(deniedList);
}
}
/**
* Filter the permissions you want to apply; remove unsupported and duplicate permissions.
*/
public static List<String> filterPermissions(List<String> permissions) {
permissions = new ArrayList<>(new HashSet<>(permissions));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
permissions.remove(Permission.READ_PHONE_NUMBERS);
permissions.remove(Permission.ANSWER_PHONE_CALLS);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
permissions.remove(Permission.ACTIVITY_RECOGNITION);
permissions.remove(Permission.ACCESS_BACKGROUND_LOCATION);
}
return permissions;
}
/**
* Get denied permissions.
*/
public static List<String> getDeniedPermissions(PermissionChecker checker, Source source, List<String> permissions) {
List<String> deniedList = new ArrayList<>(1);
for (String permission : permissions) {
if (!checker.hasPermission(source.getContext(), permission)) {
deniedList.add(permission);
}
}
return deniedList;
}
/**
* Get permissions to show rationale.
*/
public static List<String> getRationalePermissions(Source source, List<String> deniedPermissions) {
List<String> rationaleList = new ArrayList<>(1);
for (String permission : deniedPermissions) {
if (source.isShowRationalePermission(permission)) {
rationaleList.add(permission);
}
}
return rationaleList;
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/LRequest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.runtime;
import androidx.annotation.NonNull;
import com.yanzhenjie.permission.checker.PermissionChecker;
import com.yanzhenjie.permission.checker.StrictChecker;
import com.yanzhenjie.permission.source.Source;
import com.yanzhenjie.permission.task.TaskExecutor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by Zhenjie Yan on 2018/1/25.
*/
class LRequest extends BaseRequest {
private static final PermissionChecker STRICT_CHECKER = new StrictChecker();
private Source mSource;
private List<String> mPermissions;
LRequest(Source source) {
super(source);
this.mSource = source;
}
@Override
public PermissionRequest permission(@NonNull String... permissions) {
mPermissions = new ArrayList<>();
mPermissions.addAll(Arrays.asList(permissions));
return this;
}
@Override
public PermissionRequest permission(@NonNull String[]... groups) {
mPermissions = new ArrayList<>();
for (String[] group : groups) {
mPermissions.addAll(Arrays.asList(group));
}
return this;
}
@Override
public void start() {
mPermissions = filterPermissions(mPermissions);
new TaskExecutor<List<String>>(mSource.getContext()) {
@Override
protected List<String> doInBackground(Void... voids) {
return getDeniedPermissions(STRICT_CHECKER, mSource, mPermissions);
}
@Override
protected void onFinish(List<String> deniedList) {
if (deniedList.isEmpty()) {
callbackSucceed(mPermissions);
} else {
callbackFailed(deniedList);
}
}
}.execute();
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/LRequestFactory.java
================================================
/*
* Copyright 2018 Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.runtime;
import com.yanzhenjie.permission.source.Source;
/**
* Created by Zhenjie Yan on 2018/4/28.
*/
public class LRequestFactory implements Runtime.PermissionRequestFactory {
@Override
public PermissionRequest create(Source source) {
return new LRequest(source);
}
}
================================================
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/MRequest.java
================================================
/*
* Copyright © Zhenjie Yan
*
* 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.
*/
package com.yanzhenjie.permission.runtime;
import androidx.annotation.NonNull;
import com.yanzhenjie.permission.RequestExecutor;
import com.yanzhenjie.permission.bri
gitextract_hhydg_6p/ ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.gradle ├── config.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── permission/ │ ├── .gitignore │ ├── build.gradle │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── aidl/ │ │ └── com/ │ │ └── yanzhenjie/ │ │ └── permission/ │ │ └── bridge/ │ │ └── IBridge.aidl │ ├── java/ │ │ └── com/ │ │ └── yanzhenjie/ │ │ └── permission/ │ │ ├── Action.java │ │ ├── AndPermission.java │ │ ├── Boot.java │ │ ├── FileProvider.java │ │ ├── Rationale.java │ │ ├── RequestExecutor.java │ │ ├── bridge/ │ │ │ ├── BridgeActivity.java │ │ │ ├── BridgeRequest.java │ │ │ ├── BridgeService.java │ │ │ ├── Messenger.java │ │ │ ├── RequestExecutor.java │ │ │ └── RequestManager.java │ │ ├── checker/ │ │ │ ├── CalendarReadTest.java │ │ │ ├── CalendarWriteTest.java │ │ │ ├── CallLogReadTest.java │ │ │ ├── CallLogWriteTest.java │ │ │ ├── CameraTest.java │ │ │ ├── ContactsReadTest.java │ │ │ ├── ContactsWriteTest.java │ │ │ ├── DoubleChecker.java │ │ │ ├── LocationCoarseTest.java │ │ │ ├── LocationFineTest.java │ │ │ ├── PermissionChecker.java │ │ │ ├── PermissionTest.java │ │ │ ├── PhoneStateReadTest.java │ │ │ ├── RecordAudioTest.java │ │ │ ├── SensorActivityTest.java │ │ │ ├── SensorHeartTest.java │ │ │ ├── SipTest.java │ │ │ ├── SmsReadTest.java │ │ │ ├── StandardChecker.java │ │ │ ├── StorageReadTest.java │ │ │ ├── StorageWriteTest.java │ │ │ └── StrictChecker.java │ │ ├── install/ │ │ │ ├── BaseRequest.java │ │ │ ├── InstallRequest.java │ │ │ ├── NRequest.java │ │ │ ├── NRequestFactory.java │ │ │ ├── ORequest.java │ │ │ └── ORequestFactory.java │ │ ├── notify/ │ │ │ ├── BaseRequest.java │ │ │ ├── NRequest.java │ │ │ ├── NRequestFactory.java │ │ │ ├── Notify.java │ │ │ ├── ORequest.java │ │ │ ├── ORequestFactory.java │ │ │ ├── PermissionRequest.java │ │ │ ├── listener/ │ │ │ │ ├── BaseRequest.java │ │ │ │ ├── J1Request.java │ │ │ │ ├── J1RequestFactory.java │ │ │ │ ├── J2Request.java │ │ │ │ ├── J2RequestFactory.java │ │ │ │ └── ListenerRequest.java │ │ │ └── option/ │ │ │ └── NotifyOption.java │ │ ├── option/ │ │ │ └── Option.java │ │ ├── overlay/ │ │ │ ├── BaseRequest.java │ │ │ ├── LRequest.java │ │ │ ├── LRequestFactory.java │ │ │ ├── MRequest.java │ │ │ ├── MRequestFactory.java │ │ │ ├── OverlayRequest.java │ │ │ └── setting/ │ │ │ ├── LSettingPage.java │ │ │ └── MSettingPage.java │ │ ├── runtime/ │ │ │ ├── BaseRequest.java │ │ │ ├── LRequest.java │ │ │ ├── LRequestFactory.java │ │ │ ├── MRequest.java │ │ │ ├── MRequestFactory.java │ │ │ ├── Permission.java │ │ │ ├── PermissionDef.java │ │ │ ├── PermissionRequest.java │ │ │ ├── Runtime.java │ │ │ ├── option/ │ │ │ │ └── RuntimeOption.java │ │ │ └── setting/ │ │ │ ├── AllRequest.java │ │ │ ├── SettingPage.java │ │ │ └── SettingRequest.java │ │ ├── setting/ │ │ │ ├── Setting.java │ │ │ └── write/ │ │ │ ├── BaseRequest.java │ │ │ ├── LWriteRequest.java │ │ │ ├── LWriteRequestFactory.java │ │ │ ├── MWriteRequest.java │ │ │ ├── MWriteRequestFactory.java │ │ │ └── WriteRequest.java │ │ ├── source/ │ │ │ ├── ActivitySource.java │ │ │ ├── ContextSource.java │ │ │ ├── FragmentSource.java │ │ │ ├── Source.java │ │ │ ├── WrapperSource.java │ │ │ └── XFragmentSource.java │ │ ├── task/ │ │ │ ├── TaskExecutor.java │ │ │ └── WaitDialog.java │ │ └── util/ │ │ └── StringUtils.java │ └── res/ │ ├── drawable/ │ │ └── permission_shape_wait_background.xml │ ├── layout/ │ │ └── permission_dialog_wait.xml │ ├── values/ │ │ ├── dimens.xml │ │ ├── string.xml │ │ └── style.xml │ ├── values-v21/ │ │ └── style.xml │ ├── values-zh/ │ │ └── string.xml │ ├── values-zh-RHK/ │ │ └── string.xml │ ├── values-zh-RTW/ │ │ └── string.xml │ └── xml/ │ └── permission_file_paths.xml ├── sample/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── assets/ │ │ └── android.apk │ ├── java/ │ │ └── com/ │ │ └── yanzhenjie/ │ │ └── permission/ │ │ └── sample/ │ │ ├── App.java │ │ ├── InstallRationale.java │ │ ├── NotifyListenerRationale.java │ │ ├── NotifyRationale.java │ │ ├── OverlayRationale.java │ │ ├── RuntimeRationale.java │ │ ├── WriteSettingRationale.java │ │ ├── app/ │ │ │ ├── MainActivity.java │ │ │ └── NotifyListenerService.java │ │ ├── util/ │ │ │ ├── FileUtils.java │ │ │ └── IOUtils.java │ │ └── widget/ │ │ ├── AlertWindow.java │ │ └── LauncherView.java │ └── res/ │ ├── layout/ │ │ ├── activity_main.xml │ │ └── window_launcher.xml │ └── values/ │ ├── array_string.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle
SYMBOL INDEX (600 symbols across 104 files)
FILE: permission/src/main/java/com/yanzhenjie/permission/Action.java
type Action (line 21) | public interface Action<T> {
method onAction (line 28) | void onAction(T data);
FILE: permission/src/main/java/com/yanzhenjie/permission/AndPermission.java
class AndPermission (line 42) | public class AndPermission {
method bridgeAction (line 46) | public static String bridgeAction(Context context, String suffix) {
method with (line 56) | public static Option with(Context context) {
method with (line 66) | public static Option with(Fragment fragment) {
method with (line 76) | public static Option with(android.app.Fragment fragment) {
method with (line 86) | public static Option with(Activity activity) {
method hasAlwaysDeniedPermission (line 97) | public static boolean hasAlwaysDeniedPermission(Context context, List<...
method hasAlwaysDeniedPermission (line 108) | public static boolean hasAlwaysDeniedPermission(Fragment fragment, Lis...
method hasAlwaysDeniedPermission (line 119) | public static boolean hasAlwaysDeniedPermission(android.app.Fragment f...
method hasAlwaysDeniedPermission (line 130) | public static boolean hasAlwaysDeniedPermission(Activity activity, Lis...
method hasAlwaysDeniedPermission (line 137) | private static boolean hasAlwaysDeniedPermission(Source source, List<S...
method hasAlwaysDeniedPermission (line 153) | public static boolean hasAlwaysDeniedPermission(Context context, Strin...
method hasAlwaysDeniedPermission (line 164) | public static boolean hasAlwaysDeniedPermission(Fragment fragment, Str...
method hasAlwaysDeniedPermission (line 175) | public static boolean hasAlwaysDeniedPermission(android.app.Fragment f...
method hasAlwaysDeniedPermission (line 186) | public static boolean hasAlwaysDeniedPermission(Activity activity, Str...
method hasAlwaysDeniedPermission (line 193) | private static boolean hasAlwaysDeniedPermission(Source source, String...
method hasPermissions (line 214) | public static boolean hasPermissions(Context context, String... permis...
method hasPermissions (line 225) | public static boolean hasPermissions(Fragment fragment, String... perm...
method hasPermissions (line 236) | public static boolean hasPermissions(android.app.Fragment fragment, St...
method hasPermissions (line 247) | public static boolean hasPermissions(Activity activity, String... perm...
method hasPermissions (line 258) | public static boolean hasPermissions(Context context, String[]... perm...
method hasPermissions (line 273) | public static boolean hasPermissions(Fragment fragment, String[]... pe...
method hasPermissions (line 284) | public static boolean hasPermissions(android.app.Fragment fragment, St...
method hasPermissions (line 295) | public static boolean hasPermissions(Activity activity, String[]... pe...
method getFileUri (line 310) | public static Uri getFileUri(Context context, File file) {
method getFileUri (line 324) | public static Uri getFileUri(Fragment fragment, File file) {
method getFileUri (line 335) | public static Uri getFileUri(android.app.Fragment fragment, File file) {
method getContextSource (line 339) | private static Source getContextSource(Context context) {
method AndPermission (line 348) | private AndPermission() {
FILE: permission/src/main/java/com/yanzhenjie/permission/Boot.java
class Boot (line 37) | public class Boot implements Option {
type InstallRequestFactory (line 56) | public interface InstallRequestFactory {
method create (line 61) | InstallRequest create(Source source);
type OverlayRequestFactory (line 64) | public interface OverlayRequestFactory {
method create (line 69) | OverlayRequest create(Source source);
method Boot (line 74) | public Boot(Source source) {
method runtime (line 78) | @Override
method install (line 83) | @Override
method overlay (line 88) | @Override
method notification (line 93) | @Override
method setting (line 98) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/FileProvider.java
class FileProvider (line 49) | public class FileProvider extends ContentProvider {
method onCreate (line 72) | @Override
method attachInfo (line 77) | @Override
method getUriForFile (line 90) | public static Uri getUriForFile(Context context, String authority, Fil...
method query (line 95) | @Override
method getType (line 123) | @Override
method insert (line 138) | @Override
method update (line 143) | @Override
method delete (line 148) | @Override
method openFile (line 154) | @Override
method getPathStrategy (line 161) | private static PathStrategy getPathStrategy(Context context, String au...
method parsePathStrategy (line 181) | private static PathStrategy parsePathStrategy(Context context, String ...
type PathStrategy (line 234) | interface PathStrategy {
method getUriForFile (line 236) | Uri getUriForFile(File file);
method getFileForUri (line 238) | File getFileForUri(Uri uri);
class SimplePathStrategy (line 241) | static class SimplePathStrategy implements PathStrategy {
method SimplePathStrategy (line 246) | SimplePathStrategy(String authority) {
method addRoot (line 250) | void addRoot(String name, File root) {
method getUriForFile (line 264) | @Override
method getFileForUri (line 298) | @Override
method modeToMode (line 325) | private static int modeToMode(String mode) {
method buildPath (line 346) | private static File buildPath(File base, String... segments) {
method copyOf (line 356) | private static String[] copyOf(String[] original, int newLength) {
method copyOf (line 362) | private static Object[] copyOf(Object[] original, int newLength) {
method getExternalFilesDirs (line 368) | private static File[] getExternalFilesDirs(Context context, String typ...
method getExternalCacheDirs (line 376) | public static File[] getExternalCacheDirs(Context context) {
FILE: permission/src/main/java/com/yanzhenjie/permission/Rationale.java
type Rationale (line 23) | public interface Rationale<T> {
method showRationale (line 32) | void showRationale(Context context, T data, RequestExecutor executor);
FILE: permission/src/main/java/com/yanzhenjie/permission/RequestExecutor.java
type RequestExecutor (line 22) | public interface RequestExecutor {
method execute (line 27) | void execute();
method cancel (line 32) | void cancel();
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeActivity.java
class BridgeActivity (line 39) | public final class BridgeActivity extends Activity {
method requestAppDetails (line 48) | static void requestAppDetails(Source source, String suffix) {
method requestPermission (line 58) | static void requestPermission(Source source, String suffix, String[] p...
method requestInstall (line 69) | static void requestInstall(Source source, String suffix) {
method requestOverlay (line 79) | static void requestOverlay(Source source, String suffix) {
method requestAlertWindow (line 89) | static void requestAlertWindow(Source source, String suffix) {
method requestNotify (line 99) | static void requestNotify(Source source, String suffix) {
method requestNotificationListener (line 109) | static void requestNotificationListener(Source source, String suffix) {
method requestWriteSetting (line 119) | static void requestWriteSetting(Source source, String suffix) {
method onCreate (line 128) | @Override
method onRequestPermissionsResult (line 186) | @Override
method startActivityForResult (line 192) | @Override
method onActivityResult (line 197) | @Override
method onKeyDown (line 204) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeRequest.java
class BridgeRequest (line 25) | public final class BridgeRequest {
method BridgeRequest (line 42) | public BridgeRequest(Source source) {
method getSource (line 46) | public Source getSource() {
method getType (line 50) | public int getType() {
method setType (line 54) | public void setType(int type) {
method getCallback (line 58) | public Callback getCallback() {
method setCallback (line 62) | public void setCallback(Callback callback) {
method getPermissions (line 66) | public List<String> getPermissions() {
method setPermissions (line 70) | public void setPermissions(List<String> permissions) {
type Callback (line 74) | public interface Callback {
method onCallback (line 76) | void onCallback();
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeService.java
class BridgeService (line 31) | public class BridgeService extends Service {
method onBind (line 33) | @Nullable
method requestAppDetails (line 43) | @Override
method requestPermission (line 48) | @Override
method requestInstall (line 53) | @Override
method requestOverlay (line 58) | @Override
method requestAlertWindow (line 63) | @Override
method requestNotify (line 68) | @Override
method requestNotificationListener (line 73) | @Override
method requestWriteSetting (line 78) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/Messenger.java
class Messenger (line 28) | class Messenger extends BroadcastReceiver {
method send (line 30) | public static void send(Context context, String suffix) {
method Messenger (line 38) | public Messenger(Context context, Callback callback) {
method register (line 43) | public void register(String suffix) {
method unRegister (line 48) | public void unRegister() {
method onReceive (line 52) | @Override
type Callback (line 57) | public interface Callback {
method onCallback (line 59) | void onCallback();
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/RequestExecutor.java
class RequestExecutor (line 33) | final class RequestExecutor extends Thread implements Messenger.Callback {
method RequestExecutor (line 38) | public RequestExecutor(BridgeRequest request) {
method run (line 42) | @Override
method onServiceConnected (line 56) | @Override
method onServiceDisconnected (line 66) | @Override
method executeCurrent (line 71) | private void executeCurrent(IBridge iBridge) throws RemoteException {
method onCallback (line 111) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/bridge/RequestManager.java
class RequestManager (line 24) | public class RequestManager {
method get (line 28) | public static RequestManager get() {
method RequestManager (line 41) | private RequestManager() {
method add (line 45) | public void add(BridgeRequest request) {
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CalendarReadTest.java
class CalendarReadTest (line 26) | class CalendarReadTest implements PermissionTest {
method CalendarReadTest (line 30) | CalendarReadTest(Context context) {
method test (line 34) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CalendarWriteTest.java
class CalendarWriteTest (line 33) | class CalendarWriteTest implements PermissionTest {
method CalendarWriteTest (line 40) | CalendarWriteTest(Context context) {
method test (line 44) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CallLogReadTest.java
class CallLogReadTest (line 26) | class CallLogReadTest implements PermissionTest {
method CallLogReadTest (line 30) | CallLogReadTest(Context context) {
method test (line 34) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CallLogWriteTest.java
class CallLogWriteTest (line 28) | class CallLogWriteTest implements PermissionTest {
method CallLogWriteTest (line 32) | CallLogWriteTest(Context context) {
method test (line 36) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/CameraTest.java
class CameraTest (line 25) | class CameraTest implements PermissionTest {
method CameraTest (line 29) | CameraTest(Context context) {
method test (line 33) | @Override
method onPreviewFrame (line 59) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/ContactsReadTest.java
class ContactsReadTest (line 26) | class ContactsReadTest implements PermissionTest {
method ContactsReadTest (line 30) | ContactsReadTest(Context context) {
method test (line 34) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/ContactsWriteTest.java
class ContactsWriteTest (line 30) | class ContactsWriteTest implements PermissionTest {
method ContactsWriteTest (line 36) | ContactsWriteTest(ContentResolver resolver) {
method test (line 40) | @Override
method insert (line 51) | private long[] insert() {
method delete (line 65) | private boolean delete(long rawContactId, long dataId) {
method update (line 73) | private boolean update(long rawContactId) {
method query (line 83) | @Nullable
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/DoubleChecker.java
class DoubleChecker (line 25) | public final class DoubleChecker implements PermissionChecker {
method hasPermission (line 30) | @Override
method hasPermission (line 36) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/LocationCoarseTest.java
class LocationCoarseTest (line 27) | class LocationCoarseTest implements PermissionTest {
method LocationCoarseTest (line 31) | LocationCoarseTest(Context context) {
method test (line 35) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/LocationFineTest.java
class LocationFineTest (line 27) | class LocationFineTest implements PermissionTest {
method LocationFineTest (line 31) | LocationFineTest(Context context) {
method test (line 35) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/PermissionChecker.java
type PermissionChecker (line 25) | public interface PermissionChecker {
method hasPermission (line 35) | boolean hasPermission(Context context, String... permissions);
method hasPermission (line 45) | boolean hasPermission(Context context, List<String> permissions);
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/PermissionTest.java
type PermissionTest (line 23) | interface PermissionTest {
method test (line 25) | boolean test() throws Throwable;
class CursorTest (line 27) | class CursorTest {
method read (line 29) | public static void read(Cursor cursor) {
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/PhoneStateReadTest.java
class PhoneStateReadTest (line 26) | class PhoneStateReadTest implements PermissionTest {
method PhoneStateReadTest (line 30) | PhoneStateReadTest(Context context) {
method test (line 34) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/RecordAudioTest.java
class RecordAudioTest (line 31) | class RecordAudioTest implements PermissionTest {
method RecordAudioTest (line 37) | RecordAudioTest(Context context) {
method test (line 41) | @Override
method existMicrophone (line 91) | public static boolean existMicrophone(Context context) {
method findAudioParameters (line 96) | public static int[] findAudioParameters() {
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SensorActivityTest.java
class SensorActivityTest (line 28) | class SensorActivityTest implements PermissionTest {
method SensorActivityTest (line 32) | SensorActivityTest(Context context) {
method test (line 36) | @Override
method onSensorChanged (line 51) | @Override
method onAccuracyChanged (line 55) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SensorHeartTest.java
class SensorHeartTest (line 28) | class SensorHeartTest implements PermissionTest {
method SensorHeartTest (line 32) | SensorHeartTest(Context context) {
method test (line 36) | @Override
method onSensorChanged (line 51) | @Override
method onAccuracyChanged (line 55) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SipTest.java
class SipTest (line 27) | class SipTest implements PermissionTest {
method SipTest (line 35) | SipTest(Context context) {
method test (line 39) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/SmsReadTest.java
class SmsReadTest (line 26) | class SmsReadTest implements PermissionTest {
method SmsReadTest (line 30) | SmsReadTest(Context context) {
method test (line 34) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StandardChecker.java
class StandardChecker (line 30) | public final class StandardChecker implements PermissionChecker {
method StandardChecker (line 35) | public StandardChecker() {
method hasPermission (line 38) | @Override
method hasPermission (line 43) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StorageReadTest.java
class StorageReadTest (line 27) | class StorageReadTest implements PermissionTest {
method StorageReadTest (line 29) | StorageReadTest() {
method test (line 32) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StorageWriteTest.java
class StorageWriteTest (line 28) | class StorageWriteTest implements PermissionTest {
method StorageWriteTest (line 32) | StorageWriteTest(Context c) {
method test (line 36) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/checker/StrictChecker.java
class StrictChecker (line 29) | public final class StrictChecker implements PermissionChecker {
method StrictChecker (line 31) | public StrictChecker() {
method hasPermission (line 34) | @Override
method hasPermission (line 46) | @Override
method hasPermission (line 58) | private boolean hasPermission(Context context, String permission) {
method checkReadCalendar (line 116) | private static boolean checkReadCalendar(Context context) throws Throw...
method checkWriteCalendar (line 121) | private static boolean checkWriteCalendar(Context context) throws Thro...
method checkCamera (line 126) | private static boolean checkCamera(Context context) throws Throwable {
method checkReadContacts (line 131) | private static boolean checkReadContacts(Context context) throws Throw...
method checkWriteContacts (line 136) | private static boolean checkWriteContacts(Context context) throws Thro...
method checkCoarseLocation (line 142) | private static boolean checkCoarseLocation(Context context) throws Thr...
method checkFineLocation (line 147) | private static boolean checkFineLocation(Context context) throws Throw...
method checkRecordAudio (line 152) | private static boolean checkRecordAudio(Context context) throws Throwa...
method checkReadPhoneState (line 157) | private static boolean checkReadPhoneState(Context context) throws Thr...
method checkReadCallLog (line 162) | private static boolean checkReadCallLog(Context context) throws Throwa...
method checkWriteCallLog (line 167) | private static boolean checkWriteCallLog(Context context) throws Throw...
method checkSip (line 172) | private static boolean checkSip(Context context) throws Throwable {
method checkSensorHeart (line 177) | private static boolean checkSensorHeart(Context context) throws Throwa...
method checkSensorActivity (line 182) | private static boolean checkSensorActivity(Context context) throws Thr...
method checkReadSms (line 187) | private static boolean checkReadSms(Context context) throws Throwable {
method checkReadStorage (line 192) | private static boolean checkReadStorage() throws Throwable {
method checkWriteStorage (line 197) | private static boolean checkWriteStorage(Context context) throws Throw...
FILE: permission/src/main/java/com/yanzhenjie/permission/install/BaseRequest.java
class BaseRequest (line 33) | abstract class BaseRequest implements InstallRequest {
method showRationale (line 39) | @Override
method BaseRequest (line 47) | BaseRequest(Source source) {
method file (line 51) | @Override
method rationale (line 57) | @Override
method onGranted (line 63) | @Override
method onDenied (line 69) | @Override
method showRationale (line 78) | final void showRationale(RequestExecutor executor) {
method install (line 85) | final void install() {
method callbackSucceed (line 99) | final void callbackSucceed() {
method callbackFailed (line 108) | final void callbackFailed() {
FILE: permission/src/main/java/com/yanzhenjie/permission/install/InstallRequest.java
type InstallRequest (line 26) | public interface InstallRequest {
method file (line 33) | InstallRequest file(File file);
method rationale (line 38) | InstallRequest rationale(Rationale<File> rationale);
method onGranted (line 43) | InstallRequest onGranted(Action<File> granted);
method onDenied (line 48) | InstallRequest onDenied(Action<File> denied);
method start (line 53) | void start();
FILE: permission/src/main/java/com/yanzhenjie/permission/install/NRequest.java
class NRequest (line 23) | class NRequest extends BaseRequest {
method NRequest (line 25) | NRequest(Source source) {
method start (line 29) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/install/NRequestFactory.java
class NRequestFactory (line 24) | public class NRequestFactory implements Boot.InstallRequestFactory {
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/install/ORequest.java
class ORequest (line 26) | class ORequest extends BaseRequest implements RequestExecutor, BridgeReq...
method ORequest (line 30) | ORequest(Source source) {
method start (line 35) | @Override
method execute (line 45) | @Override
method cancel (line 53) | @Override
method onCallback (line 58) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/install/ORequestFactory.java
class ORequestFactory (line 24) | public class ORequestFactory implements Boot.InstallRequestFactory {
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/BaseRequest.java
class BaseRequest (line 28) | abstract class BaseRequest implements PermissionRequest {
method showRationale (line 33) | @Override
method BaseRequest (line 41) | BaseRequest(Source source) {
method rationale (line 45) | @Override
method onGranted (line 51) | @Override
method onDenied (line 57) | @Override
method showRationale (line 66) | final void showRationale(RequestExecutor executor) {
method callbackSucceed (line 73) | final void callbackSucceed() {
method callbackFailed (line 82) | final void callbackFailed() {
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/NRequest.java
class NRequest (line 26) | class NRequest extends BaseRequest implements RequestExecutor, BridgeReq...
method NRequest (line 30) | NRequest(Source source) {
method start (line 35) | @Override
method execute (line 44) | @Override
method cancel (line 52) | @Override
method onCallback (line 57) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/NRequestFactory.java
class NRequestFactory (line 23) | public class NRequestFactory implements Notify.PermissionRequestFactory {
method create (line 25) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/Notify.java
class Notify (line 29) | public class Notify implements NotifyOption {
type PermissionRequestFactory (line 48) | public interface PermissionRequestFactory {
method create (line 53) | PermissionRequest create(Source source);
type ListenerRequestFactory (line 56) | public interface ListenerRequestFactory {
method create (line 61) | ListenerRequest create(Source source);
method Notify (line 66) | public Notify(Source source) {
method permission (line 70) | public PermissionRequest permission() {
method listener (line 74) | public ListenerRequest listener() {
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/ORequest.java
class ORequest (line 26) | class ORequest extends BaseRequest implements RequestExecutor, BridgeReq...
method ORequest (line 30) | ORequest(Source source) {
method start (line 35) | @Override
method execute (line 44) | @Override
method cancel (line 52) | @Override
method onCallback (line 57) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/ORequestFactory.java
class ORequestFactory (line 23) | public class ORequestFactory implements Notify.PermissionRequestFactory {
method create (line 25) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/PermissionRequest.java
type PermissionRequest (line 24) | public interface PermissionRequest {
method rationale (line 29) | PermissionRequest rationale(Rationale<Void> rationale);
method onGranted (line 34) | PermissionRequest onGranted(Action<Void> granted);
method onDenied (line 39) | PermissionRequest onDenied(Action<Void> denied);
method start (line 44) | void start();
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/BaseRequest.java
class BaseRequest (line 28) | abstract class BaseRequest implements ListenerRequest {
method showRationale (line 33) | @Override
method BaseRequest (line 41) | BaseRequest(Source source) {
method rationale (line 45) | @Override
method onGranted (line 51) | @Override
method onDenied (line 57) | @Override
method showRationale (line 66) | final void showRationale(RequestExecutor executor) {
method callbackSucceed (line 73) | final void callbackSucceed() {
method callbackFailed (line 82) | final void callbackFailed() {
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1Request.java
class J1Request (line 24) | class J1Request extends BaseRequest implements RequestExecutor {
method J1Request (line 26) | J1Request(Source source) {
method start (line 30) | @Override
method execute (line 35) | @Override
method cancel (line 40) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1RequestFactory.java
class J1RequestFactory (line 24) | public class J1RequestFactory implements Notify.ListenerRequestFactory {
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2Request.java
class J2Request (line 26) | class J2Request extends BaseRequest implements RequestExecutor, BridgeRe...
method J2Request (line 30) | J2Request(Source source) {
method start (line 35) | @Override
method execute (line 44) | @Override
method cancel (line 52) | @Override
method onCallback (line 57) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2RequestFactory.java
class J2RequestFactory (line 24) | public class J2RequestFactory implements Notify.ListenerRequestFactory {
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/listener/ListenerRequest.java
type ListenerRequest (line 24) | public interface ListenerRequest {
method rationale (line 29) | ListenerRequest rationale(Rationale<Void> rationale);
method onGranted (line 34) | ListenerRequest onGranted(Action<Void> granted);
method onDenied (line 39) | ListenerRequest onDenied(Action<Void> denied);
method start (line 44) | void start();
FILE: permission/src/main/java/com/yanzhenjie/permission/notify/option/NotifyOption.java
type NotifyOption (line 24) | public interface NotifyOption {
method permission (line 29) | PermissionRequest permission();
method listener (line 34) | ListenerRequest listener();
FILE: permission/src/main/java/com/yanzhenjie/permission/option/Option.java
type Option (line 27) | public interface Option {
method runtime (line 32) | RuntimeOption runtime();
method install (line 37) | InstallRequest install();
method overlay (line 42) | OverlayRequest overlay();
method notification (line 47) | NotifyOption notification();
method setting (line 52) | Setting setting();
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/BaseRequest.java
class BaseRequest (line 33) | abstract class BaseRequest implements OverlayRequest {
method showRationale (line 38) | @Override
method BaseRequest (line 46) | BaseRequest(Source source) {
method rationale (line 50) | @Override
method onGranted (line 56) | @Override
method onDenied (line 62) | @Override
method showRationale (line 71) | final void showRationale(RequestExecutor executor) {
method callbackSucceed (line 78) | final void callbackSucceed() {
method callbackFailed (line 87) | final void callbackFailed() {
method tryDisplayDialog (line 93) | static boolean tryDisplayDialog(Context context) {
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/LRequest.java
class LRequest (line 26) | class LRequest extends BaseRequest implements RequestExecutor, BridgeReq...
method LRequest (line 30) | LRequest(Source source) {
method start (line 35) | @Override
method execute (line 44) | @Override
method cancel (line 52) | @Override
method onCallback (line 57) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/LRequestFactory.java
class LRequestFactory (line 24) | public class LRequestFactory implements Boot.OverlayRequestFactory {
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/MRequest.java
class MRequest (line 26) | class MRequest extends BaseRequest implements RequestExecutor, BridgeReq...
method MRequest (line 30) | MRequest(Source source) {
method start (line 35) | @Override
method execute (line 44) | @Override
method cancel (line 52) | @Override
method onCallback (line 57) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/MRequestFactory.java
class MRequestFactory (line 24) | public class MRequestFactory implements Boot.OverlayRequestFactory {
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/OverlayRequest.java
type OverlayRequest (line 24) | public interface OverlayRequest {
method rationale (line 29) | OverlayRequest rationale(Rationale<Void> rationale);
method onGranted (line 34) | OverlayRequest onGranted(Action<Void> granted);
method onDenied (line 39) | OverlayRequest onDenied(Action<Void> denied);
method start (line 44) | void start();
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/setting/LSettingPage.java
class LSettingPage (line 31) | public class LSettingPage {
method LSettingPage (line 37) | public LSettingPage(Source source) {
method start (line 41) | public void start(int requestCode) {
method defaultApi (line 65) | private static Intent defaultApi(Context context) {
method huaweiApi (line 71) | private Intent huaweiApi(Context context) {
method xiaomiApi (line 88) | private Intent xiaomiApi(Context context) {
method oppoApi (line 99) | private Intent oppoApi(Context context) {
method vivoApi (line 115) | private Intent vivoApi(Context context) {
method meizuApi (line 127) | private Intent meizuApi(Context context) {
method hasActivity (line 136) | private static boolean hasActivity(Context context, Intent intent) {
FILE: permission/src/main/java/com/yanzhenjie/permission/overlay/setting/MSettingPage.java
class MSettingPage (line 30) | public class MSettingPage {
method MSettingPage (line 36) | public MSettingPage(Source source) {
method start (line 40) | public void start(int requestCode) {
method appDetailsApi (line 56) | private static Intent appDetailsApi(Context context) {
method defaultApi (line 62) | private static Intent defaultApi(Context context) {
method meiZuApi (line 70) | private static Intent meiZuApi(Context context) {
method hasActivity (line 79) | private static boolean hasActivity(Context context, Intent intent) {
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/BaseRequest.java
class BaseRequest (line 36) | abstract class BaseRequest implements PermissionRequest {
method showRationale (line 41) | @Override
method BaseRequest (line 49) | BaseRequest(Source source) {
method rationale (line 53) | @Override
method onGranted (line 59) | @Override
method onDenied (line 65) | @Override
method showRationale (line 74) | final void showRationale(List<String> rationaleList, RequestExecutor e...
method callbackSucceed (line 81) | final void callbackSucceed(List<String> grantedList) {
method callbackFailed (line 90) | final void callbackFailed(List<String> deniedList) {
method filterPermissions (line 99) | public static List<String> filterPermissions(List<String> permissions) {
method getDeniedPermissions (line 116) | public static List<String> getDeniedPermissions(PermissionChecker chec...
method getRationalePermissions (line 129) | public static List<String> getRationalePermissions(Source source, List...
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/LRequest.java
class LRequest (line 32) | class LRequest extends BaseRequest {
method LRequest (line 40) | LRequest(Source source) {
method permission (line 45) | @Override
method permission (line 52) | @Override
method start (line 61) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/LRequestFactory.java
class LRequestFactory (line 23) | public class LRequestFactory implements Runtime.PermissionRequestFactory {
method create (line 25) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/MRequest.java
class MRequest (line 36) | class MRequest extends BaseRequest implements RequestExecutor, BridgeReq...
method MRequest (line 47) | MRequest(Source source) {
method permission (line 52) | @Override
method permission (line 59) | @Override
method start (line 68) | @Override
method execute (line 85) | @Override
method cancel (line 94) | @Override
method onCallback (line 99) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/MRequestFactory.java
class MRequestFactory (line 23) | public class MRequestFactory implements Runtime.PermissionRequestFactory {
method create (line 25) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/Permission.java
class Permission (line 31) | public class Permission {
class Group (line 71) | public static final class Group {
method transformText (line 103) | public static List<String> transformText(Context context, String... pe...
method transformText (line 110) | public static List<String> transformText(Context context, String[]... ...
method transformText (line 121) | public static List<String> transformText(Context context, List<String>...
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/PermissionRequest.java
type PermissionRequest (line 29) | public interface PermissionRequest {
method permission (line 34) | PermissionRequest permission(@NonNull @PermissionDef String... permiss...
method permission (line 41) | PermissionRequest permission(@NonNull String[]... groups);
method rationale (line 46) | PermissionRequest rationale(@NonNull Rationale<List<String>> rationale);
method onGranted (line 51) | PermissionRequest onGranted(@NonNull Action<List<String>> granted);
method onDenied (line 56) | PermissionRequest onDenied(@NonNull Action<List<String>> denied);
method start (line 61) | void start();
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/Runtime.java
class Runtime (line 37) | public class Runtime implements RuntimeOption {
type PermissionRequestFactory (line 52) | public interface PermissionRequestFactory {
method create (line 57) | PermissionRequest create(Source source);
method Runtime (line 62) | public Runtime(Source source) {
method permission (line 66) | @Override
method permission (line 72) | @Override
method setting (line 83) | @Override
method checkPermissions (line 94) | private void checkPermissions(String... permissions) {
method getManifestPermissions (line 116) | public static List<String> getManifestPermissions(Context context) {
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/option/RuntimeOption.java
type RuntimeOption (line 28) | public interface RuntimeOption {
method permission (line 33) | PermissionRequest permission(@NonNull @PermissionDef String... permiss...
method permission (line 40) | PermissionRequest permission(@NonNull String[]... groups);
method setting (line 45) | SettingRequest setting();
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/setting/AllRequest.java
class AllRequest (line 24) | public class AllRequest implements SettingRequest {
method AllRequest (line 28) | public AllRequest(Source source) {
method start (line 32) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/setting/SettingPage.java
class SettingPage (line 30) | public class SettingPage {
method SettingPage (line 36) | public SettingPage(Source source) {
method start (line 45) | public void start(int requestCode) {
method defaultApi (line 68) | private static Intent defaultApi(Context context) {
method huaweiApi (line 74) | private static Intent huaweiApi(Context context) {
method xiaomiApi (line 82) | private static Intent xiaomiApi(Context context) {
method vivoApi (line 96) | private static Intent vivoApi(Context context) {
method oppoApi (line 108) | private static Intent oppoApi(Context context) {
method meizuApi (line 120) | private static Intent meizuApi(Context context) {
method hasActivity (line 129) | private static boolean hasActivity(Context context, Intent intent) {
FILE: permission/src/main/java/com/yanzhenjie/permission/runtime/setting/SettingRequest.java
type SettingRequest (line 21) | public interface SettingRequest {
method start (line 26) | void start(int requestCode);
FILE: permission/src/main/java/com/yanzhenjie/permission/setting/Setting.java
class Setting (line 28) | public class Setting {
type SettingRequestFactory (line 40) | public interface SettingRequestFactory {
method create (line 42) | WriteRequest create(Source source);
method Setting (line 47) | public Setting(Source source) {
method write (line 54) | public WriteRequest write() {
FILE: permission/src/main/java/com/yanzhenjie/permission/setting/write/BaseRequest.java
class BaseRequest (line 28) | abstract class BaseRequest implements WriteRequest {
method showRationale (line 33) | @Override
method BaseRequest (line 41) | BaseRequest(Source source) {
method rationale (line 45) | @Override
method onGranted (line 51) | @Override
method onDenied (line 57) | @Override
method showRationale (line 66) | final void showRationale(RequestExecutor executor) {
method callbackSucceed (line 73) | final void callbackSucceed() {
method callbackFailed (line 82) | final void callbackFailed() {
FILE: permission/src/main/java/com/yanzhenjie/permission/setting/write/LWriteRequest.java
class LWriteRequest (line 23) | public class LWriteRequest extends BaseRequest {
method LWriteRequest (line 25) | public LWriteRequest(Source source) {
method start (line 29) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/setting/write/LWriteRequestFactory.java
class LWriteRequestFactory (line 24) | public class LWriteRequestFactory implements Setting.SettingRequestFacto...
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/setting/write/MWriteRequest.java
class MWriteRequest (line 26) | public class MWriteRequest extends BaseRequest implements RequestExecuto...
method MWriteRequest (line 30) | public MWriteRequest(Source source) {
method start (line 35) | @Override
method execute (line 44) | @Override
method cancel (line 52) | @Override
method onCallback (line 57) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/setting/write/MWriteRequestFactory.java
class MWriteRequestFactory (line 24) | public class MWriteRequestFactory implements Setting.SettingRequestFacto...
method create (line 26) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/setting/write/WriteRequest.java
type WriteRequest (line 24) | public interface WriteRequest {
method rationale (line 29) | WriteRequest rationale(Rationale<Void> rationale);
method onGranted (line 34) | WriteRequest onGranted(Action<Void> granted);
method onDenied (line 39) | WriteRequest onDenied(Action<Void> denied);
method start (line 44) | void start();
FILE: permission/src/main/java/com/yanzhenjie/permission/source/ActivitySource.java
class ActivitySource (line 27) | public class ActivitySource extends Source {
method ActivitySource (line 31) | public ActivitySource(Activity activity) {
method getContext (line 35) | @Override
method startActivity (line 40) | @Override
method startActivityForResult (line 45) | @Override
method isShowRationalePermission (line 50) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/source/ContextSource.java
class ContextSource (line 29) | public class ContextSource extends Source {
method ContextSource (line 33) | public ContextSource(Context context) {
method getContext (line 37) | @Override
method startActivity (line 42) | @Override
method startActivityForResult (line 48) | @Override
method isShowRationalePermission (line 53) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/source/FragmentSource.java
class FragmentSource (line 27) | public class FragmentSource extends Source {
method FragmentSource (line 31) | public FragmentSource(Fragment fragment) {
method getContext (line 35) | @Override
method startActivity (line 40) | @Override
method startActivityForResult (line 45) | @Override
method isShowRationalePermission (line 50) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/source/Source.java
class Source (line 35) | public abstract class Source {
method getContext (line 53) | public abstract Context getContext();
method startActivity (line 55) | public abstract void startActivity(Intent intent);
method startActivityForResult (line 57) | public abstract void startActivityForResult(Intent intent, int request...
method isShowRationalePermission (line 59) | public abstract boolean isShowRationalePermission(String permission);
method getTargetSdkVersion (line 61) | public int getTargetSdkVersion() {
method getPackageName (line 68) | public String getPackageName() {
method getPackageManager (line 75) | private PackageManager getPackageManager() {
method getAppOpsManager (line 82) | @RequiresApi(api = Build.VERSION_CODES.KITKAT)
method getNotificationManager (line 90) | private NotificationManager getNotificationManager() {
method canRequestPackageInstalls (line 97) | public final boolean canRequestPackageInstalls() {
method canDrawOverlays (line 111) | public final boolean canDrawOverlays() {
method canNotify (line 123) | public final boolean canNotify() {
method canListenerNotification (line 133) | public final boolean canListenerNotification() {
method canWriteSetting (line 143) | public final boolean canWriteSetting() {
method reflectionOps (line 155) | @RequiresApi(api = Build.VERSION_CODES.KITKAT)
FILE: permission/src/main/java/com/yanzhenjie/permission/source/WrapperSource.java
class WrapperSource (line 24) | public class WrapperSource extends Source {
method WrapperSource (line 28) | public WrapperSource(Source source) {
method getContext (line 32) | @Override
method startActivity (line 37) | @Override
method startActivityForResult (line 42) | @Override
method isShowRationalePermission (line 47) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/source/XFragmentSource.java
class XFragmentSource (line 28) | public class XFragmentSource extends Source {
method XFragmentSource (line 32) | public XFragmentSource(Fragment fragment) {
method getContext (line 36) | @Override
method startActivity (line 41) | @Override
method startActivityForResult (line 46) | @Override
method isShowRationalePermission (line 51) | @Override
FILE: permission/src/main/java/com/yanzhenjie/permission/task/TaskExecutor.java
class TaskExecutor (line 28) | public abstract class TaskExecutor<T> extends AsyncTask<Void, Void, T> {
method TaskExecutor (line 34) | public TaskExecutor(Context context) {
method onPreExecute (line 39) | @Override
method onPostExecute (line 46) | @Override
method onFinish (line 54) | protected abstract void onFinish(T t);
method execute (line 59) | public final void execute() {
FILE: permission/src/main/java/com/yanzhenjie/permission/task/WaitDialog.java
class WaitDialog (line 28) | public class WaitDialog extends AppCompatDialog {
method WaitDialog (line 30) | public WaitDialog(@NonNull Context context) {
FILE: permission/src/main/java/com/yanzhenjie/permission/util/StringUtils.java
class StringUtils (line 21) | public class StringUtils {
method textToHex (line 26) | public static String textToHex(String text) {
method hexToText (line 40) | public static String hexToText(String hexText) {
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/App.java
class App (line 27) | public class App extends Application {
method onCreate (line 31) | @Override
method get (line 37) | public static App get() {
method showLauncherView (line 41) | public void showLauncherView() {
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/InstallRationale.java
class InstallRationale (line 30) | public class InstallRationale implements Rationale<File> {
method showRationale (line 32) | @Override
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/NotifyListenerRationale.java
class NotifyListenerRationale (line 28) | public class NotifyListenerRationale implements Rationale<Void> {
method showRationale (line 30) | @Override
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/NotifyRationale.java
class NotifyRationale (line 28) | public class NotifyRationale implements Rationale<Void> {
method showRationale (line 30) | @Override
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/OverlayRationale.java
class OverlayRationale (line 28) | public class OverlayRationale implements Rationale<Void> {
method showRationale (line 30) | @Override
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/RuntimeRationale.java
class RuntimeRationale (line 32) | public final class RuntimeRationale implements Rationale<List<String>> {
method showRationale (line 34) | @Override
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/WriteSettingRationale.java
class WriteSettingRationale (line 28) | public class WriteSettingRationale implements Rationale<Void> {
method showRationale (line 30) | @Override
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/app/MainActivity.java
class MainActivity (line 64) | public class MainActivity extends AppCompatActivity implements View.OnCl...
method onCreate (line 68) | @Override
method onClick (line 96) | @Override
method requestPermission (line 365) | private void requestPermission(@PermissionDef String... permissions) {
method showSettingDialog (line 391) | public void showSettingDialog(Context context, final List<String> perm...
method setPermission (line 416) | private void setPermission() {
method onActivityResult (line 420) | @Override
method requestNotification (line 434) | private void requestNotification() {
method requestNotificationListener (line 457) | private void requestNotificationListener() {
method requestPermissionForInstallPackage (line 480) | private void requestPermissionForInstallPackage() {
method writeApkForInstallPackage (line 514) | private void writeApkForInstallPackage() {
method installPackage (line 558) | private void installPackage(File apkFile) {
method requestPermissionForAlertWindow (line 578) | private void requestPermissionForAlertWindow() {
method requestWriteSystemSetting (line 592) | private void requestWriteSystemSetting() {
method showAlertWindow (line 606) | private void showAlertWindow() {
method createMenu (line 618) | private PopupMenu createMenu(View v, String[] menuArray) {
method toast (line 628) | protected void toast(@StringRes int message) {
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/app/NotifyListenerService.java
class NotifyListenerService (line 27) | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
method onNotificationPosted (line 30) | @Override
method onNotificationRemoved (line 34) | @Override
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/util/FileUtils.java
class FileUtils (line 29) | public class FileUtils {
method getFileDir (line 31) | public static File getFileDir(Context context) {
method getFileDir (line 35) | public static File getFileDir(Context context, @Nullable String type) {
method externalAvailable (line 46) | public static boolean externalAvailable() {
method getExternalDir (line 50) | public static File getExternalDir(Context context) {
method getExternalDir (line 54) | public static File getExternalDir(Context context, @Nullable String ty...
method getRootDir (line 72) | public static File getRootDir() {
method getRootDir (line 76) | public static File getRootDir(@Nullable String type) {
method createDir (line 94) | public static void createDir(File dir) {
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/util/IOUtils.java
class IOUtils (line 27) | public class IOUtils {
method write (line 29) | public static void write(InputStream in, OutputStream out) throws IOEx...
method close (line 38) | public static void close(Closeable closeable) {
method flush (line 46) | public static void flush(Flushable flushable) {
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/widget/AlertWindow.java
class AlertWindow (line 31) | public class AlertWindow {
method AlertWindow (line 40) | public AlertWindow(Context context) {
method create (line 45) | private void create() {
method setContentView (line 69) | public void setContentView(int layoutId) {
method setContentView (line 78) | public void setContentView(View view) {
method isShowing (line 95) | public boolean isShowing() {
method show (line 102) | public void show() {
method dismiss (line 114) | public void dismiss() {
FILE: sample/src/main/java/com/yanzhenjie/permission/sample/widget/LauncherView.java
class LauncherView (line 28) | public class LauncherView extends RelativeLayout implements View.OnClick...
method LauncherView (line 32) | public LauncherView(Context context) {
method LauncherView (line 36) | public LauncherView(Context context, AttributeSet attrs) {
method LauncherView (line 40) | public LauncherView(Context context, AttributeSet attrs, int defStyleA...
method onClick (line 46) | @Override
method setCancelClickListener (line 59) | public void setCancelClickListener(OnClickListener cancelClickListener) {
Condensed preview — 143 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (356K chars).
[
{
"path": ".gitignore",
"chars": 88,
"preview": "*.iml\n/.idea/\n/build/\n.gradle\n/local.properties\n.DS_Store\n/captures\n.externalNativeBuild"
},
{
"path": "CONTRIBUTING.md",
"chars": 774,
"preview": "# Contributing to AndPermission\nFirst off, thanks for taking the time to contribute. \n\nThe following is a set of guidel"
},
{
"path": "LICENSE",
"chars": 11342,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 1715,
"preview": "# AndPermission\n1. Request for runtime permissions. \n2. Share private files. \n3. Request to install unknown source ap"
},
{
"path": "build.gradle",
"chars": 607,
"preview": "apply from: \"config.gradle\"\n\nbuildscript {\n repositories {\n google()\n jcenter {url 'https://maven.aliyu"
},
{
"path": "config.gradle",
"chars": 1502,
"preview": "ext {\n plugins = [application: 'com.android.application',\n library : 'com.android.library',\n "
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 201,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dist"
},
{
"path": "gradle.properties",
"chars": 25,
"preview": "android.useAndroidX=true\n"
},
{
"path": "gradlew",
"chars": 4971,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "gradlew.bat",
"chars": 2314,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
},
{
"path": "permission/.gitignore",
"chars": 6,
"preview": "/build"
},
{
"path": "permission/build.gradle",
"chars": 436,
"preview": "apply plugin: rootProject.ext.plugins.library\n\nandroid {\n compileSdkVersion rootProject.ext.android.compileSdkVersion"
},
{
"path": "permission/src/main/AndroidManifest.xml",
"chars": 2171,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/aidl/com/yanzhenjie/permission/bridge/IBridge.aidl",
"chars": 851,
"preview": "package com.yanzhenjie.permission.bridge;\n\ninterface IBridge {\n /**\n * Request for permissions.\n */\n void "
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/Action.java",
"chars": 807,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/AndPermission.java",
"chars": 12017,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/Boot.java",
"chars": 2982,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/FileProvider.java",
"chars": 14381,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/Rationale.java",
"chars": 966,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/RequestExecutor.java",
"chars": 874,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeActivity.java",
"chars": 8226,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeRequest.java",
"chars": 1985,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeService.java",
"chars": 2645,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/bridge/Messenger.java",
"chars": 1783,
"preview": "/*\n * Copyright © 2018 Zhenjie Yan.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/bridge/RequestExecutor.java",
"chars": 3898,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/bridge/RequestManager.java",
"chars": 1373,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/CalendarReadTest.java",
"chars": 1545,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/CalendarWriteTest.java",
"chars": 3212,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/CallLogReadTest.java",
"chars": 1517,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/CallLogWriteTest.java",
"chars": 1727,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/CameraTest.java",
"chars": 2029,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/ContactsReadTest.java",
"chars": 1560,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/ContactsWriteTest.java",
"chars": 4065,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/DoubleChecker.java",
"chars": 1439,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/LocationCoarseTest.java",
"chars": 1701,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/LocationFineTest.java",
"chars": 1776,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/PermissionChecker.java",
"chars": 1367,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/PermissionTest.java",
"chars": 1529,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/PhoneStateReadTest.java",
"chars": 1512,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/RecordAudioTest.java",
"chars": 3831,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/SensorActivityTest.java",
"chars": 2057,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/SensorHeartTest.java",
"chars": 2044,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/SipTest.java",
"chars": 1777,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/SmsReadTest.java",
"chars": 1546,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/StandardChecker.java",
"chars": 2290,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/StorageReadTest.java",
"chars": 1430,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/StorageWriteTest.java",
"chars": 1823,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/checker/StrictChecker.java",
"chars": 7233,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/install/BaseRequest.java",
"chars": 3099,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/install/InstallRequest.java",
"chars": 1357,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/install/NRequest.java",
"chars": 928,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/install/NRequestFactory.java",
"chars": 954,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/install/ORequest.java",
"chars": 1847,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/install/ORequestFactory.java",
"chars": 954,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/BaseRequest.java",
"chars": 2318,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/NRequest.java",
"chars": 1772,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/NRequestFactory.java",
"chars": 922,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/Notify.java",
"chars": 2340,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/ORequest.java",
"chars": 1767,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/ORequestFactory.java",
"chars": 922,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/PermissionRequest.java",
"chars": 1235,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/listener/BaseRequest.java",
"chars": 2319,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1Request.java",
"chars": 1133,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1RequestFactory.java",
"chars": 977,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2Request.java",
"chars": 1815,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2RequestFactory.java",
"chars": 977,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/listener/ListenerRequest.java",
"chars": 1236,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/notify/option/NotifyOption.java",
"chars": 1011,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/option/Option.java",
"chars": 1419,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/BaseRequest.java",
"chars": 3102,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/LRequest.java",
"chars": 1812,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/LRequestFactory.java",
"chars": 954,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/MRequest.java",
"chars": 1818,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/MRequestFactory.java",
"chars": 954,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/OverlayRequest.java",
"chars": 1225,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/setting/LSettingPage.java",
"chars": 5539,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/overlay/setting/MSettingPage.java",
"chars": 2849,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/BaseRequest.java",
"chars": 4277,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/LRequest.java",
"chars": 2432,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/LRequestFactory.java",
"chars": 924,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/MRequest.java",
"chars": 3692,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/MRequestFactory.java",
"chars": 924,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/Permission.java",
"chars": 10160,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/PermissionDef.java",
"chars": 1784,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/PermissionRequest.java",
"chars": 1699,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/Runtime.java",
"chars": 4408,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/option/RuntimeOption.java",
"chars": 1393,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/setting/AllRequest.java",
"chars": 1091,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/setting/SettingPage.java",
"chars": 5077,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/runtime/setting/SettingRequest.java",
"chars": 805,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/setting/Setting.java",
"chars": 1647,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/setting/write/BaseRequest.java",
"chars": 2305,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/setting/write/LWriteRequest.java",
"chars": 936,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/setting/write/LWriteRequestFactory.java",
"chars": 979,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/setting/write/MWriteRequest.java",
"chars": 1814,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/setting/write/MWriteRequestFactory.java",
"chars": 979,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/setting/write/WriteRequest.java",
"chars": 1220,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/source/ActivitySource.java",
"chars": 1580,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/source/ContextSource.java",
"chars": 2076,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/source/FragmentSource.java",
"chars": 1605,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/source/Source.java",
"chars": 6120,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/source/WrapperSource.java",
"chars": 1406,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/source/XFragmentSource.java",
"chars": 1628,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/task/TaskExecutor.java",
"chars": 1645,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/task/WaitDialog.java",
"chars": 1067,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/java/com/yanzhenjie/permission/util/StringUtils.java",
"chars": 1798,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "permission/src/main/res/drawable/permission_shape_wait_background.xml",
"chars": 835,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2019 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/layout/permission_dialog_wait.xml",
"chars": 1630,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/values/dimens.xml",
"chars": 1335,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/values/string.xml",
"chars": 1439,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/values/style.xml",
"chars": 2777,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2019 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/values-v21/style.xml",
"chars": 1415,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2019 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/values-zh/string.xml",
"chars": 1359,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/values-zh-RHK/string.xml",
"chars": 1359,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/values-zh-RTW/string.xml",
"chars": 1359,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "permission/src/main/res/xml/permission_file_paths.xml",
"chars": 1151,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n Copyright 2018 Zhenjie Yan\n\n Licensed under the Apache License, Versio"
},
{
"path": "sample/.gitignore",
"chars": 6,
"preview": "/build"
},
{
"path": "sample/build.gradle",
"chars": 633,
"preview": "apply plugin: rootProject.ext.plugins.application\n\nandroid {\n compileSdkVersion rootProject.ext.android.compileSdkVer"
},
{
"path": "sample/proguard-rules.pro",
"chars": 1866,
"preview": "-optimizationpasses 5\n-ignorewarnings\n-dontusemixedcaseclassnames\n-dontskipnonpubliclibraryclasses\n-dontskipnonpubliclib"
},
{
"path": "sample/src/main/AndroidManifest.xml",
"chars": 4183,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright © Zhenjie Yan\n\n Licensed under the Apache License, Version"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/App.java",
"chars": 1531,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/InstallRationale.java",
"chars": 1787,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/NotifyListenerRationale.java",
"chars": 1789,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/NotifyRationale.java",
"chars": 1772,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/OverlayRationale.java",
"chars": 1765,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/RuntimeRationale.java",
"chars": 2095,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/WriteSettingRationale.java",
"chars": 1773,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/app/MainActivity.java",
"chars": 24516,
"preview": "/*\n * Copyright © Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use t"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/app/NotifyListenerService.java",
"chars": 1184,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/util/FileUtils.java",
"chars": 2988,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/util/IOUtils.java",
"chars": 1485,
"preview": "/*\n * Copyright 2019 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/widget/AlertWindow.java",
"chars": 3729,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/java/com/yanzhenjie/permission/sample/widget/LauncherView.java",
"chars": 1902,
"preview": "/*\n * Copyright 2018 Zhenjie Yan\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": "sample/src/main/res/layout/activity_main.xml",
"chars": 5110,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright © Zhenjie Yan\n\n Licensed under the Apache License, Version"
},
{
"path": "sample/src/main/res/layout/window_launcher.xml",
"chars": 1481,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Versi"
},
{
"path": "sample/src/main/res/values/array_string.xml",
"chars": 2049,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright 2017 Zhenjie Yan\n\n Licensed under the Apache License, Vers"
},
{
"path": "sample/src/main/res/values/colors.xml",
"chars": 843,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n Copyright © Zhenjie Yan\n\n Licensed under the Apache License, Version "
},
{
"path": "sample/src/main/res/values/dimens.xml",
"chars": 1035,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n Copyright © Zhenjie Yan\n\n Licensed under the Apache License, Version "
},
{
"path": "sample/src/main/res/values/strings.xml",
"chars": 3261,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!--\n Copyright © Zhenjie Yan\n\n Licensed under the Apache License, Version"
},
{
"path": "sample/src/main/res/values/styles.xml",
"chars": 2811,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n Copyright © Zhenjie Yan\n\n Licensed under the Apache License, Version "
},
{
"path": "settings.gradle",
"chars": 32,
"preview": "include ':permission', ':sample'"
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the yanzhenjie/AndPermission GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 143 files (323.5 KB), approximately 74.3k tokens, and a symbol index with 600 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.