18
18
import android .annotation .TargetApi ;
19
19
import android .app .Activity ;
20
20
import android .content .Context ;
21
- import android .content .DialogInterface ;
22
- import android .content .Intent ;
23
21
import android .content .pm .PackageManager ;
24
- import android .net .Uri ;
25
22
import android .os .Build ;
26
- import android .provider . Settings ;
23
+ import android .support . annotation . NonNull ;
27
24
import android .support .annotation .Nullable ;
28
25
import android .support .annotation .StringRes ;
29
26
import android .support .v4 .app .ActivityCompat ;
30
27
import android .support .v4 .app .Fragment ;
31
28
import android .support .v4 .content .ContextCompat ;
32
- import android .support .v7 .app .AlertDialog ;
29
+ import android .support .v7 .app .AppCompatActivity ;
33
30
import android .util .Log ;
34
31
35
32
import java .lang .reflect .InvocationTargetException ;
36
33
import java .lang .reflect .Method ;
37
34
import java .util .ArrayList ;
38
- import java .util .Arrays ;
39
35
import java .util .List ;
40
36
41
37
/**
44
40
public class EasyPermissions {
45
41
46
42
private static final String TAG = "EasyPermissions" ;
43
+ private static final String DIALOG_TAG = "RationaleDialogFragment" ;
44
+
47
45
48
46
public interface PermissionCallbacks extends
49
47
ActivityCompat .OnRequestPermissionsResultCallback {
@@ -57,12 +55,13 @@ public interface PermissionCallbacks extends
57
55
/**
58
56
* Check if the calling context has a set of permissions.
59
57
*
60
- * @param context the calling context.
61
- * @param perms one ore more permissions, such as {@code android.Manifest.permission.CAMERA}.
62
- * @return true if all permissions are already granted, false if at least one permission
63
- * is not yet granted.
58
+ * @param context
59
+ * the calling context.
60
+ * @param perms
61
+ * one ore more permissions, such as {@code android.Manifest.permission.CAMERA}.
62
+ * @return true if all permissions are already granted, false if at least one permission is not yet granted.
64
63
*/
65
- public static boolean hasPermissions (Context context , String ... perms ) {
64
+ public static boolean hasPermissions (@ NonNull Context context , @ NonNull String ... perms ) {
66
65
// Always return true for SDK < M, let the system deal with the permissions
67
66
if (Build .VERSION .SDK_INT < Build .VERSION_CODES .M ) {
68
67
Log .w (TAG , "hasPermissions: API version < M, returning true by default" );
@@ -83,17 +82,20 @@ public static boolean hasPermissions(Context context, String... perms) {
83
82
/**
84
83
* Request a set of permissions, showing rationale if the system requests it.
85
84
*
86
- * @param object Activity or Fragment requesting permissions. Should implement
87
- * {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
88
- * or
89
- * {@link android.support.v13.app.FragmentCompat.OnRequestPermissionsResultCallback}
90
- * @param rationale a message explaining why the application needs this set of permissions, will
91
- * be displayed if the user rejects the request the first time.
92
- * @param requestCode request code to track this request, must be < 256.
93
- * @param perms a set of permissions to be requested.
85
+ * @param object
86
+ * Activity or Fragment requesting permissions. Should implement
87
+ * {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
88
+ * or {@link android.support.v13.app.FragmentCompat.OnRequestPermissionsResultCallback}
89
+ * @param rationale
90
+ * a message explaining why the application needs this set of permissions, will be displayed if the user rejects the request the first
91
+ * time.
92
+ * @param requestCode
93
+ * request code to track this request, must be < 256.
94
+ * @param perms
95
+ * a set of permissions to be requested.
94
96
*/
95
- public static void requestPermissions (final Object object , String rationale ,
96
- final int requestCode , final String ... perms ) {
97
+ public static void requestPermissions (@ NonNull final Object object , @ NonNull String rationale ,
98
+ final int requestCode , @ NonNull final String ... perms ) {
97
99
requestPermissions (object , rationale ,
98
100
android .R .string .ok ,
99
101
android .R .string .cancel ,
@@ -103,21 +105,25 @@ public static void requestPermissions(final Object object, String rationale,
103
105
/**
104
106
* Request a set of permissions, showing rationale if the system requests it.
105
107
*
106
- * @param object Activity or Fragment requesting permissions. Should implement
107
- * {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
108
- * or
109
- * {@link android.support.v13.app.FragmentCompat.OnRequestPermissionsResultCallback}
110
- * @param rationale a message explaining why the application needs this set of permissions, will
111
- * be displayed if the user rejects the request the first time.
112
- * @param positiveButton custom text for positive button
113
- * @param negativeButton custom text for negative button
114
- * @param requestCode request code to track this request, must be < 256.
115
- * @param perms a set of permissions to be requested.
108
+ * @param object
109
+ * Activity or Fragment requesting permissions. Should implement
110
+ * {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
111
+ * or {@link android.support.v13.app.FragmentCompat.OnRequestPermissionsResultCallback}
112
+ * @param rationale
113
+ * a message explaining why the application needs this set of permissions, will be displayed if the user rejects the request the first
114
+ * time.
115
+ * @param positiveButton
116
+ * custom text for positive button
117
+ * @param negativeButton
118
+ * custom text for negative button
119
+ * @param requestCode
120
+ * request code to track this request, must be < 256.
121
+ * @param perms
122
+ * a set of permissions to be requested.
116
123
*/
117
- public static void requestPermissions (final Object object , String rationale ,
118
- @ StringRes int positiveButton ,
119
- @ StringRes int negativeButton ,
120
- final int requestCode , final String ... perms ) {
124
+ public static void requestPermissions (@ NonNull final Object object , @ NonNull String rationale ,
125
+ @ StringRes int positiveButton , @ StringRes int negativeButton ,
126
+ final int requestCode , @ NonNull final String ... perms ) {
121
127
122
128
checkCallingObjectSuitability (object );
123
129
@@ -128,45 +134,69 @@ public static void requestPermissions(final Object object, String rationale,
128
134
}
129
135
130
136
if (shouldShowRationale ) {
131
- Activity activity = getActivity (object );
132
- if (null == activity ) {
133
- return ;
137
+ if (object instanceof AppCompatActivity ) {
138
+ showAppCompatRationaleDialog ((AppCompatActivity ) object , requestCode ,
139
+ perms , positiveButton , negativeButton , rationale );
140
+ } else if (object instanceof Activity ) {
141
+ showRationaleDialog ((Activity ) object , requestCode , perms ,
142
+ positiveButton , negativeButton , rationale );
143
+ } else if (object instanceof Fragment ) {
144
+ showAppCompatRationaleDialogByFragment ((Fragment ) object , requestCode , perms ,
145
+ positiveButton , negativeButton , rationale );
146
+ } else if (object instanceof android .app .Fragment ) {
147
+ showRationaleDialogByFragment ((android .app .Fragment ) object , requestCode , perms ,
148
+ positiveButton , negativeButton , rationale );
149
+ } else {
150
+ throw new RuntimeException ("Object is not assigned to either an Activity or Fragment." );
134
151
}
135
-
136
- AlertDialog dialog = new AlertDialog .Builder (activity )
137
- .setMessage (rationale )
138
- .setPositiveButton (positiveButton , new DialogInterface .OnClickListener () {
139
- @ Override
140
- public void onClick (DialogInterface dialog , int which ) {
141
- executePermissionsRequest (object , perms , requestCode );
142
- }
143
- })
144
- .setNegativeButton (negativeButton , new DialogInterface .OnClickListener () {
145
- @ Override
146
- public void onClick (DialogInterface dialog , int which ) {
147
- // act as if the permissions were denied
148
- if (object instanceof PermissionCallbacks ) {
149
- ((PermissionCallbacks ) object ).onPermissionsDenied (requestCode , Arrays .asList (perms ));
150
- }
151
- }
152
- }).create ();
153
- dialog .show ();
154
152
} else {
155
153
executePermissionsRequest (object , perms , requestCode );
156
154
}
157
155
}
158
156
159
157
158
+ @ TargetApi (Build .VERSION_CODES .JELLY_BEAN_MR1 )
159
+ private static void showRationaleDialogByFragment (@ NonNull android .app .Fragment object , int requestCode ,
160
+ @ NonNull String [] perms , @ StringRes int positiveButton ,
161
+ @ StringRes int negativeButton , @ NonNull String rationale ) {
162
+ RationaleDialogFragment .newInstance (positiveButton , negativeButton , rationale , requestCode , perms )
163
+ .show (object .getChildFragmentManager (), DIALOG_TAG );
164
+ }
165
+
166
+ @ TargetApi (Build .VERSION_CODES .JELLY_BEAN_MR1 )
167
+ private static void showRationaleDialog (@ NonNull Activity object , int requestCode ,
168
+ @ NonNull String [] perms , @ StringRes int positiveButton ,
169
+ @ StringRes int negativeButton , @ NonNull String rationale ) {
170
+ RationaleDialogFragment .newInstance (positiveButton , negativeButton , rationale , requestCode , perms )
171
+ .show (object .getFragmentManager (), DIALOG_TAG );
172
+ }
173
+
174
+ private static void showAppCompatRationaleDialogByFragment (@ NonNull Fragment object , int requestCode ,
175
+ @ NonNull String [] perms , @ StringRes int positiveButton ,
176
+ @ StringRes int negativeButton , @ NonNull String rationale ) {
177
+ RationaleAppCompatDialogFragment .newInstance (positiveButton , negativeButton , rationale , requestCode , perms )
178
+ .show (object .getChildFragmentManager (), DIALOG_TAG );
179
+ }
180
+
181
+ private static void showAppCompatRationaleDialog (@ NonNull AppCompatActivity object , int requestCode ,
182
+ @ NonNull String [] perms , @ StringRes int positiveButton ,
183
+ @ StringRes int negativeButton , @ NonNull String rationale ) {
184
+ RationaleAppCompatDialogFragment .newInstance (positiveButton , negativeButton , rationale , requestCode , perms )
185
+ .show (object .getSupportFragmentManager (), DIALOG_TAG );
186
+ }
187
+
188
+
160
189
/**
161
- * Check if at least one permission in the list of denied permissions has been permanently
162
- * denied (user clicked "Never ask again").
163
- * @param object Activity or Fragment requesting permissions.
164
- * @param deniedPermissions list of denied permissions, usually from
165
- * {@link PermissionCallbacks#onPermissionsDenied(int, List)}
190
+ * Check if at least one permission in the list of denied permissions has been permanently denied (user clicked "Never ask again").
191
+ *
192
+ * @param object
193
+ * Activity or Fragment requesting permissions.
194
+ * @param deniedPermissions
195
+ * list of denied permissions, usually from {@link PermissionCallbacks#onPermissionsDenied(int, List)}
166
196
* @return {@code true} if at least one permission in the list was permanently denied.
167
197
*/
168
- public static boolean somePermissionPermanentlyDenied (Object object ,
169
- List <String > deniedPermissions ) {
198
+ public static boolean somePermissionPermanentlyDenied (@ NonNull Object object ,
199
+ @ NonNull List <String > deniedPermissions ) {
170
200
for (String deniedPermission : deniedPermissions ) {
171
201
if (permissionPermanentlyDenied (object , deniedPermission )) {
172
202
return true ;
@@ -179,32 +209,38 @@ public static boolean somePermissionPermanentlyDenied(Object object,
179
209
180
210
/**
181
211
* Check if a permission has been permanently denied (user clicked "Never ask again").
182
- * @param object Activity or Fragment requesting permissions.
183
- * @param deniedPermission denied permission.
212
+ *
213
+ * @param object
214
+ * Activity or Fragment requesting permissions.
215
+ * @param deniedPermission
216
+ * denied permission.
184
217
* @return {@code true} if the permissions has been permanently denied.
185
218
*/
186
- public static boolean permissionPermanentlyDenied (Object object , String deniedPermission ) {
219
+ public static boolean permissionPermanentlyDenied (@ NonNull Object object ,
220
+ @ NonNull String deniedPermission ) {
187
221
return !shouldShowRequestPermissionRationale (object , deniedPermission );
188
222
}
189
223
190
224
191
225
/**
192
- * Handle the result of a permission request, should be called from the calling Activity's
193
- * {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}
194
- * method.
226
+ * Handle the result of a permission request, should be called from the calling Activity's {@link android.support.v4.app.ActivityCompat
227
+ * .OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])} method.
195
228
* <p>
196
- * If any permissions were granted or denied, the {@code object} will receive the appropriate
197
- * callbacks through {@link PermissionCallbacks} and methods annotated with
198
- * {@link AfterPermissionGranted} will be run if appropriate.
229
+ * If any permissions were granted or denied, the {@code object} will receive the appropriate callbacks through {@link PermissionCallbacks} and
230
+ * methods annotated with {@link AfterPermissionGranted} will be run if appropriate.
199
231
*
200
- * @param requestCode requestCode argument to permission result callback.
201
- * @param permissions permissions argument to permission result callback.
202
- * @param grantResults grantResults argument to permission result callback.
203
- * @param receivers an array of objects that have a method annotated with {@link AfterPermissionGranted}
204
- * or implement {@link PermissionCallbacks}.
232
+ * @param requestCode
233
+ * requestCode argument to permission result callback.
234
+ * @param permissions
235
+ * permissions argument to permission result callback.
236
+ * @param grantResults
237
+ * grantResults argument to permission result callback.
238
+ * @param receivers
239
+ * an array of objects that have a method annotated with {@link AfterPermissionGranted} or implement {@link PermissionCallbacks}.
205
240
*/
206
- public static void onRequestPermissionsResult (int requestCode , String [] permissions ,
207
- int [] grantResults , Object ... receivers ) {
241
+ public static void onRequestPermissionsResult (int requestCode , @ NonNull String [] permissions ,
242
+ @ NonNull int [] grantResults ,
243
+ @ NonNull Object ... receivers ) {
208
244
209
245
// Make a collection of granted and denied permissions from the request.
210
246
ArrayList <String > granted = new ArrayList <>();
@@ -243,7 +279,8 @@ public static void onRequestPermissionsResult(int requestCode, String[] permissi
243
279
}
244
280
245
281
@ TargetApi (23 )
246
- private static boolean shouldShowRequestPermissionRationale (Object object , String perm ) {
282
+ private static boolean shouldShowRequestPermissionRationale (@ NonNull Object object ,
283
+ @ NonNull String perm ) {
247
284
if (object instanceof Activity ) {
248
285
return ActivityCompat .shouldShowRequestPermissionRationale ((Activity ) object , perm );
249
286
} else if (object instanceof Fragment ) {
@@ -256,9 +293,8 @@ private static boolean shouldShowRequestPermissionRationale(Object object, Strin
256
293
}
257
294
258
295
@ TargetApi (23 )
259
- private static void executePermissionsRequest (Object object , String [] perms , int requestCode ) {
296
+ static void executePermissionsRequest (@ NonNull Object object , @ NonNull String [] perms , int requestCode ) {
260
297
checkCallingObjectSuitability (object );
261
-
262
298
if (object instanceof Activity ) {
263
299
ActivityCompat .requestPermissions ((Activity ) object , perms , requestCode );
264
300
} else if (object instanceof Fragment ) {
@@ -269,7 +305,7 @@ private static void executePermissionsRequest(Object object, String[] perms, int
269
305
}
270
306
271
307
@ TargetApi (11 )
272
- private static Activity getActivity (Object object ) {
308
+ private static Activity getActivity (@ NonNull Object object ) {
273
309
if (object instanceof Activity ) {
274
310
return ((Activity ) object );
275
311
} else if (object instanceof Fragment ) {
@@ -281,7 +317,7 @@ private static Activity getActivity(Object object) {
281
317
}
282
318
}
283
319
284
- private static void runAnnotatedMethods (Object object , int requestCode ) {
320
+ private static void runAnnotatedMethods (@ NonNull Object object , int requestCode ) {
285
321
Class clazz = object .getClass ();
286
322
if (isUsingAndroidAnnotations (object )) {
287
323
clazz = clazz .getSuperclass ();
@@ -313,13 +349,15 @@ private static void runAnnotatedMethods(Object object, int requestCode) {
313
349
}
314
350
}
315
351
316
- private static void checkCallingObjectSuitability (Object object ) {
352
+ private static void checkCallingObjectSuitability (@ Nullable Object object ) {
353
+ if (object == null ) {
354
+ throw new NullPointerException ("Activity or Fragment should not be null" );
355
+ }
317
356
// Make sure Object is an Activity or Fragment
318
357
boolean isActivity = object instanceof Activity ;
319
358
boolean isSupportFragment = object instanceof Fragment ;
320
359
boolean isAppFragment = object instanceof android .app .Fragment ;
321
360
boolean isMinSdkM = Build .VERSION .SDK_INT >= Build .VERSION_CODES .M ;
322
-
323
361
if (!(isSupportFragment || isActivity || (isAppFragment && isMinSdkM ))) {
324
362
if (isAppFragment ) {
325
363
throw new IllegalArgumentException (
@@ -330,11 +368,10 @@ private static void checkCallingObjectSuitability(Object object) {
330
368
}
331
369
}
332
370
333
- private static boolean isUsingAndroidAnnotations (Object object ) {
371
+ private static boolean isUsingAndroidAnnotations (@ NonNull Object object ) {
334
372
if (!object .getClass ().getSimpleName ().endsWith ("_" )) {
335
373
return false ;
336
374
}
337
-
338
375
try {
339
376
Class clazz = Class .forName ("org.androidannotations.api.view.HasViews" );
340
377
return clazz .isInstance (object );
0 commit comments