Skip to content

Commit 764d99b

Browse files
author
Shintaro Katafuchi
committed
Merge pull request #9 from hotchemi/multiple_permissions
Add multiple permissions.
2 parents 0659239 + 2a509c5 commit 764d99b

File tree

22 files changed

+644
-206
lines changed

22 files changed

+644
-206
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ android:
1212
- extra-google-m2repository
1313

1414
jdk:
15-
- oraclejdk7
1615
- oraclejdk8
1716

1817
branches:

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# ChangeLog
22

3+
- 1.1.0 2015/08/24
4+
- Add `@NeedsPermissions` and `@ShowRationales`.
35
- 1.0.1 2015/08/20
46
- Stop calling rationale methods in the OnRequestPermissionsResult.
57
- 1.0.0 2015/08/19

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
[ ![Download](https://api.bintray.com/packages/hotchemi/maven/permissionsdispatcher/images/download.svg) ](https://bintray.com/hotchemi/maven/permissionsdispatcher/_latestVersion)
55
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-PermissionsDispatcher-green.svg?style=flat)](https://android-arsenal.com/details/1/2316)
66

7-
PermissionsDispatcher provides simple annotation-based API to handle runtime permissions in Android M.
7+
PermissionsDispatcher provides simple annotation-based API to handle runtime permissions in Marshmallow.
88

9-
[Runtime permissions](https://developer.android.com/preview/features/runtime-permissions.html) is so great for users but also the hell for developers. Actually I don't want to write such a complicated [code](https://github.com/googlesamples/android-RuntimePermissions/blob/master/Application/src/main/java/com/example/android/system/runtimepermissions/MainActivity.java) anymore.
9+
[Runtime permissions](https://developer.android.com/preview/features/runtime-permissions.html) is so great for users but also the hell for developers.
1010

1111
You can be released from the burden that writing a bunch of check statements whether a permission have been granted or not.
1212

@@ -16,11 +16,13 @@ Here's a minimum example that you register `MainActivity` which requires `Manife
1616

1717
### 1. Attach annotations
1818

19-
There are only 3 annotations.
19+
There are only few annotations.
2020

2121
- `@RuntimePermissions`: [Must] Register an Activity or Fragment to handle permissions.
2222
- `@NeedsPermission`: [Must] Register a method which the permission is needed.
23+
- You can use `@NeedsPermissions` for multiple requests.
2324
- `@ShowsRationale`: [Option] Register a method which explains why the permission is needed. Actually an annotated method is called when `shouldShowRequestPermissionRationale` returns true or when uer deny a permission.
25+
- You can use `@ShowsRationales` for multiple requests.
2426

2527
> NOTE: Annotated methods must be package private or above.
2628
@@ -103,8 +105,8 @@ buildscript {
103105
apply plugin: 'android-apt'
104106
105107
dependencies {
106-
compile 'com.github.hotchemi:permissionsdispatcher:1.0.1'
107-
apt 'com.github.hotchemi:permissionsdispatcher-processor:1.0.1'
108+
compile 'com.github.hotchemi:permissionsdispatcher:1.1.0'
109+
apt 'com.github.hotchemi:permissionsdispatcher-processor:1.1.0'
108110
}
109111
```
110112

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ USER = hotchemi
22
GROUP_ID = com.github.hotchemi
33
ARTIFACT_ID_CORE = permissionsdispatcher
44
ARTIFACT_ID_PROCESSOR = permissionsdispatcher-processor
5-
VERSION = 1.0.1
5+
VERSION = 1.1.0
66
DESCRIPTION = Annotation-based library for generating runtime permissions dispatcher.
77
WEBSITE = https://github.com/hotchemi/PermissionsDispatcher
88
LICENCES = ['Apache-2.0']

permissionsdispatcher-processor/build.gradle

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import org.gradle.internal.jvm.Jvm
2+
13
apply plugin: "java"
24
apply plugin: 'com.novoda.bintray-release'
35

4-
targetCompatibility = JavaVersion.VERSION_1_7
5-
sourceCompatibility = JavaVersion.VERSION_1_7
6+
targetCompatibility = JavaVersion.VERSION_1_8
7+
sourceCompatibility = JavaVersion.VERSION_1_8
68

79
sourceSets {
810
main {
@@ -20,7 +22,7 @@ dependencies {
2022
testCompile 'org.mockito:mockito-core:1.10.19'
2123
testCompile 'com.google.testing.compile:compile-testing:0.6'
2224
testCompile 'com.google.android:android:4.1.1.4'
23-
testCompile files(org.gradle.internal.jvm.Jvm.current().getToolsJar())
25+
testCompile files(Jvm.current().getToolsJar())
2426
// FIXME: there are support v4 and core module jar but it is dirty hack
2527
testCompile fileTree(dir: './src/test/libs', includes: ['*.jar'])
2628
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package permissions.dispatcher.processor;
22

3-
public enum ClassType {
3+
enum ClassType {
44
ACTIVITY("target"),
55
FRAGMENT("target.getActivity()");
66

@@ -10,10 +10,6 @@ public enum ClassType {
1010
this.activity = activity;
1111
}
1212

13-
public String getActivity() {
14-
return activity;
15-
}
16-
1713
static ClassType getClassType(String className) {
1814
if (className.endsWith("Activity")) {
1915
return ACTIVITY;
@@ -22,4 +18,8 @@ static ClassType getClassType(String className) {
2218
}
2319
return null;
2420
}
25-
}
21+
22+
public String getActivity() {
23+
return activity;
24+
}
25+
}

permissionsdispatcher-processor/src/main/java/permissions/dispatcher/processor/ConstantsProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
interface ConstantsProvider {
66

77
ClassName ACTIVITY_COMPAT = ClassName.get("android.support.v4.app", "ActivityCompat");
8-
ClassName PERMISSION_UTIL = ClassName.get("permissions.dispatcher", "PermissionUtils");
8+
ClassName PERMISSION_UTILS = ClassName.get("permissions.dispatcher", "PermissionUtils");
99
String CLASS_SUFFIX = "PermissionsDispatcher";
1010
String METHOD_SUFFIX = "WithCheck";
1111
String FIELD_PREFIX = "REQUEST_";

permissionsdispatcher-processor/src/main/java/permissions/dispatcher/processor/JavaFileBuilder.java

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,58 @@
11
package permissions.dispatcher.processor;
22

3-
import com.squareup.javapoet.ClassName;
4-
import com.squareup.javapoet.FieldSpec;
5-
import com.squareup.javapoet.JavaFile;
6-
import com.squareup.javapoet.MethodSpec;
7-
import com.squareup.javapoet.TypeSpec;
8-
9-
import java.util.ArrayList;
10-
import java.util.List;
3+
import com.squareup.javapoet.*;
4+
import permissions.dispatcher.NeedsPermission;
5+
import permissions.dispatcher.NeedsPermissions;
116

127
import javax.lang.model.element.ExecutableElement;
138
import javax.lang.model.element.Modifier;
9+
import java.util.ArrayList;
10+
import java.util.List;
1411

15-
import permissions.dispatcher.NeedsPermission;
16-
17-
import static permissions.dispatcher.processor.ConstantsProvider.ACTIVITY_COMPAT;
18-
import static permissions.dispatcher.processor.ConstantsProvider.METHOD_SUFFIX;
19-
import static permissions.dispatcher.processor.ConstantsProvider.PERMISSION_UTIL;
12+
import static permissions.dispatcher.processor.ConstantsProvider.*;
2013
import static permissions.dispatcher.processor.Utils.getFieldName;
2114

2215
final class JavaFileBuilder {
2316

24-
private JavaFileBuilder() {
25-
}
26-
2717
private static MethodSpec createConstructor() {
2818
return MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build();
2919
}
3020

31-
private static List<MethodSpec> createMethodsWithCheck(RuntimePermissionsAnnotatedElement clazz) {
21+
private static List<MethodSpec> createNeedsPermissionMethods(RuntimePermissionsAnnotatedElement clazz) {
3222
List<MethodSpec> methodSpecs = new ArrayList<>();
3323
List<ExecutableElement> elements = clazz.getNeedsPermissionMethods();
3424
for (ExecutableElement element : elements) {
3525
String value = element.getAnnotation(NeedsPermission.class).value();
36-
ExecutableElement showsRationale = clazz.getShowsRationaleMethodFromValue(value);
37-
methodSpecs.add(createMethodWithCheck(clazz.getClassType(), clazz.getClassName(), element, showsRationale));
26+
ExecutableElement showsRationale = clazz.getShowsRationaleFromValue(value);
27+
String activity = clazz.getClassType().getActivity();
28+
methodSpecs.add(createNeedsPermissionMethod(activity, clazz.getClassName(), element, showsRationale));
3829
}
3930
return methodSpecs;
4031
}
4132

42-
private static MethodSpec createMethodWithCheck(ClassType classType, ClassName target, ExecutableElement needsPermission, ExecutableElement showsRationale) {
33+
private static List<MethodSpec> createNeedsPermissionsMethods(RuntimePermissionsAnnotatedElement clazz) {
34+
List<MethodSpec> methodSpecs = new ArrayList<>();
35+
List<ExecutableElement> elements = clazz.getNeedsPermissionsMethods();
36+
for (ExecutableElement element : elements) {
37+
String[] value = element.getAnnotation(NeedsPermissions.class).value();
38+
ExecutableElement showsRationale = clazz.getShowsRationaleFromValue(value);
39+
String activity = clazz.getClassType().getActivity();
40+
methodSpecs.add(createNeedsPermissionsMethod(activity, clazz.getClassName(), element, showsRationale));
41+
}
42+
return methodSpecs;
43+
}
44+
45+
private static MethodSpec createNeedsPermissionMethod(String activity, ClassName target, ExecutableElement needsPermission, ExecutableElement showsRationale) {
4346
String methodName = needsPermission.getSimpleName().toString();
4447
String value = needsPermission.getAnnotation(NeedsPermission.class).value();
45-
String activity = classType.getActivity();
4648
MethodSpec.Builder
4749
methodBuilder = MethodSpec.methodBuilder(methodName + METHOD_SUFFIX)
4850
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
4951
.returns(void.class)
5052
.addParameter(target, "target")
51-
.beginControlFlow("if ($T.hasSelfPermissions($N, $S))", PERMISSION_UTIL, activity, value)
53+
.beginControlFlow("if ($T.hasSelfPermissions($N, $S))", PERMISSION_UTILS, activity, value)
5254
.addStatement("target.$N()", methodName)
5355
.nextControlFlow("else");
54-
5556
if (showsRationale != null) {
5657
methodBuilder.beginControlFlow("if ($T.shouldShowRequestPermissionRationale($N, $S))",
5758
ACTIVITY_COMPAT, activity, value)
@@ -64,6 +65,30 @@ ACTIVITY_COMPAT, activity, value, getFieldName(methodName))
6465
.build();
6566
}
6667

68+
private static MethodSpec createNeedsPermissionsMethod(String activity, ClassName target, ExecutableElement needsPermission, ExecutableElement showsRationale) {
69+
String methodName = needsPermission.getSimpleName().toString();
70+
String[] value = needsPermission.getAnnotation(NeedsPermissions.class).value();
71+
String array = "new String[]" + Utils.toString(value);
72+
MethodSpec.Builder
73+
methodBuilder = MethodSpec.methodBuilder(methodName + METHOD_SUFFIX)
74+
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
75+
.returns(void.class)
76+
.addParameter(target, "target")
77+
.beginControlFlow("if ($T.hasSelfPermissions($N, $L))", PERMISSION_UTILS, activity, array)
78+
.addStatement("target.$N()", methodName)
79+
.nextControlFlow("else");
80+
if (showsRationale != null) {
81+
methodBuilder.beginControlFlow("if ($T.shouldShowRequestPermissionRationale($N, $L))",
82+
PERMISSION_UTILS, activity, array)
83+
.addStatement("target.$N()", showsRationale.getSimpleName())
84+
.endControlFlow();
85+
}
86+
return methodBuilder.addStatement("$T.requestPermissions($N, $L, $N)",
87+
ACTIVITY_COMPAT, activity, array, getFieldName(methodName))
88+
.endControlFlow()
89+
.build();
90+
}
91+
6792
private static MethodSpec createOnRequestPermissionsResult(ClassName target, List<ExecutableElement> methods) {
6893
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("onRequestPermissionsResult")
6994
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
@@ -73,12 +98,11 @@ private static MethodSpec createOnRequestPermissionsResult(ClassName target, Lis
7398
.addParameter(int[].class, "grantResults")
7499
.returns(void.class)
75100
.beginControlFlow("switch (requestCode)");
76-
77101
for (ExecutableElement method : methods) {
78102
String methodName = method.getSimpleName().toString();
79103
methodBuilder
80104
.addCode("case $N:\n", getFieldName(methodName))
81-
.beginControlFlow("if ($T.verifyPermissions(grantResults))", PERMISSION_UTIL)
105+
.beginControlFlow("if ($T.verifyPermissions(grantResults))", PERMISSION_UTILS)
82106
.addStatement("target.$N()", methodName)
83107
.endControlFlow()
84108
.addStatement("break");
@@ -106,15 +130,24 @@ private static FieldSpec createField(String name, int index) {
106130
.build();
107131
}
108132

109-
public static JavaFile createJavaFile(RuntimePermissionsAnnotatedElement element) {
110-
List<ExecutableElement> needsPermissionMethods = element.getNeedsPermissionMethods();
111-
TypeSpec clazz = TypeSpec.classBuilder(element.getDispatchClassName())
133+
static JavaFile createJavaFile(RuntimePermissionsAnnotatedElement element) {
134+
List<ExecutableElement> permissionsMethods = new ArrayList<ExecutableElement>() {
135+
{
136+
addAll(element.getNeedsPermissionMethods());
137+
}
138+
139+
{
140+
addAll(element.getNeedsPermissionsMethods());
141+
}
142+
};
143+
TypeSpec clazz = TypeSpec.classBuilder(element.getDispatcherClassName())
112144
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
113-
.addFields(createFields(needsPermissionMethods))
145+
.addFields(createFields(permissionsMethods))
114146
.addMethod(createConstructor())
115-
.addMethods(createMethodsWithCheck(element))
116-
.addMethod(createOnRequestPermissionsResult(element.getClassName(), needsPermissionMethods))
117-
.build();
147+
.addMethods(createNeedsPermissionMethods(element))
148+
.addMethods(createNeedsPermissionsMethods(element))
149+
.addMethod(createOnRequestPermissionsResult(element.getClassName(), permissionsMethods))
150+
.build();
118151
String packageName = element.getPackageName();
119152
return JavaFile.builder(packageName, clazz).build();
120153
}

permissionsdispatcher-processor/src/main/java/permissions/dispatcher/processor/PermissionsProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,4 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
6161
return true;
6262
}
6363

64-
}
64+
}

0 commit comments

Comments
 (0)