├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.gradle ├── config.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.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-v21 │ └── style.xml │ ├── values-zh-RHK │ └── string.xml │ ├── values-zh-RTW │ └── string.xml │ ├── values-zh │ └── string.xml │ ├── values │ ├── dimens.xml │ ├── string.xml │ └── style.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 │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── array_string.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /.idea/ 3 | /build/ 4 | .gradle 5 | /local.properties 6 | .DS_Store 7 | /captures 8 | .externalNativeBuild -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to AndPermission 2 | First off, thanks for taking the time to contribute. 3 | 4 | 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. 5 | 6 | 1. All your actions in AndPermission should be in English, not in other languages. 7 | 2. Please keep AndPermission the existing code style, not according to your habits. 8 | 3. Just modify the code you are sure need to be optimized, not all the different code from your ideas. 9 | 4. Before launching a pull request, you should test your commit code adequately. 10 | 5. Please commit new code to the [dev](https://github.com/yanzhenjie/AndPermission/tree/dev) branch instead of the master branch. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndPermission 2 | 1. Request for runtime permissions. 3 | 2. Share private files. 4 | 3. Request to install unknown source apk. 5 | `android.permission.REQUEST_INSTALL_PACKAGES` 6 | 4. Request to draw at the top of other apps. 7 | `android.permission.SYSTEM_ALERT_WINDOW` 8 | 5. Request to show notifications. 9 | 6. Request to access notifications. 10 | `android.permission.BIND_NOTIFICATION_LISTENER_SERVICE` 11 | 7. Request to modify system setting. 12 | `android.permission.WRITE_SETTINGS` 13 | 14 | ```java 15 | AndPermission.with(this) 16 | .runtime() 17 | .permission(Permission.Group.STORAGE) 18 | .onGranted(permissions -> { 19 | // Storage permission are allowed. 20 | }) 21 | .onDenied(permissions -> { 22 | // Storage permission are not allowed. 23 | }) 24 | .start(); 25 | ``` 26 | 27 | For documentation and additional information see [the website](https://yanzhenjie.com/AndPermission). 28 | 29 | ## Download 30 | It only supports androidx, add dependencies in your gradle: 31 | 32 | ```groovy 33 | implementation 'com.yanzhenjie:permission:2.0.3' 34 | ``` 35 | 36 | AndPermission requires at minimum Android 4.0(Api level 14) . 37 | 38 | ## Contributing 39 | Before submitting pull requests, contributors must abide by the [agreement](CONTRIBUTING.md) . 40 | 41 | ## License 42 | ```text 43 | Copyright 2019 Zhenjie Yan 44 | 45 | Licensed under the Apache License, Version 2.0 (the "License"); 46 | you may not use this file except in compliance with the License. 47 | You may obtain a copy of the License at 48 | 49 | http://www.apache.org/licenses/LICENSE-2.0 50 | 51 | Unless required by applicable law or agreed to in writing, software 52 | distributed under the License is distributed on an "AS IS" BASIS, 53 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 54 | See the License for the specific language governing permissions and 55 | limitations under the License. 56 | ``` -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "config.gradle" 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter {url 'https://maven.aliyun.com/repository/jcenter'} 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.5.1' 11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' 12 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | google() 19 | jcenter {url 'https://maven.aliyun.com/repository/jcenter'} 20 | jcenter() 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } -------------------------------------------------------------------------------- /config.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | plugins = [application: 'com.android.application', 3 | library : 'com.android.library', 4 | maven : 'com.github.dcendents.android-maven', 5 | bintray : 'com.jfrog.bintray'] 6 | 7 | android = [applicationId : "com.yanzhenjie.permission.sample", 8 | compileSdkVersion: 29, 9 | buildToolsVersion: "29.0.2", 10 | minSdkVersion : 14, 11 | targetSdkVersion : 29, 12 | versionCode : 108, 13 | versionName : "2.0.3"] 14 | 15 | bintray = [version : "2.0.3", 16 | 17 | siteUrl : 'https://github.com/yanzhenjie/AndPermission', 18 | gitUrl : 'https://github.com/yanzhenjie/AndPermission.git', 19 | 20 | group : "com.yanzhenjie", 21 | 22 | packaging : 'aar', 23 | name : 'Permission', 24 | description : 'Permission manager for Android', 25 | 26 | licenseName : 'The Apache Software License, Version 2.0', 27 | licenseUrl : 'http://www.apache.org/licenses/LICENSE-2.0.txt', 28 | 29 | developerId : 'yanzhenjie', 30 | developerName : 'yanzhenjie', 31 | developerEmail: 'im.yanzhenjie@gmail.com', 32 | 33 | binrayLibrary : "permission", 34 | bintrayRepo : "maven", 35 | bintrayUser : 'yolanda', 36 | bintrayLicense: "Apache-2.0"] 37 | 38 | dependencies = [ 39 | fragment: 'androidx.appcompat:appcompat:1.1.0' 40 | ] 41 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanzhenjie/AndPermission/00bedd6a3a939ce6dab22885723699025c63377b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /permission/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /permission/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: rootProject.ext.plugins.library 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.android.compileSdkVersion 5 | buildToolsVersion rootProject.ext.android.buildToolsVersion 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.android.minSdkVersion 9 | targetSdkVersion rootProject.ext.android.targetSdkVersion 10 | } 11 | 12 | resourcePrefix 'permission' 13 | } 14 | 15 | dependencies { 16 | api rootProject.ext.dependencies.fragment 17 | } -------------------------------------------------------------------------------- /permission/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 21 | 25 | 26 | 27 | 28 | 29 | 34 | 35 | 36 | 37 | 38 | 39 | 46 | 47 | 52 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /permission/src/main/aidl/com/yanzhenjie/permission/bridge/IBridge.aidl: -------------------------------------------------------------------------------- 1 | package com.yanzhenjie.permission.bridge; 2 | 3 | interface IBridge { 4 | /** 5 | * Request for permissions. 6 | */ 7 | void requestAppDetails(in String suffix); 8 | 9 | /** 10 | * Request for permissions. 11 | */ 12 | void requestPermission(in String suffix, in String[] permissions); 13 | 14 | /** 15 | * Request for package install. 16 | */ 17 | void requestInstall(in String suffix); 18 | 19 | /** 20 | * Request for overlay. 21 | */ 22 | void requestOverlay(in String suffix); 23 | 24 | /** 25 | * Request for alert window. 26 | */ 27 | void requestAlertWindow(in String suffix); 28 | 29 | /** 30 | * Request for notify. 31 | */ 32 | void requestNotify(in String suffix); 33 | 34 | /** 35 | * Request for notification listener. 36 | */ 37 | void requestNotificationListener(in String suffix); 38 | 39 | /** 40 | * Request for write system setting. 41 | */ 42 | void requestWriteSetting(in String suffix); 43 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/Action.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission; 17 | 18 | /** 19 | * Created by Zhenjie Yan on 2018/1/1. 20 | */ 21 | public interface Action { 22 | 23 | /** 24 | * An action. 25 | * 26 | * @param data the data. 27 | */ 28 | void onAction(T data); 29 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/Boot.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission; 17 | 18 | import android.os.Build; 19 | 20 | import com.yanzhenjie.permission.install.InstallRequest; 21 | import com.yanzhenjie.permission.install.NRequestFactory; 22 | import com.yanzhenjie.permission.install.ORequestFactory; 23 | import com.yanzhenjie.permission.notify.Notify; 24 | import com.yanzhenjie.permission.notify.option.NotifyOption; 25 | import com.yanzhenjie.permission.option.Option; 26 | import com.yanzhenjie.permission.overlay.LRequestFactory; 27 | import com.yanzhenjie.permission.overlay.MRequestFactory; 28 | import com.yanzhenjie.permission.overlay.OverlayRequest; 29 | import com.yanzhenjie.permission.runtime.Runtime; 30 | import com.yanzhenjie.permission.runtime.option.RuntimeOption; 31 | import com.yanzhenjie.permission.setting.Setting; 32 | import com.yanzhenjie.permission.source.Source; 33 | 34 | /** 35 | * Created by Zhenjie Yan on 2018/4/28. 36 | */ 37 | public class Boot implements Option { 38 | 39 | private static final InstallRequestFactory INSTALL_REQUEST_FACTORY; 40 | private static final OverlayRequestFactory OVERLAY_REQUEST_FACTORY; 41 | 42 | static { 43 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 44 | INSTALL_REQUEST_FACTORY = new ORequestFactory(); 45 | } else { 46 | INSTALL_REQUEST_FACTORY = new NRequestFactory(); 47 | } 48 | 49 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 50 | OVERLAY_REQUEST_FACTORY = new MRequestFactory(); 51 | } else { 52 | OVERLAY_REQUEST_FACTORY = new LRequestFactory(); 53 | } 54 | } 55 | 56 | public interface InstallRequestFactory { 57 | 58 | /** 59 | * Create apk installer request. 60 | */ 61 | InstallRequest create(Source source); 62 | } 63 | 64 | public interface OverlayRequestFactory { 65 | 66 | /** 67 | * Create overlay request. 68 | */ 69 | OverlayRequest create(Source source); 70 | } 71 | 72 | private Source mSource; 73 | 74 | public Boot(Source source) { 75 | this.mSource = source; 76 | } 77 | 78 | @Override 79 | public RuntimeOption runtime() { 80 | return new Runtime(mSource); 81 | } 82 | 83 | @Override 84 | public InstallRequest install() { 85 | return INSTALL_REQUEST_FACTORY.create(mSource); 86 | } 87 | 88 | @Override 89 | public OverlayRequest overlay() { 90 | return OVERLAY_REQUEST_FACTORY.create(mSource); 91 | } 92 | 93 | @Override 94 | public NotifyOption notification() { 95 | return new Notify(mSource); 96 | } 97 | 98 | @Override 99 | public Setting setting() { 100 | return new Setting(mSource); 101 | } 102 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/Rationale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission; 17 | 18 | import android.content.Context; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 2016/9/10. 22 | */ 23 | public interface Rationale { 24 | 25 | /** 26 | * Show rationale to user. 27 | * 28 | * @param context context. 29 | * @param data the data. 30 | * @param executor executor. 31 | */ 32 | void showRationale(Context context, T data, RequestExecutor executor); 33 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/RequestExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission; 17 | 18 | /** 19 | *

Request executor.

20 | * Created by Zhenjie Yan on 2016/9/10. 21 | */ 22 | public interface RequestExecutor { 23 | 24 | /** 25 | * Go request permission. 26 | */ 27 | void execute(); 28 | 29 | /** 30 | * Cancel the operation. 31 | */ 32 | void cancel(); 33 | 34 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.bridge; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Created by Zhenjie Yan on 2/13/19. 24 | */ 25 | public final class BridgeRequest { 26 | 27 | public static final int TYPE_APP_DETAILS = 1; 28 | public static final int TYPE_PERMISSION = 2; 29 | public static final int TYPE_INSTALL = 3; 30 | public static final int TYPE_OVERLAY = 4; 31 | public static final int TYPE_ALERT_WINDOW = 5; 32 | public static final int TYPE_NOTIFY = 6; 33 | public static final int TYPE_NOTIFY_LISTENER = 7; 34 | public static final int TYPE_WRITE_SETTING = 8; 35 | 36 | private final Source mSource; 37 | 38 | private int mType; 39 | private Callback mCallback; 40 | private List mPermissions; 41 | 42 | public BridgeRequest(Source source) { 43 | this.mSource = source; 44 | } 45 | 46 | public Source getSource() { 47 | return mSource; 48 | } 49 | 50 | public int getType() { 51 | return mType; 52 | } 53 | 54 | public void setType(int type) { 55 | mType = type; 56 | } 57 | 58 | public Callback getCallback() { 59 | return mCallback; 60 | } 61 | 62 | public void setCallback(Callback callback) { 63 | mCallback = callback; 64 | } 65 | 66 | public List getPermissions() { 67 | return mPermissions; 68 | } 69 | 70 | public void setPermissions(List permissions) { 71 | mPermissions = permissions; 72 | } 73 | 74 | public interface Callback { 75 | 76 | void onCallback(); 77 | } 78 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/bridge/BridgeService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.bridge; 17 | 18 | import android.app.Service; 19 | import android.content.Intent; 20 | import android.os.IBinder; 21 | import android.os.RemoteException; 22 | 23 | import androidx.annotation.Nullable; 24 | 25 | import com.yanzhenjie.permission.source.ContextSource; 26 | import com.yanzhenjie.permission.source.Source; 27 | 28 | /** 29 | * Created by Zhenjie Yan on 2019-08-30. 30 | */ 31 | public class BridgeService extends Service { 32 | 33 | @Nullable 34 | @Override 35 | public IBinder onBind(Intent intent) { 36 | return mStub.asBinder(); 37 | } 38 | 39 | private IBridge.Stub mStub = new IBridge.Stub() { 40 | 41 | private Source mSource = new ContextSource(BridgeService.this); 42 | 43 | @Override 44 | public void requestAppDetails(String suffix) throws RemoteException { 45 | BridgeActivity.requestAppDetails(mSource, suffix); 46 | } 47 | 48 | @Override 49 | public void requestPermission(String suffix, String[] permissions) throws RemoteException { 50 | BridgeActivity.requestPermission(mSource, suffix, permissions); 51 | } 52 | 53 | @Override 54 | public void requestInstall(String suffix) throws RemoteException { 55 | BridgeActivity.requestInstall(mSource, suffix); 56 | } 57 | 58 | @Override 59 | public void requestOverlay(String suffix) throws RemoteException { 60 | BridgeActivity.requestOverlay(mSource, suffix); 61 | } 62 | 63 | @Override 64 | public void requestAlertWindow(String suffix) throws RemoteException { 65 | BridgeActivity.requestAlertWindow(mSource, suffix); 66 | } 67 | 68 | @Override 69 | public void requestNotify(String suffix) throws RemoteException { 70 | BridgeActivity.requestNotify(mSource, suffix); 71 | } 72 | 73 | @Override 74 | public void requestNotificationListener(String suffix) throws RemoteException { 75 | BridgeActivity.requestNotificationListener(mSource, suffix); 76 | } 77 | 78 | @Override 79 | public void requestWriteSetting(String suffix) throws RemoteException { 80 | BridgeActivity.requestWriteSetting(mSource, suffix); 81 | } 82 | }; 83 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/bridge/Messenger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2018 Zhenjie Yan. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.bridge; 17 | 18 | import android.content.BroadcastReceiver; 19 | import android.content.Context; 20 | import android.content.Intent; 21 | import android.content.IntentFilter; 22 | 23 | import com.yanzhenjie.permission.AndPermission; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/6/9. 27 | */ 28 | class Messenger extends BroadcastReceiver { 29 | 30 | public static void send(Context context, String suffix) { 31 | Intent broadcast = new Intent(AndPermission.bridgeAction(context, suffix)); 32 | context.sendBroadcast(broadcast); 33 | } 34 | 35 | private final Context mContext; 36 | private final Callback mCallback; 37 | 38 | public Messenger(Context context, Callback callback) { 39 | this.mContext = context; 40 | this.mCallback = callback; 41 | } 42 | 43 | public void register(String suffix) { 44 | IntentFilter filter = new IntentFilter(AndPermission.bridgeAction(mContext, suffix)); 45 | mContext.registerReceiver(this, filter); 46 | } 47 | 48 | public void unRegister() { 49 | mContext.unregisterReceiver(this); 50 | } 51 | 52 | @Override 53 | public void onReceive(Context context, Intent intent) { 54 | mCallback.onCallback(); 55 | } 56 | 57 | public interface Callback { 58 | 59 | void onCallback(); 60 | } 61 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/bridge/RequestManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.bridge; 17 | 18 | import java.util.concurrent.Executor; 19 | import java.util.concurrent.Executors; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2/13/19. 23 | */ 24 | public class RequestManager { 25 | 26 | private static RequestManager sManager; 27 | 28 | public static RequestManager get() { 29 | if (sManager == null) { 30 | synchronized (RequestManager.class) { 31 | if (sManager == null) { 32 | sManager = new RequestManager(); 33 | } 34 | } 35 | } 36 | return sManager; 37 | } 38 | 39 | private final Executor mExecutor; 40 | 41 | private RequestManager() { 42 | this.mExecutor = Executors.newCachedThreadPool(); 43 | } 44 | 45 | public void add(BridgeRequest request) { 46 | mExecutor.execute(new RequestExecutor(request)); 47 | } 48 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/CalendarReadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.ContentResolver; 19 | import android.content.Context; 20 | import android.database.Cursor; 21 | import android.provider.CalendarContract; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/1/25. 25 | */ 26 | class CalendarReadTest implements PermissionTest { 27 | 28 | private ContentResolver mResolver; 29 | 30 | CalendarReadTest(Context context) { 31 | mResolver = context.getContentResolver(); 32 | } 33 | 34 | @Override 35 | public boolean test() throws Throwable { 36 | String[] projection = new String[] {CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME}; 37 | Cursor cursor = mResolver.query(CalendarContract.Calendars.CONTENT_URI, projection, null, null, null); 38 | if (cursor != null) { 39 | try { 40 | CursorTest.read(cursor); 41 | } finally { 42 | cursor.close(); 43 | } 44 | return true; 45 | } else { 46 | return false; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/CalendarWriteTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.ContentResolver; 19 | import android.content.ContentUris; 20 | import android.content.ContentValues; 21 | import android.content.Context; 22 | import android.graphics.Color; 23 | import android.net.Uri; 24 | import android.provider.CalendarContract; 25 | 26 | import com.yanzhenjie.permission.util.StringUtils; 27 | 28 | import java.util.TimeZone; 29 | 30 | /** 31 | * Created by Zhenjie Yan on 2018/1/15. 32 | */ 33 | class CalendarWriteTest implements PermissionTest { 34 | 35 | private static final String NAME = StringUtils.hexToText("5045524D495353494F4E"); 36 | private static final String ACCOUNT = StringUtils.hexToText("7065726D697373696F6E40676D61696C2E636F6D"); 37 | 38 | private ContentResolver mResolver; 39 | 40 | CalendarWriteTest(Context context) { 41 | this.mResolver = context.getContentResolver(); 42 | } 43 | 44 | @Override 45 | public boolean test() throws Throwable { 46 | try { 47 | TimeZone timeZone = TimeZone.getDefault(); 48 | ContentValues value = new ContentValues(); 49 | value.put(CalendarContract.Calendars.NAME, NAME); 50 | value.put(CalendarContract.Calendars.ACCOUNT_NAME, ACCOUNT); 51 | value.put(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL); 52 | value.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, NAME); 53 | value.put(CalendarContract.Calendars.VISIBLE, 1); 54 | value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE); 55 | value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER); 56 | value.put(CalendarContract.Calendars.SYNC_EVENTS, 1); 57 | value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.getID()); 58 | value.put(CalendarContract.Calendars.OWNER_ACCOUNT, NAME); 59 | value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0); 60 | 61 | Uri insertUri = CalendarContract.Calendars.CONTENT_URI.buildUpon() 62 | .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true") 63 | .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, NAME) 64 | .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL) 65 | .build(); 66 | Uri resourceUri = mResolver.insert(insertUri, value); 67 | return ContentUris.parseId(resourceUri) > 0; 68 | } finally { 69 | Uri deleteUri = CalendarContract.Calendars.CONTENT_URI.buildUpon().build(); 70 | mResolver.delete(deleteUri, CalendarContract.Calendars.ACCOUNT_NAME + "=?", new String[]{ACCOUNT}); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/CallLogReadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.ContentResolver; 19 | import android.content.Context; 20 | import android.database.Cursor; 21 | import android.provider.CallLog; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/1/25. 25 | */ 26 | class CallLogReadTest implements PermissionTest { 27 | 28 | private ContentResolver mResolver; 29 | 30 | CallLogReadTest(Context context) { 31 | mResolver = context.getContentResolver(); 32 | } 33 | 34 | @Override 35 | public boolean test() throws Throwable { 36 | String[] projection = new String[] {CallLog.Calls._ID, CallLog.Calls.NUMBER, CallLog.Calls.TYPE}; 37 | Cursor cursor = mResolver.query(CallLog.Calls.CONTENT_URI, projection, null, null, null); 38 | if (cursor != null) { 39 | try { 40 | CursorTest.read(cursor); 41 | } finally { 42 | cursor.close(); 43 | } 44 | return true; 45 | } else { 46 | return false; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/CallLogWriteTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.ContentResolver; 19 | import android.content.ContentUris; 20 | import android.content.ContentValues; 21 | import android.content.Context; 22 | import android.net.Uri; 23 | import android.provider.CallLog; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/1/14. 27 | */ 28 | class CallLogWriteTest implements PermissionTest { 29 | 30 | private ContentResolver mResolver; 31 | 32 | CallLogWriteTest(Context context) { 33 | this.mResolver = context.getContentResolver(); 34 | } 35 | 36 | @Override 37 | public boolean test() throws Throwable { 38 | try { 39 | ContentValues content = new ContentValues(); 40 | content.put(CallLog.Calls.TYPE, CallLog.Calls.INCOMING_TYPE); 41 | content.put(CallLog.Calls.NUMBER, "1"); 42 | content.put(CallLog.Calls.DATE, 20080808); 43 | content.put(CallLog.Calls.NEW, "0"); 44 | Uri resourceUri = mResolver.insert(CallLog.Calls.CONTENT_URI, content); 45 | return ContentUris.parseId(resourceUri) > 0; 46 | } finally { 47 | mResolver.delete(CallLog.Calls.CONTENT_URI, CallLog.Calls.NUMBER + "=?", new String[] {"1"}); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/CameraTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.content.pm.PackageManager; 20 | import android.hardware.Camera; 21 | 22 | /** 23 | * Created by Zhenjie Yan on 2018/1/15. 24 | */ 25 | class CameraTest implements PermissionTest { 26 | 27 | private Context mContext; 28 | 29 | CameraTest(Context context) { 30 | this.mContext = context; 31 | } 32 | 33 | @Override 34 | public boolean test() throws Throwable { 35 | Camera camera = null; 36 | try { 37 | int cameraCount = Camera.getNumberOfCameras(); 38 | if (cameraCount <= 0) return true; 39 | 40 | camera = Camera.open(cameraCount - 1); 41 | Camera.Parameters parameters = camera.getParameters(); 42 | camera.setParameters(parameters); 43 | camera.setPreviewCallback(PREVIEW_CALLBACK); 44 | camera.startPreview(); 45 | return true; 46 | } catch (Throwable e) { 47 | PackageManager packageManager = mContext.getPackageManager(); 48 | return !packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA); 49 | } finally { 50 | if (camera != null) { 51 | camera.stopPreview(); 52 | camera.setPreviewCallback(null); 53 | camera.release(); 54 | } 55 | } 56 | } 57 | 58 | private static final Camera.PreviewCallback PREVIEW_CALLBACK = new Camera.PreviewCallback() { 59 | @Override 60 | public void onPreviewFrame(byte[] data, Camera camera) { 61 | } 62 | }; 63 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/ContactsReadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.ContentResolver; 19 | import android.content.Context; 20 | import android.database.Cursor; 21 | import android.provider.ContactsContract; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/1/25. 25 | */ 26 | class ContactsReadTest implements PermissionTest { 27 | 28 | private ContentResolver mResolver; 29 | 30 | ContactsReadTest(Context context) { 31 | mResolver = context.getContentResolver(); 32 | } 33 | 34 | @Override 35 | public boolean test() throws Throwable { 36 | String[] projection = new String[] {ContactsContract.Data._ID, ContactsContract.Data.DATA1}; 37 | Cursor cursor = mResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null, 38 | null); 39 | if (cursor != null) { 40 | try { 41 | CursorTest.read(cursor); 42 | } finally { 43 | cursor.close(); 44 | } 45 | return true; 46 | } else { 47 | return false; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/DoubleChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Created by Zhenjie Yan on 2018/1/27. 24 | */ 25 | public final class DoubleChecker implements PermissionChecker { 26 | 27 | private static final PermissionChecker STANDARD_CHECKER = new StandardChecker(); 28 | private static final PermissionChecker STRICT_CHECKER = new StrictChecker(); 29 | 30 | @Override 31 | public boolean hasPermission(Context context, String... permissions) { 32 | return STRICT_CHECKER.hasPermission(context, permissions) && 33 | STANDARD_CHECKER.hasPermission(context, permissions); 34 | } 35 | 36 | @Override 37 | public boolean hasPermission(Context context, List permissions) { 38 | return STRICT_CHECKER.hasPermission(context, permissions) && 39 | STANDARD_CHECKER.hasPermission(context, permissions); 40 | } 41 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/LocationCoarseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.content.pm.PackageManager; 20 | import android.location.LocationManager; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * Created by Zhenjie Yan on 2018/1/14. 26 | */ 27 | class LocationCoarseTest implements PermissionTest { 28 | 29 | private Context mContext; 30 | 31 | LocationCoarseTest(Context context) { 32 | this.mContext = context; 33 | } 34 | 35 | @Override 36 | public boolean test() throws Throwable { 37 | LocationManager locationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE); 38 | List providers = locationManager.getProviders(true); 39 | boolean networkProvider = providers.contains(LocationManager.NETWORK_PROVIDER); 40 | if (networkProvider) { 41 | return true; 42 | } 43 | 44 | PackageManager packageManager = mContext.getPackageManager(); 45 | boolean networkHardware = packageManager.hasSystemFeature(PackageManager.FEATURE_LOCATION_NETWORK); 46 | if (!networkHardware) return true; 47 | 48 | return !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 49 | } 50 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/LocationFineTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.content.pm.PackageManager; 20 | import android.location.LocationManager; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * Created by Zhenjie Yan on 2018/1/14. 26 | */ 27 | class LocationFineTest implements PermissionTest { 28 | 29 | private Context mContext; 30 | 31 | LocationFineTest(Context context) { 32 | this.mContext = context; 33 | } 34 | 35 | @Override 36 | public boolean test() throws Throwable { 37 | LocationManager locationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE); 38 | List providers = locationManager.getProviders(true); 39 | boolean gpsProvider = providers.contains(LocationManager.GPS_PROVIDER); 40 | boolean passiveProvider = providers.contains(LocationManager.PASSIVE_PROVIDER); 41 | if (gpsProvider || passiveProvider) { 42 | return true; 43 | } 44 | 45 | PackageManager packageManager = mContext.getPackageManager(); 46 | boolean gpsHardware = packageManager.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS); 47 | if (!gpsHardware) return true; 48 | 49 | return !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 50 | } 51 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/PermissionChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Created by Zhenjie Yan on 2018/1/7. 24 | */ 25 | public interface PermissionChecker { 26 | 27 | /** 28 | * Check if the calling context has a set of permissions. 29 | * 30 | * @param context {@link Context}. 31 | * @param permissions one or more permissions. 32 | * 33 | * @return true, other wise is false. 34 | */ 35 | boolean hasPermission(Context context, String... permissions); 36 | 37 | /** 38 | * Check if the calling context has a set of permissions. 39 | * 40 | * @param context {@link Context}. 41 | * @param permissions one or more permissions. 42 | * 43 | * @return true, other wise is false. 44 | */ 45 | boolean hasPermission(Context context, List permissions); 46 | 47 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/PermissionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.database.Cursor; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 2018/1/14. 22 | */ 23 | interface PermissionTest { 24 | 25 | boolean test() throws Throwable; 26 | 27 | class CursorTest { 28 | 29 | public static void read(Cursor cursor) { 30 | int count = cursor.getCount(); 31 | if (count > 0) { 32 | cursor.moveToFirst(); 33 | int type = cursor.getType(0); 34 | switch (type) { 35 | case Cursor.FIELD_TYPE_BLOB: 36 | case Cursor.FIELD_TYPE_NULL: { 37 | break; 38 | } 39 | case Cursor.FIELD_TYPE_INTEGER: 40 | case Cursor.FIELD_TYPE_FLOAT: 41 | case Cursor.FIELD_TYPE_STRING: 42 | default: { 43 | cursor.getString(0); 44 | break; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/PhoneStateReadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.content.pm.PackageManager; 20 | import android.os.Build; 21 | import android.telephony.TelephonyManager; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/1/25. 25 | */ 26 | class PhoneStateReadTest implements PermissionTest { 27 | 28 | private Context mContext; 29 | 30 | PhoneStateReadTest(Context context) { 31 | this.mContext = context; 32 | } 33 | 34 | @Override 35 | public boolean test() throws Throwable { 36 | PackageManager packageManager = mContext.getPackageManager(); 37 | if (!packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) return true; 38 | 39 | TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 40 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) telephonyManager.getDeviceId(); 41 | else telephonyManager.getDeviceSoftwareVersion(); 42 | return true; 43 | } 44 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/SensorActivityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.content.pm.PackageManager; 20 | import android.hardware.Sensor; 21 | import android.hardware.SensorEvent; 22 | import android.hardware.SensorEventListener; 23 | import android.hardware.SensorManager; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/1/25. 27 | */ 28 | class SensorActivityTest implements PermissionTest { 29 | 30 | private Context mContext; 31 | 32 | SensorActivityTest(Context context) { 33 | this.mContext = context; 34 | } 35 | 36 | @Override 37 | public boolean test() throws Throwable { 38 | SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); 39 | try { 40 | Sensor heartRateSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR); 41 | sensorManager.registerListener(SENSOR_EVENT_LISTENER, heartRateSensor, 3); 42 | sensorManager.unregisterListener(SENSOR_EVENT_LISTENER, heartRateSensor); 43 | } catch (Throwable e) { 44 | PackageManager packageManager = mContext.getPackageManager(); 45 | return !packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR); 46 | } 47 | return true; 48 | } 49 | 50 | private static final SensorEventListener SENSOR_EVENT_LISTENER = new SensorEventListener() { 51 | @Override 52 | public void onSensorChanged(SensorEvent event) { 53 | } 54 | 55 | @Override 56 | public void onAccuracyChanged(Sensor sensor, int accuracy) { 57 | } 58 | }; 59 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/SensorHeartTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.content.pm.PackageManager; 20 | import android.hardware.Sensor; 21 | import android.hardware.SensorEvent; 22 | import android.hardware.SensorEventListener; 23 | import android.hardware.SensorManager; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/1/25. 27 | */ 28 | class SensorHeartTest implements PermissionTest { 29 | 30 | private Context mContext; 31 | 32 | SensorHeartTest(Context context) { 33 | this.mContext = context; 34 | } 35 | 36 | @Override 37 | public boolean test() throws Throwable { 38 | SensorManager sensorManager = (SensorManager)mContext.getSystemService(Context.SENSOR_SERVICE); 39 | try { 40 | Sensor heartRateSensor = sensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE); 41 | sensorManager.registerListener(SENSOR_EVENT_LISTENER, heartRateSensor, 3); 42 | sensorManager.unregisterListener(SENSOR_EVENT_LISTENER, heartRateSensor); 43 | } catch (Throwable e) { 44 | PackageManager packageManager = mContext.getPackageManager(); 45 | return !packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE); 46 | } 47 | return true; 48 | } 49 | 50 | private static final SensorEventListener SENSOR_EVENT_LISTENER = new SensorEventListener() { 51 | @Override 52 | public void onSensorChanged(SensorEvent event) { 53 | } 54 | 55 | @Override 56 | public void onAccuracyChanged(Sensor sensor, int accuracy) { 57 | } 58 | }; 59 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/SipTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.net.sip.SipManager; 20 | import android.net.sip.SipProfile; 21 | 22 | import com.yanzhenjie.permission.util.StringUtils; 23 | 24 | /** 25 | * Created by Zhenjie Yan on 2018/1/25. 26 | */ 27 | class SipTest implements PermissionTest { 28 | 29 | private static final String USER = StringUtils.hexToText("5065726D697373696F6E"); 30 | private static final String IP = StringUtils.hexToText("3132372E302E302E31"); 31 | private static final String PASSWORD = StringUtils.textToHex("70617373776F7264"); 32 | 33 | private Context mContext; 34 | 35 | SipTest(Context context) { 36 | this.mContext = context; 37 | } 38 | 39 | @Override 40 | public boolean test() throws Throwable { 41 | if (!SipManager.isApiSupported(mContext)) { 42 | return true; 43 | } 44 | SipManager manager = SipManager.newInstance(mContext); 45 | if (manager == null) { 46 | return true; 47 | } 48 | SipProfile.Builder builder = new SipProfile.Builder(USER, IP); 49 | builder.setPassword(PASSWORD); 50 | SipProfile profile = builder.build(); 51 | manager.open(profile); 52 | manager.close(profile.getUriString()); 53 | return true; 54 | } 55 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/SmsReadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.ContentResolver; 19 | import android.content.Context; 20 | import android.database.Cursor; 21 | import android.provider.Telephony; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/1/25. 25 | */ 26 | class SmsReadTest implements PermissionTest { 27 | 28 | private ContentResolver mResolver; 29 | 30 | SmsReadTest(Context context) { 31 | mResolver = context.getContentResolver(); 32 | } 33 | 34 | @Override 35 | public boolean test() throws Throwable { 36 | String[] projection = new String[] {Telephony.Sms._ID, Telephony.Sms.ADDRESS, Telephony.Sms.PERSON, 37 | Telephony.Sms.BODY}; 38 | Cursor cursor = mResolver.query(Telephony.Sms.CONTENT_URI, projection, null, null, null); 39 | if (cursor != null) { 40 | try { 41 | CursorTest.read(cursor); 42 | } finally { 43 | cursor.close(); 44 | } 45 | return true; 46 | } else { 47 | return false; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/StandardChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.app.AppOpsManager; 19 | import android.content.Context; 20 | import android.content.pm.PackageManager; 21 | import android.os.Build; 22 | import android.text.TextUtils; 23 | 24 | import java.util.Arrays; 25 | import java.util.List; 26 | 27 | /** 28 | * Created by Zhenjie Yan on 2018/1/7. 29 | */ 30 | public final class StandardChecker implements PermissionChecker { 31 | 32 | private static final int MODE_ASK = 4; 33 | private static final int MODE_COMPAT = 5; 34 | 35 | public StandardChecker() { 36 | } 37 | 38 | @Override 39 | public boolean hasPermission(Context context, String... permissions) { 40 | return hasPermission(context, Arrays.asList(permissions)); 41 | } 42 | 43 | @Override 44 | public boolean hasPermission(Context context, List permissions) { 45 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true; 46 | 47 | AppOpsManager opsManager = null; 48 | for (String permission : permissions) { 49 | int result = context.checkPermission(permission, android.os.Process.myPid(), android.os.Process.myUid()); 50 | if (result == PackageManager.PERMISSION_DENIED) { 51 | return false; 52 | } 53 | 54 | String op = AppOpsManager.permissionToOp(permission); 55 | if (TextUtils.isEmpty(op)) { 56 | continue; 57 | } 58 | 59 | if (opsManager == null) opsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 60 | result = opsManager.checkOpNoThrow(op, android.os.Process.myUid(), context.getPackageName()); 61 | if (result != AppOpsManager.MODE_ALLOWED && result != MODE_ASK && result != MODE_COMPAT) { 62 | return false; 63 | } 64 | } 65 | return true; 66 | } 67 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/StorageReadTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.os.Build; 19 | import android.os.Environment; 20 | import android.text.TextUtils; 21 | 22 | import java.io.File; 23 | 24 | /** 25 | * Created by Zhenjie Yan on 2018/1/16. 26 | */ 27 | class StorageReadTest implements PermissionTest { 28 | 29 | StorageReadTest() { 30 | } 31 | 32 | @Override 33 | public boolean test() throws Throwable { 34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !Environment.isExternalStorageLegacy()) return true; 35 | 36 | if (!TextUtils.equals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState())) return true; 37 | 38 | File directory = Environment.getExternalStorageDirectory(); 39 | if (!directory.exists()) return true; 40 | 41 | long modified = directory.lastModified(); 42 | String[] pathList = directory.list(); 43 | return modified > 0 && pathList != null; 44 | } 45 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/checker/StorageWriteTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.checker; 17 | 18 | import android.content.Context; 19 | import android.os.Build; 20 | import android.os.Environment; 21 | import android.text.TextUtils; 22 | 23 | import java.io.File; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/1/16. 27 | */ 28 | class StorageWriteTest implements PermissionTest { 29 | 30 | private Context mContext; 31 | 32 | StorageWriteTest(Context c) { 33 | mContext = c; 34 | } 35 | 36 | @Override 37 | public boolean test() throws Throwable { 38 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !Environment.isExternalStorageLegacy()) return true; 39 | 40 | if (!TextUtils.equals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState())) return true; 41 | 42 | File directory = mContext.getExternalFilesDir(null); 43 | 44 | if (!directory.exists()) return true; 45 | 46 | File parent = new File(directory, "Android"); 47 | if (parent.exists() && parent.isFile()) { 48 | if (!parent.delete()) return false; 49 | } 50 | if (!parent.exists()) { 51 | if (!parent.mkdirs()) return false; 52 | } 53 | File file = new File(parent, "ANDROID.PERMISSION.TEST"); 54 | if (file.exists()) { 55 | return file.delete(); 56 | } else { 57 | return file.createNewFile(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/install/BaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.install; 17 | 18 | import android.content.Context; 19 | import android.content.Intent; 20 | import android.net.Uri; 21 | 22 | import com.yanzhenjie.permission.Action; 23 | import com.yanzhenjie.permission.AndPermission; 24 | import com.yanzhenjie.permission.Rationale; 25 | import com.yanzhenjie.permission.RequestExecutor; 26 | import com.yanzhenjie.permission.source.Source; 27 | 28 | import java.io.File; 29 | 30 | /** 31 | * Created by Zhenjie Yan on 2018/6/1. 32 | */ 33 | abstract class BaseRequest implements InstallRequest { 34 | 35 | private Source mSource; 36 | 37 | private File mFile; 38 | private Rationale mRationale = new Rationale() { 39 | @Override 40 | public void showRationale(Context context, File data, RequestExecutor executor) { 41 | executor.execute(); 42 | } 43 | }; 44 | private Action mGranted; 45 | private Action mDenied; 46 | 47 | BaseRequest(Source source) { 48 | this.mSource = source; 49 | } 50 | 51 | @Override 52 | public final InstallRequest file(File file) { 53 | this.mFile = file; 54 | return this; 55 | } 56 | 57 | @Override 58 | public final InstallRequest rationale(Rationale rationale) { 59 | this.mRationale = rationale; 60 | return this; 61 | } 62 | 63 | @Override 64 | public final InstallRequest onGranted(Action granted) { 65 | this.mGranted = granted; 66 | return this; 67 | } 68 | 69 | @Override 70 | public final InstallRequest onDenied(Action denied) { 71 | this.mDenied = denied; 72 | return this; 73 | } 74 | 75 | /** 76 | * Why permissions are required. 77 | */ 78 | final void showRationale(RequestExecutor executor) { 79 | mRationale.showRationale(mSource.getContext(), null, executor); 80 | } 81 | 82 | /** 83 | * Start the installation. 84 | */ 85 | final void install() { 86 | if (mFile != null) { 87 | Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); 88 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 89 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 90 | Uri uri = AndPermission.getFileUri(mSource.getContext(), mFile); 91 | intent.setDataAndType(uri, "application/vnd.android.package-archive"); 92 | mSource.startActivity(intent); 93 | } 94 | } 95 | 96 | /** 97 | * Callback acceptance status. 98 | */ 99 | final void callbackSucceed() { 100 | if (mGranted != null) { 101 | mGranted.onAction(mFile); 102 | } 103 | } 104 | 105 | /** 106 | * Callback rejected state. 107 | */ 108 | final void callbackFailed() { 109 | if (mDenied != null) { 110 | mDenied.onAction(mFile); 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/install/InstallRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.install; 17 | 18 | import com.yanzhenjie.permission.Action; 19 | import com.yanzhenjie.permission.Rationale; 20 | 21 | import java.io.File; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/4/28. 25 | */ 26 | public interface InstallRequest { 27 | 28 | /** 29 | * The apk file. 30 | * 31 | * @param file apk file. 32 | */ 33 | InstallRequest file(File file); 34 | 35 | /** 36 | * Set request rationale. 37 | */ 38 | InstallRequest rationale(Rationale rationale); 39 | 40 | /** 41 | * Action to be taken when all permissions are granted. 42 | */ 43 | InstallRequest onGranted(Action granted); 44 | 45 | /** 46 | * Action to be taken when all permissions are denied. 47 | */ 48 | InstallRequest onDenied(Action denied); 49 | 50 | /** 51 | * Start install. 52 | */ 53 | void start(); 54 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/install/NRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.install; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 2018/4/28. 22 | */ 23 | class NRequest extends BaseRequest { 24 | 25 | NRequest(Source source) { 26 | super(source); 27 | } 28 | 29 | @Override 30 | public void start() { 31 | callbackSucceed(); 32 | install(); 33 | } 34 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/install/NRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.install; 17 | 18 | import com.yanzhenjie.permission.Boot; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/4/28. 23 | */ 24 | public class NRequestFactory implements Boot.InstallRequestFactory { 25 | 26 | @Override 27 | public InstallRequest create(Source source) { 28 | return new NRequest(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/install/ORequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.install; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.bridge.BridgeRequest; 20 | import com.yanzhenjie.permission.bridge.RequestManager; 21 | import com.yanzhenjie.permission.source.Source; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/4/28. 25 | */ 26 | class ORequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback { 27 | 28 | private Source mSource; 29 | 30 | ORequest(Source source) { 31 | super(source); 32 | this.mSource = source; 33 | } 34 | 35 | @Override 36 | public void start() { 37 | if (mSource.canRequestPackageInstalls()) { 38 | callbackSucceed(); 39 | install(); 40 | } else { 41 | showRationale(this); 42 | } 43 | } 44 | 45 | @Override 46 | public void execute() { 47 | BridgeRequest request = new BridgeRequest(mSource); 48 | request.setType(BridgeRequest.TYPE_INSTALL); 49 | request.setCallback(this); 50 | RequestManager.get().add(request); 51 | } 52 | 53 | @Override 54 | public void cancel() { 55 | callbackFailed(); 56 | } 57 | 58 | @Override 59 | public void onCallback() { 60 | if (mSource.canRequestPackageInstalls()) { 61 | callbackSucceed(); 62 | install(); 63 | } else { 64 | callbackFailed(); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/install/ORequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.install; 17 | 18 | import com.yanzhenjie.permission.Boot; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/4/28. 23 | */ 24 | public class ORequestFactory implements Boot.InstallRequestFactory { 25 | 26 | @Override 27 | public InstallRequest create(Source source) { 28 | return new ORequest(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/BaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify; 17 | 18 | import android.content.Context; 19 | 20 | import com.yanzhenjie.permission.Action; 21 | import com.yanzhenjie.permission.Rationale; 22 | import com.yanzhenjie.permission.RequestExecutor; 23 | import com.yanzhenjie.permission.source.Source; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/6/1. 27 | */ 28 | abstract class BaseRequest implements PermissionRequest { 29 | 30 | private Source mSource; 31 | 32 | private Rationale mRationale = new Rationale() { 33 | @Override 34 | public void showRationale(Context context, Void data, RequestExecutor executor) { 35 | executor.execute(); 36 | } 37 | }; 38 | private Action mGranted; 39 | private Action mDenied; 40 | 41 | BaseRequest(Source source) { 42 | this.mSource = source; 43 | } 44 | 45 | @Override 46 | public final PermissionRequest rationale(Rationale rationale) { 47 | this.mRationale = rationale; 48 | return this; 49 | } 50 | 51 | @Override 52 | public final PermissionRequest onGranted(Action granted) { 53 | this.mGranted = granted; 54 | return this; 55 | } 56 | 57 | @Override 58 | public final PermissionRequest onDenied(Action denied) { 59 | this.mDenied = denied; 60 | return this; 61 | } 62 | 63 | /** 64 | * Why permissions are required. 65 | */ 66 | final void showRationale(RequestExecutor executor) { 67 | mRationale.showRationale(mSource.getContext(), null, executor); 68 | } 69 | 70 | /** 71 | * Callback acceptance status. 72 | */ 73 | final void callbackSucceed() { 74 | if (mGranted != null) { 75 | mGranted.onAction(null); 76 | } 77 | } 78 | 79 | /** 80 | * Callback rejected state. 81 | */ 82 | final void callbackFailed() { 83 | if (mDenied != null) { 84 | mDenied.onAction(null); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/NRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.bridge.BridgeRequest; 20 | import com.yanzhenjie.permission.bridge.RequestManager; 21 | import com.yanzhenjie.permission.source.Source; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/5/29. 25 | */ 26 | class NRequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback { 27 | 28 | private Source mSource; 29 | 30 | NRequest(Source source) { 31 | super(source); 32 | this.mSource = source; 33 | } 34 | 35 | @Override 36 | public void start() { 37 | if (mSource.canNotify()) { 38 | callbackSucceed(); 39 | } else { 40 | showRationale(this); 41 | } 42 | } 43 | 44 | @Override 45 | public void execute() { 46 | BridgeRequest request = new BridgeRequest(mSource); 47 | request.setType(BridgeRequest.TYPE_APP_DETAILS); 48 | request.setCallback(this); 49 | RequestManager.get().add(request); 50 | } 51 | 52 | @Override 53 | public void cancel() { 54 | callbackFailed(); 55 | } 56 | 57 | @Override 58 | public void onCallback() { 59 | if (mSource.canNotify()) { 60 | callbackSucceed(); 61 | } else { 62 | callbackFailed(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/NRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 2018/5/29. 22 | */ 23 | public class NRequestFactory implements Notify.PermissionRequestFactory { 24 | 25 | @Override 26 | public PermissionRequest create(Source source) { 27 | return new NRequest(source); 28 | } 29 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/Notify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify; 17 | 18 | import android.os.Build; 19 | 20 | import com.yanzhenjie.permission.notify.listener.J1RequestFactory; 21 | import com.yanzhenjie.permission.notify.listener.J2RequestFactory; 22 | import com.yanzhenjie.permission.notify.listener.ListenerRequest; 23 | import com.yanzhenjie.permission.notify.option.NotifyOption; 24 | import com.yanzhenjie.permission.source.Source; 25 | 26 | /** 27 | * Created by Zhenjie Yan on 2/22/19. 28 | */ 29 | public class Notify implements NotifyOption { 30 | 31 | private static final PermissionRequestFactory PERMISSION_REQUEST_FACTORY; 32 | private static final ListenerRequestFactory LISTENER_REQUEST_FACTORY; 33 | 34 | static { 35 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 36 | PERMISSION_REQUEST_FACTORY = new ORequestFactory(); 37 | } else { 38 | PERMISSION_REQUEST_FACTORY = new NRequestFactory(); 39 | } 40 | 41 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 42 | LISTENER_REQUEST_FACTORY = new J2RequestFactory(); 43 | } else { 44 | LISTENER_REQUEST_FACTORY = new J1RequestFactory(); 45 | } 46 | } 47 | 48 | public interface PermissionRequestFactory { 49 | 50 | /** 51 | * Create notify request. 52 | */ 53 | PermissionRequest create(Source source); 54 | } 55 | 56 | public interface ListenerRequestFactory { 57 | 58 | /** 59 | * Create notification listener request. 60 | */ 61 | ListenerRequest create(Source source); 62 | } 63 | 64 | private Source mSource; 65 | 66 | public Notify(Source source) { 67 | this.mSource = source; 68 | } 69 | 70 | public PermissionRequest permission() { 71 | return PERMISSION_REQUEST_FACTORY.create(mSource); 72 | } 73 | 74 | public ListenerRequest listener() { 75 | return LISTENER_REQUEST_FACTORY.create(mSource); 76 | } 77 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/ORequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.bridge.BridgeRequest; 20 | import com.yanzhenjie.permission.bridge.RequestManager; 21 | import com.yanzhenjie.permission.source.Source; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/5/29. 25 | */ 26 | class ORequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback { 27 | 28 | private Source mSource; 29 | 30 | ORequest(Source source) { 31 | super(source); 32 | this.mSource = source; 33 | } 34 | 35 | @Override 36 | public void start() { 37 | if (mSource.canNotify()) { 38 | callbackSucceed(); 39 | } else { 40 | showRationale(this); 41 | } 42 | } 43 | 44 | @Override 45 | public void execute() { 46 | BridgeRequest request = new BridgeRequest(mSource); 47 | request.setType(BridgeRequest.TYPE_NOTIFY); 48 | request.setCallback(this); 49 | RequestManager.get().add(request); 50 | } 51 | 52 | @Override 53 | public void cancel() { 54 | callbackFailed(); 55 | } 56 | 57 | @Override 58 | public void onCallback() { 59 | if (mSource.canNotify()) { 60 | callbackSucceed(); 61 | } else { 62 | callbackFailed(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/ORequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 2018/5/29. 22 | */ 23 | public class ORequestFactory implements Notify.PermissionRequestFactory { 24 | 25 | @Override 26 | public PermissionRequest create(Source source) { 27 | return new ORequest(source); 28 | } 29 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/PermissionRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify; 17 | 18 | import com.yanzhenjie.permission.Action; 19 | import com.yanzhenjie.permission.Rationale; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2/14/19. 23 | */ 24 | public interface PermissionRequest { 25 | 26 | /** 27 | * Set request rationale. 28 | */ 29 | PermissionRequest rationale(Rationale rationale); 30 | 31 | /** 32 | * Action to be taken when all permissions are granted. 33 | */ 34 | PermissionRequest onGranted(Action granted); 35 | 36 | /** 37 | * Action to be taken when all permissions are denied. 38 | */ 39 | PermissionRequest onDenied(Action denied); 40 | 41 | /** 42 | * Start install. 43 | */ 44 | void start(); 45 | 46 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/listener/BaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify.listener; 17 | 18 | import android.content.Context; 19 | 20 | import com.yanzhenjie.permission.Action; 21 | import com.yanzhenjie.permission.Rationale; 22 | import com.yanzhenjie.permission.RequestExecutor; 23 | import com.yanzhenjie.permission.source.Source; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/6/1. 27 | */ 28 | abstract class BaseRequest implements ListenerRequest { 29 | 30 | private Source mSource; 31 | 32 | private Rationale mRationale = new Rationale() { 33 | @Override 34 | public void showRationale(Context context, Void data, RequestExecutor executor) { 35 | executor.execute(); 36 | } 37 | }; 38 | private Action mGranted; 39 | private Action mDenied; 40 | 41 | BaseRequest(Source source) { 42 | this.mSource = source; 43 | } 44 | 45 | @Override 46 | public final ListenerRequest rationale(Rationale rationale) { 47 | this.mRationale = rationale; 48 | return this; 49 | } 50 | 51 | @Override 52 | public final ListenerRequest onGranted(Action granted) { 53 | this.mGranted = granted; 54 | return this; 55 | } 56 | 57 | @Override 58 | public final ListenerRequest onDenied(Action denied) { 59 | this.mDenied = denied; 60 | return this; 61 | } 62 | 63 | /** 64 | * Why permissions are required. 65 | */ 66 | final void showRationale(RequestExecutor executor) { 67 | mRationale.showRationale(mSource.getContext(), null, executor); 68 | } 69 | 70 | /** 71 | * Callback acceptance status. 72 | */ 73 | final void callbackSucceed() { 74 | if (mGranted != null) { 75 | mGranted.onAction(null); 76 | } 77 | } 78 | 79 | /** 80 | * Callback rejected state. 81 | */ 82 | final void callbackFailed() { 83 | if (mDenied != null) { 84 | mDenied.onAction(null); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify.listener; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/5/29. 23 | */ 24 | class J1Request extends BaseRequest implements RequestExecutor { 25 | 26 | J1Request(Source source) { 27 | super(source); 28 | } 29 | 30 | @Override 31 | public void start() { 32 | callbackSucceed(); 33 | } 34 | 35 | @Override 36 | public void execute() { 37 | // Nothing. 38 | } 39 | 40 | @Override 41 | public void cancel() { 42 | // Nothing. 43 | } 44 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/listener/J1RequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify.listener; 17 | 18 | import com.yanzhenjie.permission.notify.Notify; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/5/29. 23 | */ 24 | public class J1RequestFactory implements Notify.ListenerRequestFactory { 25 | 26 | @Override 27 | public ListenerRequest create(Source source) { 28 | return new J1Request(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify.listener; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.bridge.BridgeRequest; 20 | import com.yanzhenjie.permission.bridge.RequestManager; 21 | import com.yanzhenjie.permission.source.Source; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/5/29. 25 | */ 26 | class J2Request extends BaseRequest implements RequestExecutor, BridgeRequest.Callback { 27 | 28 | private Source mSource; 29 | 30 | J2Request(Source source) { 31 | super(source); 32 | this.mSource = source; 33 | } 34 | 35 | @Override 36 | public void start() { 37 | if (mSource.canListenerNotification()) { 38 | callbackSucceed(); 39 | } else { 40 | showRationale(this); 41 | } 42 | } 43 | 44 | @Override 45 | public void execute() { 46 | BridgeRequest request = new BridgeRequest(mSource); 47 | request.setType(BridgeRequest.TYPE_NOTIFY_LISTENER); 48 | request.setCallback(this); 49 | RequestManager.get().add(request); 50 | } 51 | 52 | @Override 53 | public void cancel() { 54 | callbackFailed(); 55 | } 56 | 57 | @Override 58 | public void onCallback() { 59 | if (mSource.canListenerNotification()) { 60 | callbackSucceed(); 61 | } else { 62 | callbackFailed(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/listener/J2RequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify.listener; 17 | 18 | import com.yanzhenjie.permission.notify.Notify; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/5/29. 23 | */ 24 | public class J2RequestFactory implements Notify.ListenerRequestFactory { 25 | 26 | @Override 27 | public ListenerRequest create(Source source) { 28 | return new J2Request(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/listener/ListenerRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify.listener; 17 | 18 | import com.yanzhenjie.permission.Action; 19 | import com.yanzhenjie.permission.Rationale; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2/14/19. 23 | */ 24 | public interface ListenerRequest { 25 | 26 | /** 27 | * Set request rationale. 28 | */ 29 | ListenerRequest rationale(Rationale rationale); 30 | 31 | /** 32 | * Action to be taken when all permissions are granted. 33 | */ 34 | ListenerRequest onGranted(Action granted); 35 | 36 | /** 37 | * Action to be taken when all permissions are denied. 38 | */ 39 | ListenerRequest onDenied(Action denied); 40 | 41 | /** 42 | * Start install. 43 | */ 44 | void start(); 45 | 46 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/notify/option/NotifyOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.notify.option; 17 | 18 | import com.yanzhenjie.permission.notify.PermissionRequest; 19 | import com.yanzhenjie.permission.notify.listener.ListenerRequest; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2/14/19. 23 | */ 24 | public interface NotifyOption { 25 | 26 | /** 27 | * Handle permissions. 28 | */ 29 | PermissionRequest permission(); 30 | 31 | /** 32 | * Handle notify listener. 33 | */ 34 | ListenerRequest listener(); 35 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/option/Option.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.option; 17 | 18 | import com.yanzhenjie.permission.install.InstallRequest; 19 | import com.yanzhenjie.permission.notify.option.NotifyOption; 20 | import com.yanzhenjie.permission.overlay.OverlayRequest; 21 | import com.yanzhenjie.permission.runtime.option.RuntimeOption; 22 | import com.yanzhenjie.permission.setting.Setting; 23 | 24 | /** 25 | * Created by Zhenjie Yan on 2/22/19. 26 | */ 27 | public interface Option { 28 | 29 | /** 30 | * Handle runtime permissions. 31 | */ 32 | RuntimeOption runtime(); 33 | 34 | /** 35 | * Handle request package install permission. 36 | */ 37 | InstallRequest install(); 38 | 39 | /** 40 | * Handle overlay permission. 41 | */ 42 | OverlayRequest overlay(); 43 | 44 | /** 45 | * Handle notification permission. 46 | */ 47 | NotifyOption notification(); 48 | 49 | /** 50 | * Handle system setting. 51 | */ 52 | Setting setting(); 53 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/overlay/BaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.overlay; 17 | 18 | import android.app.Dialog; 19 | import android.content.Context; 20 | import android.os.Build; 21 | import android.view.Window; 22 | import android.view.WindowManager; 23 | 24 | import com.yanzhenjie.permission.Action; 25 | import com.yanzhenjie.permission.R; 26 | import com.yanzhenjie.permission.Rationale; 27 | import com.yanzhenjie.permission.RequestExecutor; 28 | import com.yanzhenjie.permission.source.Source; 29 | 30 | /** 31 | * Created by Zhenjie Yan on 2018/6/1. 32 | */ 33 | abstract class BaseRequest implements OverlayRequest { 34 | 35 | private Source mSource; 36 | 37 | private Rationale mRationale = new Rationale() { 38 | @Override 39 | public void showRationale(Context context, Void data, RequestExecutor executor) { 40 | executor.execute(); 41 | } 42 | }; 43 | private Action mGranted; 44 | private Action mDenied; 45 | 46 | BaseRequest(Source source) { 47 | this.mSource = source; 48 | } 49 | 50 | @Override 51 | public final OverlayRequest rationale(Rationale rationale) { 52 | this.mRationale = rationale; 53 | return this; 54 | } 55 | 56 | @Override 57 | public final OverlayRequest onGranted(Action granted) { 58 | this.mGranted = granted; 59 | return this; 60 | } 61 | 62 | @Override 63 | public final OverlayRequest onDenied(Action denied) { 64 | this.mDenied = denied; 65 | return this; 66 | } 67 | 68 | /** 69 | * Why permissions are required. 70 | */ 71 | final void showRationale(RequestExecutor executor) { 72 | mRationale.showRationale(mSource.getContext(), null, executor); 73 | } 74 | 75 | /** 76 | * Callback acceptance status. 77 | */ 78 | final void callbackSucceed() { 79 | if (mGranted != null) { 80 | mGranted.onAction(null); 81 | } 82 | } 83 | 84 | /** 85 | * Callback rejected state. 86 | */ 87 | final void callbackFailed() { 88 | if (mDenied != null) { 89 | mDenied.onAction(null); 90 | } 91 | } 92 | 93 | static boolean tryDisplayDialog(Context context) { 94 | Dialog dialog = new Dialog(context, R.style.Permission_Theme_Dialog_Transparent); 95 | Window window = dialog.getWindow(); 96 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 97 | window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); 98 | } else { 99 | window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 100 | } 101 | try { 102 | dialog.show(); 103 | } catch (Exception e) { 104 | return false; 105 | } finally { 106 | if (dialog.isShowing()) dialog.dismiss(); 107 | } 108 | return true; 109 | } 110 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/overlay/LRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.overlay; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.bridge.BridgeRequest; 20 | import com.yanzhenjie.permission.bridge.RequestManager; 21 | import com.yanzhenjie.permission.source.Source; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/5/29. 25 | */ 26 | class LRequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback { 27 | 28 | private Source mSource; 29 | 30 | LRequest(Source source) { 31 | super(source); 32 | this.mSource = source; 33 | } 34 | 35 | @Override 36 | public void start() { 37 | if (tryDisplayDialog(mSource.getContext())) { 38 | callbackSucceed(); 39 | } else { 40 | showRationale(this); 41 | } 42 | } 43 | 44 | @Override 45 | public void execute() { 46 | BridgeRequest request = new BridgeRequest(mSource); 47 | request.setType(BridgeRequest.TYPE_ALERT_WINDOW); 48 | request.setCallback(this); 49 | RequestManager.get().add(request); 50 | } 51 | 52 | @Override 53 | public void cancel() { 54 | callbackFailed(); 55 | } 56 | 57 | @Override 58 | public void onCallback() { 59 | if (tryDisplayDialog(mSource.getContext())) { 60 | callbackSucceed(); 61 | } else { 62 | callbackFailed(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/overlay/LRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.overlay; 17 | 18 | import com.yanzhenjie.permission.Boot; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/5/29. 23 | */ 24 | public class LRequestFactory implements Boot.OverlayRequestFactory { 25 | 26 | @Override 27 | public OverlayRequest create(Source source) { 28 | return new LRequest(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/overlay/MRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.overlay; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.bridge.BridgeRequest; 20 | import com.yanzhenjie.permission.bridge.RequestManager; 21 | import com.yanzhenjie.permission.source.Source; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 2018/5/29. 25 | */ 26 | class MRequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback { 27 | 28 | private Source mSource; 29 | 30 | MRequest(Source source) { 31 | super(source); 32 | this.mSource = source; 33 | } 34 | 35 | @Override 36 | public void start() { 37 | if (mSource.canDrawOverlays()) { 38 | onCallback(); 39 | } else { 40 | showRationale(this); 41 | } 42 | } 43 | 44 | @Override 45 | public void execute() { 46 | BridgeRequest request = new BridgeRequest(mSource); 47 | request.setType(BridgeRequest.TYPE_OVERLAY); 48 | request.setCallback(this); 49 | RequestManager.get().add(request); 50 | } 51 | 52 | @Override 53 | public void cancel() { 54 | callbackFailed(); 55 | } 56 | 57 | @Override 58 | public void onCallback() { 59 | if (mSource.canDrawOverlays() && tryDisplayDialog(mSource.getContext())) { 60 | callbackSucceed(); 61 | } else { 62 | callbackFailed(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/overlay/MRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.overlay; 17 | 18 | import com.yanzhenjie.permission.Boot; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/5/29. 23 | */ 24 | public class MRequestFactory implements Boot.OverlayRequestFactory { 25 | 26 | @Override 27 | public OverlayRequest create(Source source) { 28 | return new MRequest(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/overlay/OverlayRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.overlay; 17 | 18 | import com.yanzhenjie.permission.Action; 19 | import com.yanzhenjie.permission.Rationale; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2018/5/29. 23 | */ 24 | public interface OverlayRequest { 25 | 26 | /** 27 | * Set request rationale. 28 | */ 29 | OverlayRequest rationale(Rationale rationale); 30 | 31 | /** 32 | * Action to be taken when all permissions are granted. 33 | */ 34 | OverlayRequest onGranted(Action granted); 35 | 36 | /** 37 | * Action to be taken when all permissions are denied. 38 | */ 39 | OverlayRequest onDenied(Action denied); 40 | 41 | /** 42 | * Start request. 43 | */ 44 | void start(); 45 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/overlay/setting/MSettingPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.overlay.setting; 17 | 18 | import android.content.Context; 19 | import android.content.Intent; 20 | import android.content.pm.PackageManager; 21 | import android.net.Uri; 22 | import android.os.Build; 23 | import android.provider.Settings; 24 | 25 | import com.yanzhenjie.permission.source.Source; 26 | 27 | /** 28 | * Created by Zhenjie Yan on 2018/5/30. 29 | */ 30 | public class MSettingPage { 31 | 32 | private static final String MARK = Build.MANUFACTURER.toLowerCase(); 33 | 34 | private Source mSource; 35 | 36 | public MSettingPage(Source source) { 37 | this.mSource = source; 38 | } 39 | 40 | public void start(int requestCode) { 41 | Intent intent; 42 | if (MARK.contains("meizu")) { 43 | intent = meiZuApi(mSource.getContext()); 44 | } else { 45 | intent = defaultApi(mSource.getContext()); 46 | } 47 | 48 | try { 49 | mSource.startActivityForResult(intent, requestCode); 50 | } catch (Exception e) { 51 | intent = appDetailsApi(mSource.getContext()); 52 | mSource.startActivityForResult(intent, requestCode); 53 | } 54 | } 55 | 56 | private static Intent appDetailsApi(Context context) { 57 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 58 | intent.setData(Uri.fromParts("package", context.getPackageName(), null)); 59 | return intent; 60 | } 61 | 62 | private static Intent defaultApi(Context context) { 63 | Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); 64 | intent.setData(Uri.fromParts("package", context.getPackageName(), null)); 65 | if (hasActivity(context, intent)) return intent; 66 | 67 | return appDetailsApi(context); 68 | } 69 | 70 | private static Intent meiZuApi(Context context) { 71 | Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC"); 72 | intent.putExtra("packageName", context.getPackageName()); 73 | intent.setClassName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity"); 74 | if (hasActivity(context, intent)) return intent; 75 | 76 | return defaultApi(context); 77 | } 78 | 79 | private static boolean hasActivity(Context context, Intent intent) { 80 | PackageManager packageManager = context.getPackageManager(); 81 | return packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0; 82 | } 83 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/LRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime; 17 | 18 | import androidx.annotation.NonNull; 19 | 20 | import com.yanzhenjie.permission.checker.PermissionChecker; 21 | import com.yanzhenjie.permission.checker.StrictChecker; 22 | import com.yanzhenjie.permission.source.Source; 23 | import com.yanzhenjie.permission.task.TaskExecutor; 24 | 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.List; 28 | 29 | /** 30 | * Created by Zhenjie Yan on 2018/1/25. 31 | */ 32 | class LRequest extends BaseRequest { 33 | 34 | private static final PermissionChecker STRICT_CHECKER = new StrictChecker(); 35 | 36 | private Source mSource; 37 | 38 | private List mPermissions; 39 | 40 | LRequest(Source source) { 41 | super(source); 42 | this.mSource = source; 43 | } 44 | 45 | @Override 46 | public PermissionRequest permission(@NonNull String... permissions) { 47 | mPermissions = new ArrayList<>(); 48 | mPermissions.addAll(Arrays.asList(permissions)); 49 | return this; 50 | } 51 | 52 | @Override 53 | public PermissionRequest permission(@NonNull String[]... groups) { 54 | mPermissions = new ArrayList<>(); 55 | for (String[] group : groups) { 56 | mPermissions.addAll(Arrays.asList(group)); 57 | } 58 | return this; 59 | } 60 | 61 | @Override 62 | public void start() { 63 | mPermissions = filterPermissions(mPermissions); 64 | 65 | new TaskExecutor>(mSource.getContext()) { 66 | @Override 67 | protected List doInBackground(Void... voids) { 68 | return getDeniedPermissions(STRICT_CHECKER, mSource, mPermissions); 69 | } 70 | 71 | @Override 72 | protected void onFinish(List deniedList) { 73 | if (deniedList.isEmpty()) { 74 | callbackSucceed(mPermissions); 75 | } else { 76 | callbackFailed(deniedList); 77 | } 78 | } 79 | }.execute(); 80 | } 81 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/LRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 2018/4/28. 22 | */ 23 | public class LRequestFactory implements Runtime.PermissionRequestFactory { 24 | 25 | @Override 26 | public PermissionRequest create(Source source) { 27 | return new LRequest(source); 28 | } 29 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/MRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 2018/4/28. 22 | */ 23 | public class MRequestFactory implements Runtime.PermissionRequestFactory { 24 | 25 | @Override 26 | public PermissionRequest create(Source source) { 27 | return new MRequest(source); 28 | } 29 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/PermissionDef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime; 17 | 18 | import androidx.annotation.StringDef; 19 | 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | 23 | /** 24 | * Created Zhenjie Yan on 2019-10-10. 25 | */ 26 | @StringDef({ 27 | Permission.READ_CALENDAR, 28 | Permission.WRITE_CALENDAR, 29 | Permission.CAMERA, 30 | Permission.READ_CONTACTS, 31 | Permission.WRITE_CONTACTS, 32 | Permission.GET_ACCOUNTS, 33 | Permission.ACCESS_FINE_LOCATION, 34 | Permission.ACCESS_COARSE_LOCATION, 35 | Permission.ACCESS_BACKGROUND_LOCATION, 36 | Permission.RECORD_AUDIO, 37 | Permission.READ_PHONE_STATE, 38 | Permission.CALL_PHONE, 39 | Permission.ADD_VOICEMAIL, 40 | Permission.USE_SIP, 41 | Permission.READ_PHONE_NUMBERS, 42 | Permission.ANSWER_PHONE_CALLS, 43 | Permission.READ_CALL_LOG, 44 | Permission.WRITE_CALL_LOG, 45 | Permission.PROCESS_OUTGOING_CALLS, 46 | Permission.BODY_SENSORS, 47 | Permission.ACTIVITY_RECOGNITION, 48 | Permission.SEND_SMS, 49 | Permission.RECEIVE_SMS, 50 | Permission.READ_SMS, 51 | Permission.RECEIVE_WAP_PUSH, 52 | Permission.RECEIVE_MMS, 53 | Permission.READ_EXTERNAL_STORAGE, 54 | Permission.WRITE_EXTERNAL_STORAGE 55 | }) 56 | @Retention(RetentionPolicy.SOURCE) 57 | public @interface PermissionDef { 58 | } 59 | -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/PermissionRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime; 17 | 18 | import androidx.annotation.NonNull; 19 | 20 | import com.yanzhenjie.permission.Action; 21 | import com.yanzhenjie.permission.Rationale; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | *

Permission request.

27 | * Created by Zhenjie Yan on 2016/9/9. 28 | */ 29 | public interface PermissionRequest { 30 | 31 | /** 32 | * One or more permissions. 33 | */ 34 | PermissionRequest permission(@NonNull @PermissionDef String... permissions); 35 | 36 | /** 37 | * One or more permissions group. 38 | * 39 | * @param groups use constants in {@link Permission.Group}. 40 | */ 41 | PermissionRequest permission(@NonNull String[]... groups); 42 | 43 | /** 44 | * Set request rationale. 45 | */ 46 | PermissionRequest rationale(@NonNull Rationale> rationale); 47 | 48 | /** 49 | * Action to be taken when all permissions are granted. 50 | */ 51 | PermissionRequest onGranted(@NonNull Action> granted); 52 | 53 | /** 54 | * Action to be taken when all permissions are denied. 55 | */ 56 | PermissionRequest onDenied(@NonNull Action> denied); 57 | 58 | /** 59 | * Request permission. 60 | */ 61 | void start(); 62 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/option/RuntimeOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime.option; 17 | 18 | import androidx.annotation.NonNull; 19 | 20 | import com.yanzhenjie.permission.runtime.Permission; 21 | import com.yanzhenjie.permission.runtime.PermissionDef; 22 | import com.yanzhenjie.permission.runtime.PermissionRequest; 23 | import com.yanzhenjie.permission.runtime.setting.SettingRequest; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2/22/19. 27 | */ 28 | public interface RuntimeOption { 29 | 30 | /** 31 | * One or more permissions. 32 | */ 33 | PermissionRequest permission(@NonNull @PermissionDef String... permissions); 34 | 35 | /** 36 | * One or more permission groups. 37 | * 38 | * @param groups use constants in {@link Permission.Group}. 39 | */ 40 | PermissionRequest permission(@NonNull String[]... groups); 41 | 42 | /** 43 | * Permission settings. 44 | */ 45 | SettingRequest setting(); 46 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/setting/AllRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime.setting; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | /** 21 | *

SettingRequest executor.

22 | * Created by Zhenjie Yan on 2016/12/28. 23 | */ 24 | public class AllRequest implements SettingRequest { 25 | 26 | private Source mSource; 27 | 28 | public AllRequest(Source source) { 29 | this.mSource = source; 30 | } 31 | 32 | @Override 33 | public void start(int requestCode) { 34 | SettingPage setting = new SettingPage(mSource); 35 | setting.start(requestCode); 36 | } 37 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/runtime/setting/SettingRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.runtime.setting; 17 | 18 | /** 19 | * Created by Zhenjie Yan on 2018/4/30. 20 | */ 21 | public interface SettingRequest { 22 | 23 | /** 24 | * Start the setup. 25 | */ 26 | void start(int requestCode); 27 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/setting/Setting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.setting; 17 | 18 | import android.os.Build; 19 | 20 | import com.yanzhenjie.permission.setting.write.LWriteRequestFactory; 21 | import com.yanzhenjie.permission.setting.write.MWriteRequestFactory; 22 | import com.yanzhenjie.permission.setting.write.WriteRequest; 23 | import com.yanzhenjie.permission.source.Source; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 3/1/19. 27 | */ 28 | public class Setting { 29 | 30 | private static final SettingRequestFactory SETTING_REQUEST_FACTORY; 31 | 32 | static { 33 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 34 | SETTING_REQUEST_FACTORY = new MWriteRequestFactory(); 35 | } else { 36 | SETTING_REQUEST_FACTORY = new LWriteRequestFactory(); 37 | } 38 | } 39 | 40 | public interface SettingRequestFactory { 41 | 42 | WriteRequest create(Source source); 43 | } 44 | 45 | private Source mSource; 46 | 47 | public Setting(Source source) { 48 | this.mSource = source; 49 | } 50 | 51 | /** 52 | * Handle write system settings. 53 | */ 54 | public WriteRequest write() { 55 | return SETTING_REQUEST_FACTORY.create(mSource); 56 | } 57 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/setting/write/BaseRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.setting.write; 17 | 18 | import android.content.Context; 19 | 20 | import com.yanzhenjie.permission.Action; 21 | import com.yanzhenjie.permission.Rationale; 22 | import com.yanzhenjie.permission.RequestExecutor; 23 | import com.yanzhenjie.permission.source.Source; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/6/1. 27 | */ 28 | abstract class BaseRequest implements WriteRequest { 29 | 30 | private Source mSource; 31 | 32 | private Rationale mRationale = new Rationale() { 33 | @Override 34 | public void showRationale(Context context, Void data, RequestExecutor executor) { 35 | executor.execute(); 36 | } 37 | }; 38 | private Action mGranted; 39 | private Action mDenied; 40 | 41 | BaseRequest(Source source) { 42 | this.mSource = source; 43 | } 44 | 45 | @Override 46 | public final WriteRequest rationale(Rationale rationale) { 47 | this.mRationale = rationale; 48 | return this; 49 | } 50 | 51 | @Override 52 | public final WriteRequest onGranted(Action granted) { 53 | this.mGranted = granted; 54 | return this; 55 | } 56 | 57 | @Override 58 | public final WriteRequest onDenied(Action denied) { 59 | this.mDenied = denied; 60 | return this; 61 | } 62 | 63 | /** 64 | * Why permissions are required. 65 | */ 66 | final void showRationale(RequestExecutor executor) { 67 | mRationale.showRationale(mSource.getContext(), null, executor); 68 | } 69 | 70 | /** 71 | * Callback acceptance status. 72 | */ 73 | final void callbackSucceed() { 74 | if (mGranted != null) { 75 | mGranted.onAction(null); 76 | } 77 | } 78 | 79 | /** 80 | * Callback rejected state. 81 | */ 82 | final void callbackFailed() { 83 | if (mDenied != null) { 84 | mDenied.onAction(null); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/setting/write/LWriteRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.setting.write; 17 | 18 | import com.yanzhenjie.permission.source.Source; 19 | 20 | /** 21 | * Created by Zhenjie Yan on 3/1/19. 22 | */ 23 | public class LWriteRequest extends BaseRequest { 24 | 25 | public LWriteRequest(Source source) { 26 | super(source); 27 | } 28 | 29 | @Override 30 | public void start() { 31 | callbackSucceed(); 32 | } 33 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/setting/write/LWriteRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.setting.write; 17 | 18 | import com.yanzhenjie.permission.setting.Setting; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 3/1/19. 23 | */ 24 | public class LWriteRequestFactory implements Setting.SettingRequestFactory { 25 | 26 | @Override 27 | public WriteRequest create(Source source) { 28 | return new LWriteRequest(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/setting/write/MWriteRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.setting.write; 17 | 18 | import com.yanzhenjie.permission.RequestExecutor; 19 | import com.yanzhenjie.permission.bridge.BridgeRequest; 20 | import com.yanzhenjie.permission.bridge.RequestManager; 21 | import com.yanzhenjie.permission.source.Source; 22 | 23 | /** 24 | * Created by Zhenjie Yan on 3/1/19. 25 | */ 26 | public class MWriteRequest extends BaseRequest implements RequestExecutor, BridgeRequest.Callback { 27 | 28 | private Source mSource; 29 | 30 | public MWriteRequest(Source source) { 31 | super(source); 32 | this.mSource = source; 33 | } 34 | 35 | @Override 36 | public void start() { 37 | if (mSource.canWriteSetting()) { 38 | callbackSucceed(); 39 | } else { 40 | showRationale(this); 41 | } 42 | } 43 | 44 | @Override 45 | public void execute() { 46 | BridgeRequest request = new BridgeRequest(mSource); 47 | request.setType(BridgeRequest.TYPE_WRITE_SETTING); 48 | request.setCallback(this); 49 | RequestManager.get().add(request); 50 | } 51 | 52 | @Override 53 | public void cancel() { 54 | callbackFailed(); 55 | } 56 | 57 | @Override 58 | public void onCallback() { 59 | if (mSource.canWriteSetting()) { 60 | callbackSucceed(); 61 | } else { 62 | callbackFailed(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/setting/write/MWriteRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.setting.write; 17 | 18 | import com.yanzhenjie.permission.setting.Setting; 19 | import com.yanzhenjie.permission.source.Source; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 3/1/19. 23 | */ 24 | public class MWriteRequestFactory implements Setting.SettingRequestFactory { 25 | 26 | @Override 27 | public WriteRequest create(Source source) { 28 | return new MWriteRequest(source); 29 | } 30 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/setting/write/WriteRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.setting.write; 17 | 18 | import com.yanzhenjie.permission.Action; 19 | import com.yanzhenjie.permission.Rationale; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 3/1/19. 23 | */ 24 | public interface WriteRequest { 25 | 26 | /** 27 | * Set request rationale. 28 | */ 29 | WriteRequest rationale(Rationale rationale); 30 | 31 | /** 32 | * Action to be taken when all permissions are granted. 33 | */ 34 | WriteRequest onGranted(Action granted); 35 | 36 | /** 37 | * Action to be taken when all permissions are denied. 38 | */ 39 | WriteRequest onDenied(Action denied); 40 | 41 | /** 42 | * Start install. 43 | */ 44 | void start(); 45 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/source/ActivitySource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.source; 17 | 18 | import android.app.Activity; 19 | import android.content.Context; 20 | import android.content.Intent; 21 | import android.os.Build; 22 | 23 | /** 24 | *

Context Wrapper.

25 | * Created by Zhenjie Yan on 2017/5/1. 26 | */ 27 | public class ActivitySource extends Source { 28 | 29 | private Activity mActivity; 30 | 31 | public ActivitySource(Activity activity) { 32 | this.mActivity = activity; 33 | } 34 | 35 | @Override 36 | public Context getContext() { 37 | return mActivity; 38 | } 39 | 40 | @Override 41 | public void startActivity(Intent intent) { 42 | mActivity.startActivity(intent); 43 | } 44 | 45 | @Override 46 | public void startActivityForResult(Intent intent, int requestCode) { 47 | mActivity.startActivityForResult(intent, requestCode); 48 | } 49 | 50 | @Override 51 | public boolean isShowRationalePermission(String permission) { 52 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; 53 | 54 | return mActivity.shouldShowRequestPermissionRationale(permission); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/source/ContextSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.source; 17 | 18 | import android.content.Context; 19 | import android.content.Intent; 20 | import android.content.pm.PackageManager; 21 | import android.os.Build; 22 | 23 | import java.lang.reflect.Method; 24 | 25 | /** 26 | *

Context Wrapper.

27 | * Created by Zhenjie Yan on 2017/5/1. 28 | */ 29 | public class ContextSource extends Source { 30 | 31 | private Context mContext; 32 | 33 | public ContextSource(Context context) { 34 | this.mContext = context; 35 | } 36 | 37 | @Override 38 | public Context getContext() { 39 | return mContext; 40 | } 41 | 42 | @Override 43 | public void startActivity(Intent intent) { 44 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 45 | mContext.startActivity(intent); 46 | } 47 | 48 | @Override 49 | public void startActivityForResult(Intent intent, int requestCode) { 50 | throw new UnsupportedOperationException("Unsupported operation."); 51 | } 52 | 53 | @Override 54 | public boolean isShowRationalePermission(String permission) { 55 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; 56 | 57 | PackageManager packageManager = mContext.getPackageManager(); 58 | Class pkManagerClass = packageManager.getClass(); 59 | try { 60 | Method method = pkManagerClass.getMethod("shouldShowRequestPermissionRationale", String.class); 61 | if (!method.isAccessible()) method.setAccessible(true); 62 | return (boolean)method.invoke(packageManager, permission); 63 | } catch (Exception ignored) { 64 | return false; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/source/FragmentSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.source; 17 | 18 | import android.app.Fragment; 19 | import android.content.Context; 20 | import android.content.Intent; 21 | import android.os.Build; 22 | 23 | /** 24 | *

android.app.Fragment Wrapper.

25 | * Created by Zhenjie Yan on 2017/5/1. 26 | */ 27 | public class FragmentSource extends Source { 28 | 29 | private Fragment mFragment; 30 | 31 | public FragmentSource(Fragment fragment) { 32 | this.mFragment = fragment; 33 | } 34 | 35 | @Override 36 | public Context getContext() { 37 | return mFragment.getActivity(); 38 | } 39 | 40 | @Override 41 | public void startActivity(Intent intent) { 42 | mFragment.startActivity(intent); 43 | } 44 | 45 | @Override 46 | public void startActivityForResult(Intent intent, int requestCode) { 47 | mFragment.startActivityForResult(intent, requestCode); 48 | } 49 | 50 | @Override 51 | public boolean isShowRationalePermission(String permission) { 52 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; 53 | return mFragment.shouldShowRequestPermissionRationale(permission); 54 | } 55 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/source/WrapperSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.source; 17 | 18 | import android.content.Context; 19 | import android.content.Intent; 20 | 21 | /** 22 | * Created by Zhenjie Yan on 2/22/19. 23 | */ 24 | public class WrapperSource extends Source { 25 | 26 | private Source mSource; 27 | 28 | public WrapperSource(Source source) { 29 | this.mSource = source; 30 | } 31 | 32 | @Override 33 | public Context getContext() { 34 | return mSource.getContext(); 35 | } 36 | 37 | @Override 38 | public void startActivity(Intent intent) { 39 | mSource.startActivity(intent); 40 | } 41 | 42 | @Override 43 | public void startActivityForResult(Intent intent, int requestCode) { 44 | mSource.startActivityForResult(intent, requestCode); 45 | } 46 | 47 | @Override 48 | public boolean isShowRationalePermission(String permission) { 49 | return mSource.isShowRationalePermission(permission); 50 | } 51 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/source/XFragmentSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.source; 17 | 18 | import android.content.Context; 19 | import android.content.Intent; 20 | import android.os.Build; 21 | 22 | import androidx.fragment.app.Fragment; 23 | 24 | /** 25 | *

android.support.v4.app.Fragment Wrapper.

26 | * Created by Zhenjie Yan on 2017/5/1. 27 | */ 28 | public class XFragmentSource extends Source { 29 | 30 | private Fragment mFragment; 31 | 32 | public XFragmentSource(Fragment fragment) { 33 | this.mFragment = fragment; 34 | } 35 | 36 | @Override 37 | public Context getContext() { 38 | return mFragment.getContext(); 39 | } 40 | 41 | @Override 42 | public void startActivity(Intent intent) { 43 | mFragment.startActivity(intent); 44 | } 45 | 46 | @Override 47 | public void startActivityForResult(Intent intent, int requestCode) { 48 | mFragment.startActivityForResult(intent, requestCode); 49 | } 50 | 51 | @Override 52 | public boolean isShowRationalePermission(String permission) { 53 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; 54 | return mFragment.shouldShowRequestPermissionRationale(permission); 55 | } 56 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/task/TaskExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.task; 17 | 18 | import android.app.Dialog; 19 | import android.content.Context; 20 | import android.os.AsyncTask; 21 | 22 | import java.util.concurrent.Executor; 23 | import java.util.concurrent.Executors; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2019-09-23. 27 | */ 28 | public abstract class TaskExecutor extends AsyncTask { 29 | 30 | private static Executor sExecutor = Executors.newSingleThreadExecutor(); 31 | 32 | private Dialog mDialog; 33 | 34 | public TaskExecutor(Context context) { 35 | this.mDialog = new WaitDialog(context); 36 | this.mDialog.setCancelable(false); 37 | } 38 | 39 | @Override 40 | protected final void onPreExecute() { 41 | if (!mDialog.isShowing()) { 42 | mDialog.show(); 43 | } 44 | } 45 | 46 | @Override 47 | protected final void onPostExecute(T t) { 48 | if (mDialog.isShowing()) { 49 | mDialog.dismiss(); 50 | } 51 | onFinish(t); 52 | } 53 | 54 | protected abstract void onFinish(T t); 55 | 56 | /** 57 | * Just call this method. 58 | */ 59 | public final void execute() { 60 | executeOnExecutor(sExecutor); 61 | } 62 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/task/WaitDialog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.task; 17 | 18 | import android.content.Context; 19 | 20 | import androidx.annotation.NonNull; 21 | import androidx.appcompat.app.AppCompatDialog; 22 | 23 | import com.yanzhenjie.permission.R; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2019-09-23. 27 | */ 28 | public class WaitDialog extends AppCompatDialog { 29 | 30 | public WaitDialog(@NonNull Context context) { 31 | super(context, R.style.Permission_Theme_Dialog_Wait); 32 | setContentView(R.layout.permission_dialog_wait); 33 | } 34 | } -------------------------------------------------------------------------------- /permission/src/main/java/com/yanzhenjie/permission/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.util; 17 | 18 | /** 19 | * Created Zhenjie Yan on 2019-10-02. 20 | */ 21 | public class StringUtils { 22 | 23 | private static final String DIGITS_TEXT = "0123456789ABCDEF"; 24 | private static final char[] DIGITS_ARRAY = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 25 | 26 | public static String textToHex(String text) { 27 | StringBuilder builder = new StringBuilder(); 28 | byte[] textBytes = text.getBytes(); 29 | int bit; 30 | 31 | for (int i = 0; i < textBytes.length; i++) { 32 | bit = (textBytes[i] & 0x0f0) >> 4; 33 | builder.append(DIGITS_ARRAY[bit]); 34 | bit = textBytes[i] & 0x0f; 35 | builder.append(DIGITS_ARRAY[bit]); 36 | } 37 | return builder.toString().trim(); 38 | } 39 | 40 | public static String hexToText(String hexText) { 41 | char[] hexArray = hexText.toCharArray(); 42 | byte[] hexBytes = new byte[hexText.length() / 2]; 43 | for (int i = 0; i < hexBytes.length; i++) { 44 | int n = DIGITS_TEXT.indexOf(hexArray[2 * i]) * 16; 45 | n += DIGITS_TEXT.indexOf(hexArray[2 * i + 1]); 46 | hexBytes[i] = (byte) (n & 0xff); 47 | } 48 | return new String(hexBytes); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /permission/src/main/res/drawable/permission_shape_wait_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /permission/src/main/res/layout/permission_dialog_wait.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 27 | 28 | 32 | 33 | 40 | 41 | -------------------------------------------------------------------------------- /permission/src/main/res/values-v21/style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 26 | 27 | 35 | 36 | -------------------------------------------------------------------------------- /permission/src/main/res/values-zh-RHK/string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 日曆 20 | 相機 21 | 手機賬號/通訊錄 22 | 位置信息 23 | 麥克風 24 | 電話 25 | 通話記錄 26 | 身體傳感器 27 | 健身運動 28 | 短訊 29 | 存儲空間 30 | 31 | 正在請求授權… 32 | -------------------------------------------------------------------------------- /permission/src/main/res/values-zh-RTW/string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 日曆 20 | 相機 21 | 手機賬號/通訊錄 22 | 位置信息 23 | 麥克風 24 | 電話 25 | 通話記錄 26 | 身體感測器 27 | 健身運動 28 | 簡訊 29 | 存儲空間 30 | 31 | 正在請求授權… 32 | -------------------------------------------------------------------------------- /permission/src/main/res/values-zh/string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 日历 20 | 相机 21 | 手机账号/通讯录 22 | 位置信息 23 | 麦克风 24 | 电话 25 | 通话记录 26 | 身体传感器 27 | 健身运动 28 | 短信 29 | 存储空间 30 | 31 | 正在请求授权… 32 | -------------------------------------------------------------------------------- /permission/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 3dp 21 | 5dp 22 | 10dp 23 | 15dp 24 | 20dp 25 | 25dp 26 | 30dp 27 | 35dp 28 | 40dp 29 | 30 | 12sp 31 | 14sp 32 | 16sp 33 | 18sp 34 | 20sp 35 | 36 | -------------------------------------------------------------------------------- /permission/src/main/res/values/string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | Calendar 20 | Camera 21 | Accounts/Contacts 22 | Location 23 | Microphone 24 | Phone 25 | Call Log 26 | Body Sensors 27 | Activity Recognition 28 | SMS 29 | Storage 30 | 31 | Requesting permissions… 32 | -------------------------------------------------------------------------------- /permission/src/main/res/values/style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 31 | 32 | 37 | 38 | 45 | 46 | 53 | 54 | 61 | 62 | 66 | 67 | 71 | 72 | -------------------------------------------------------------------------------- /permission/src/main/res/xml/permission_file_paths.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 20 | 21 | 24 | 25 | 28 | 29 | 32 | 33 | 36 | 37 | 40 | 41 | 44 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: rootProject.ext.plugins.application 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.android.compileSdkVersion 5 | buildToolsVersion rootProject.ext.android.buildToolsVersion 6 | 7 | defaultConfig { 8 | applicationId rootProject.ext.android.applicationId 9 | minSdkVersion rootProject.ext.android.minSdkVersion 10 | targetSdkVersion rootProject.ext.android.targetSdkVersion 11 | versionCode rootProject.ext.android.versionCode 12 | versionName rootProject.ext.android.versionName 13 | } 14 | } 15 | 16 | dependencies { 17 | implementation project(':permission') 18 | 19 | implementation rootProject.ext.dependencies.fragment 20 | } -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -ignorewarnings 3 | -dontusemixedcaseclassnames 4 | -dontskipnonpubliclibraryclasses 5 | -dontskipnonpubliclibraryclassmembers 6 | -useuniqueclassmembernames 7 | -allowaccessmodification 8 | -dontpreverify 9 | -verbose 10 | -dontoptimize 11 | -renamesourcefileattribute SourceFile 12 | -keepattributes SourceFile,LineNumberTable 13 | -keepattributes Signature 14 | -keepattributes *Annotation* 15 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 16 | -keepclassmembers class * extends android.app.Activity { 17 | public void *(android.view.View); 18 | } 19 | -keepclassmembers enum * { 20 | public static **[] values(); 21 | public static ** valueOf(java.lang.String); 22 | } 23 | -keep public class **.R$*{ 24 | public static final int *; 25 | } 26 | -keepclassmembers class **.R$* { 27 | public static ; 28 | } 29 | -keepclassmembers class * { 30 | native ; 31 | } 32 | -keepclasseswithmembernames class * { 33 | native ; 34 | } 35 | -keepclasseswithmembers class * { 36 | public (android.content.Context); 37 | public (android.content.Context, android.util.AttributeSet); 38 | public (android.content.Context, android.util.AttributeSet, int); 39 | public void set*(***); 40 | public *** set*(***); 41 | public *** get*(***); 42 | public *** get*(); 43 | } 44 | -keep class android.support.annotation.Keep 45 | -keep @android.support.annotation.Keep class * {*;} 46 | -keepclasseswithmembers class * { 47 | @android.support.annotation.Keep ; 48 | } 49 | -keepclasseswithmembers class * { 50 | @android.support.annotation.Keep ; 51 | } 52 | -keepclasseswithmembers class * { 53 | @android.support.annotation.Keep (...); 54 | } 55 | -keep public class * implements android.os.Parcelable{*;} 56 | -keepclasseswithmembers class * implements android.os.Parcelable { 57 | public static final android.os.Parcelable$Creator *; 58 | } 59 | -keep public class android.support.v7.widget.SearchView{*;} 60 | -keep public class * extends android.support.v4.view.ActionProvider{*;} -------------------------------------------------------------------------------- /sample/src/main/assets/android.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanzhenjie/AndPermission/00bedd6a3a939ce6dab22885723699025c63377b/sample/src/main/assets/android.apk -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/App.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample; 17 | 18 | import android.app.Application; 19 | import android.view.View; 20 | 21 | import com.yanzhenjie.permission.sample.widget.AlertWindow; 22 | import com.yanzhenjie.permission.sample.widget.LauncherView; 23 | 24 | /** 25 | * Created by Zhenjie Yan on 2018/5/30. 26 | */ 27 | public class App extends Application { 28 | 29 | private static App _instance; 30 | 31 | @Override 32 | public void onCreate() { 33 | super.onCreate(); 34 | _instance = this; 35 | } 36 | 37 | public static App get() { 38 | return _instance; 39 | } 40 | 41 | public void showLauncherView() { 42 | final AlertWindow alertWindow = new AlertWindow(this); 43 | LauncherView view = new LauncherView(this); 44 | view.setCancelClickListener(new View.OnClickListener() { 45 | @Override 46 | public void onClick(View v) { 47 | alertWindow.dismiss(); 48 | } 49 | }); 50 | alertWindow.setContentView(view); 51 | alertWindow.show(); 52 | } 53 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/InstallRationale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample; 17 | 18 | import android.app.AlertDialog; 19 | import android.content.Context; 20 | import android.content.DialogInterface; 21 | 22 | import com.yanzhenjie.permission.Rationale; 23 | import com.yanzhenjie.permission.RequestExecutor; 24 | 25 | import java.io.File; 26 | 27 | /** 28 | * Created by Zhenjie Yan on 2018/4/29. 29 | */ 30 | public class InstallRationale implements Rationale { 31 | 32 | @Override 33 | public void showRationale(Context context, File data, final RequestExecutor executor) { 34 | new AlertDialog.Builder(context).setCancelable(false) 35 | .setTitle(R.string.title_dialog) 36 | .setMessage(R.string.message_install_failed) 37 | .setPositiveButton(R.string.setting, new DialogInterface.OnClickListener() { 38 | @Override 39 | public void onClick(DialogInterface dialog, int which) { 40 | executor.execute(); 41 | } 42 | }) 43 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 44 | @Override 45 | public void onClick(DialogInterface dialog, int which) { 46 | executor.cancel(); 47 | } 48 | }) 49 | .show(); 50 | } 51 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/NotifyListenerRationale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample; 17 | 18 | import android.app.AlertDialog; 19 | import android.content.Context; 20 | import android.content.DialogInterface; 21 | 22 | import com.yanzhenjie.permission.Rationale; 23 | import com.yanzhenjie.permission.RequestExecutor; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/5/30. 27 | */ 28 | public class NotifyListenerRationale implements Rationale { 29 | 30 | @Override 31 | public void showRationale(Context context, Void data, final RequestExecutor executor) { 32 | new AlertDialog.Builder(context).setCancelable(false) 33 | .setTitle(R.string.title_dialog) 34 | .setMessage(R.string.message_notification_listener_rationale) 35 | .setPositiveButton(R.string.setting, new DialogInterface.OnClickListener() { 36 | @Override 37 | public void onClick(DialogInterface dialog, int which) { 38 | executor.execute(); 39 | } 40 | }) 41 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 42 | @Override 43 | public void onClick(DialogInterface dialog, int which) { 44 | executor.cancel(); 45 | } 46 | }) 47 | .show(); 48 | } 49 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/NotifyRationale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample; 17 | 18 | import android.app.AlertDialog; 19 | import android.content.Context; 20 | import android.content.DialogInterface; 21 | 22 | import com.yanzhenjie.permission.Rationale; 23 | import com.yanzhenjie.permission.RequestExecutor; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/5/30. 27 | */ 28 | public class NotifyRationale implements Rationale { 29 | 30 | @Override 31 | public void showRationale(Context context, Void data, final RequestExecutor executor) { 32 | new AlertDialog.Builder(context).setCancelable(false) 33 | .setTitle(R.string.title_dialog) 34 | .setMessage(R.string.message_notification_rationale) 35 | .setPositiveButton(R.string.setting, new DialogInterface.OnClickListener() { 36 | @Override 37 | public void onClick(DialogInterface dialog, int which) { 38 | executor.execute(); 39 | } 40 | }) 41 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 42 | @Override 43 | public void onClick(DialogInterface dialog, int which) { 44 | executor.cancel(); 45 | } 46 | }) 47 | .show(); 48 | } 49 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/OverlayRationale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample; 17 | 18 | import android.app.AlertDialog; 19 | import android.content.Context; 20 | import android.content.DialogInterface; 21 | 22 | import com.yanzhenjie.permission.Rationale; 23 | import com.yanzhenjie.permission.RequestExecutor; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/5/30. 27 | */ 28 | public class OverlayRationale implements Rationale { 29 | 30 | @Override 31 | public void showRationale(Context context, Void data, final RequestExecutor executor) { 32 | new AlertDialog.Builder(context).setCancelable(false) 33 | .setTitle(R.string.title_dialog) 34 | .setMessage(R.string.message_overlay_failed) 35 | .setPositiveButton(R.string.setting, new DialogInterface.OnClickListener() { 36 | @Override 37 | public void onClick(DialogInterface dialog, int which) { 38 | executor.execute(); 39 | } 40 | }) 41 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 42 | @Override 43 | public void onClick(DialogInterface dialog, int which) { 44 | executor.cancel(); 45 | } 46 | }) 47 | .show(); 48 | } 49 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/RuntimeRationale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample; 17 | 18 | import android.app.AlertDialog; 19 | import android.content.Context; 20 | import android.content.DialogInterface; 21 | import android.text.TextUtils; 22 | 23 | import com.yanzhenjie.permission.Rationale; 24 | import com.yanzhenjie.permission.RequestExecutor; 25 | import com.yanzhenjie.permission.runtime.Permission; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Created by Zhenjie Yan on 2018/1/1. 31 | */ 32 | public final class RuntimeRationale implements Rationale> { 33 | 34 | @Override 35 | public void showRationale(Context context, List permissions, final RequestExecutor executor) { 36 | List permissionNames = Permission.transformText(context, permissions); 37 | String message = context.getString(R.string.message_permission_rationale, 38 | TextUtils.join("\n", permissionNames)); 39 | 40 | new AlertDialog.Builder(context).setCancelable(false) 41 | .setTitle(R.string.title_dialog) 42 | .setMessage(message) 43 | .setPositiveButton(R.string.resume, new DialogInterface.OnClickListener() { 44 | @Override 45 | public void onClick(DialogInterface dialog, int which) { 46 | executor.execute(); 47 | } 48 | }) 49 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 50 | @Override 51 | public void onClick(DialogInterface dialog, int which) { 52 | executor.cancel(); 53 | } 54 | }) 55 | .show(); 56 | } 57 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/WriteSettingRationale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample; 17 | 18 | import android.app.AlertDialog; 19 | import android.content.Context; 20 | import android.content.DialogInterface; 21 | 22 | import com.yanzhenjie.permission.Rationale; 23 | import com.yanzhenjie.permission.RequestExecutor; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 3/1/19. 27 | */ 28 | public class WriteSettingRationale implements Rationale { 29 | 30 | @Override 31 | public void showRationale(Context context, Void data, final RequestExecutor executor) { 32 | new AlertDialog.Builder(context).setCancelable(false) 33 | .setTitle(R.string.title_dialog) 34 | .setMessage(R.string.message_write_setting_failed) 35 | .setPositiveButton(R.string.setting, new DialogInterface.OnClickListener() { 36 | @Override 37 | public void onClick(DialogInterface dialog, int which) { 38 | executor.execute(); 39 | } 40 | }) 41 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 42 | @Override 43 | public void onClick(DialogInterface dialog, int which) { 44 | executor.cancel(); 45 | } 46 | }) 47 | .show(); 48 | } 49 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/app/NotifyListenerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample.app; 17 | 18 | import android.os.Build; 19 | import android.service.notification.NotificationListenerService; 20 | import android.service.notification.StatusBarNotification; 21 | 22 | import androidx.annotation.RequiresApi; 23 | 24 | /** 25 | * Created by Zhenjie Yan on 2/14/19. 26 | */ 27 | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 28 | public class NotifyListenerService extends NotificationListenerService { 29 | 30 | @Override 31 | public void onNotificationPosted(StatusBarNotification sbn) { 32 | } 33 | 34 | @Override 35 | public void onNotificationRemoved(StatusBarNotification sbn) { 36 | } 37 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/util/FileUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample.util; 17 | 18 | import android.content.Context; 19 | import android.os.Environment; 20 | import android.text.TextUtils; 21 | 22 | import androidx.annotation.Nullable; 23 | 24 | import java.io.File; 25 | 26 | /** 27 | * Created Zhenjie Yan on 2019-10-10. 28 | */ 29 | public class FileUtils { 30 | 31 | public static File getFileDir(Context context) { 32 | return getFileDir(context, null); 33 | } 34 | 35 | public static File getFileDir(Context context, @Nullable String type) { 36 | File root = context.getFilesDir(); 37 | if (TextUtils.isEmpty(type)) { 38 | return root; 39 | } else { 40 | File dir = new File(root, type); 41 | createDir(dir); 42 | return dir; 43 | } 44 | } 45 | 46 | public static boolean externalAvailable() { 47 | return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); 48 | } 49 | 50 | public static File getExternalDir(Context context) { 51 | return getExternalDir(context, null); 52 | } 53 | 54 | public static File getExternalDir(Context context, @Nullable String type) { 55 | if (externalAvailable()) { 56 | if (TextUtils.isEmpty(type)) { 57 | return context.getExternalFilesDir(null); 58 | } 59 | 60 | File dir = context.getExternalFilesDir(type); 61 | if (dir == null) { 62 | dir = context.getExternalFilesDir(null); 63 | dir = new File(dir, type); 64 | createDir(dir); 65 | } 66 | 67 | return dir; 68 | } 69 | throw new RuntimeException("External storage device is not available."); 70 | } 71 | 72 | public static File getRootDir() { 73 | return getRootDir(null); 74 | } 75 | 76 | public static File getRootDir(@Nullable String type) { 77 | if (externalAvailable()) { 78 | File root = Environment.getExternalStorageDirectory(); 79 | File appRoot = new File(root, "AndPermission"); 80 | createDir(appRoot); 81 | 82 | if (TextUtils.isEmpty(type)) { 83 | return appRoot; 84 | } 85 | 86 | File dir = new File(appRoot, type); 87 | createDir(dir); 88 | 89 | return dir; 90 | } 91 | throw new RuntimeException("External storage device is not available."); 92 | } 93 | 94 | public static void createDir(File dir) { 95 | if (dir.exists()) { 96 | if (!dir.isDirectory()) { 97 | dir.delete(); 98 | } 99 | } 100 | if (!dir.exists()) { 101 | dir.mkdirs(); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/util/IOUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample.util; 17 | 18 | import java.io.Closeable; 19 | import java.io.Flushable; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.OutputStream; 23 | 24 | /** 25 | * Created Zhenjie Yan on 2019-10-10. 26 | */ 27 | public class IOUtils { 28 | 29 | public static void write(InputStream in, OutputStream out) throws IOException { 30 | byte[] buffer = new byte[2048]; 31 | int len; 32 | while ((len = in.read(buffer)) != -1) { 33 | out.write(buffer, 0, len); 34 | out.flush(); 35 | } 36 | } 37 | 38 | public static void close(Closeable closeable) { 39 | try { 40 | closeable.close(); 41 | } catch (IOException e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | public static void flush(Flushable flushable) { 47 | try { 48 | flushable.flush(); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /sample/src/main/java/com/yanzhenjie/permission/sample/widget/LauncherView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.yanzhenjie.permission.sample.widget; 17 | 18 | import android.content.Context; 19 | import android.util.AttributeSet; 20 | import android.view.View; 21 | import android.widget.RelativeLayout; 22 | 23 | import com.yanzhenjie.permission.sample.R; 24 | 25 | /** 26 | * Created by Zhenjie Yan on 2018/5/30. 27 | */ 28 | public class LauncherView extends RelativeLayout implements View.OnClickListener { 29 | 30 | private View.OnClickListener mCancelClickListener; 31 | 32 | public LauncherView(Context context) { 33 | this(context, null, 0); 34 | } 35 | 36 | public LauncherView(Context context, AttributeSet attrs) { 37 | this(context, attrs, 0); 38 | } 39 | 40 | public LauncherView(Context context, AttributeSet attrs, int defStyleAttr) { 41 | super(context, attrs, defStyleAttr); 42 | inflate(context, R.layout.window_launcher, this); 43 | findViewById(R.id.btn_cancel).setOnClickListener(this); 44 | } 45 | 46 | @Override 47 | public void onClick(View v) { 48 | int id = v.getId(); 49 | switch (id) { 50 | case R.id.btn_cancel: { 51 | if (mCancelClickListener != null) { 52 | mCancelClickListener.onClick(v); 53 | } 54 | break; 55 | } 56 | } 57 | } 58 | 59 | public void setCancelClickListener(OnClickListener cancelClickListener) { 60 | this.mCancelClickListener = cancelClickListener; 61 | } 62 | } -------------------------------------------------------------------------------- /sample/src/main/res/layout/window_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 23 | 24 | 31 | 32 | 39 | 40 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanzhenjie/AndPermission/00bedd6a3a939ce6dab22885723699025c63377b/sample/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanzhenjie/AndPermission/00bedd6a3a939ce6dab22885723699025c63377b/sample/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanzhenjie/AndPermission/00bedd6a3a939ce6dab22885723699025c63377b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanzhenjie/AndPermission/00bedd6a3a939ce6dab22885723699025c63377b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yanzhenjie/AndPermission/00bedd6a3a939ce6dab22885723699025c63377b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/values/array_string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | Read_Calendar 21 | Write_Calendar 22 | All 23 | 24 | 25 | 26 | Read_Contacts 27 | Write_Contacts 28 | Get_Accounts 29 | All 30 | 31 | 32 | 33 | Fine Location 34 | Coarse Location 35 | All 36 | 37 | 38 | 39 | Read_Phone_State 40 | Call_Phone 41 | Read_Phone_Numbers 42 | Answer_Phone_Calls 43 | Use_Sip 44 | Add_Voicemail 45 | All 46 | 47 | 48 | 49 | Read_Call_Log 50 | Write_Call_Log 51 | Process_Outgoing_Calls 52 | All 53 | 54 | 55 | 56 | Send_SMS 57 | Receive_SMS 58 | Read_SMS 59 | Receive_Wap_Push 60 | Receive_MMS 61 | All 62 | 63 | 64 | 65 | Read_External_Storage 66 | Write_External_Storage 67 | All 68 | 69 | -------------------------------------------------------------------------------- /sample/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | #3F51B5 19 | #303F9F 20 | #FF4081 21 | 22 | #FFF 23 | 24 | -------------------------------------------------------------------------------- /sample/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 1dp 19 | 10dp 20 | 20dp 21 | 100dp 22 | 120dp 23 | 150dp 24 | 25 | 14sp 26 | 16sp 27 | 18sp 28 | 20sp 29 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | AndPermission 20 | 21 | Setting 22 | Resume 23 | Cancel 24 | @android:string/ok 25 | 26 | Successful 27 | Failure 28 | 29 | Camera 30 | Contact 31 | Location 32 | 33 | Calendar 34 | Microphone 35 | Storage 36 | 37 | Phone 38 | Call Log 39 | Activity Recognition 40 | Sensors 41 | SMS 42 | Permission Setting 43 | 44 | Notification 45 | Notification Listener 46 | 47 | Install Apk 48 | AlertWindow 49 | 50 | Write System Setting 51 | 52 | Tips 53 | Grant the following permissions to continue the program:\n\n%1$s 54 | Please give us permission in the settings:\n\n%1$s 55 | The user comes back from the settings page. 56 | 57 | Your device does not allow us to pop up notifications. 58 | Your device does not allow us to access notifications. 59 | 60 | Your device is not allowed us to install apps. 61 | 62 | Your device is not allowed us to draw on other applications. 63 | 64 | Your device is not allowed us to modify the system settings. 65 | 66 | Please check the external storage device. 67 | External storage device is not available. 68 | 69 | Save failed, please try again. 70 | 71 | -------------------------------------------------------------------------------- /sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 30 | 31 | 35 | 36 | 39 | 40 | 44 | 45 | 49 | 50 | 56 | 57 | 60 | 61 | 64 | 65 | 71 | 72 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':permission', ':sample' --------------------------------------------------------------------------------