getResults() {
236 | if (mResults == null) {
237 | synchronized (EasyPermissionHelper.class) {
238 | if (mResults == null) {
239 | mResults = new SparseArray<>(1);
240 | }
241 | }
242 | }
243 | return mResults;
244 | }
245 |
246 | /**
247 | * Check the current permissions
248 | * 检查当前的权限情况
249 | *
250 | * @param permissions
251 | * @return
252 | */
253 | public boolean hasPermission(@NonNull String... permissions) {
254 | //6.0以上才需要动态检查
255 | // above 6.0, dynamic check is required
256 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
257 | return true;
258 | }
259 | for (String permission : permissions) {
260 | if (ContextCompat.checkSelfPermission(getTopActivity(), permission) != PackageManager.PERMISSION_GRANTED) {
261 | // 只要有一个权限没有被授予, 则直接返回 false
262 | // False is returned as long as a permission is not granted
263 | return false;
264 | }
265 | }
266 | return true;
267 | }
268 |
269 |
270 | /**
271 | * Request permission but no permission result callback is required
272 | * 申请权限但是不需要权限结果回调
273 | *
274 | * @param requestCode 请求回调code
275 | * @param mAlertInfo 提示信息
276 | * @param permissions
277 | * @return
278 | */
279 | protected void requestPermission(int requestCode, PermissionAlertInfo mAlertInfo, @NonNull String... permissions) {
280 | //显示提示信息
281 | showAlert(mAlertInfo);
282 | this.doRequestPermission(requestCode, permissions);
283 | }
284 |
285 |
286 | /**
287 | * Request permission but no permission result callback is required
288 | * 申请权限但是不需要权限结果回调
289 | *
290 | * @param easyPermission
291 | * @return
292 | */
293 | protected void requestPermission(@NonNull EasyPermission easyPermission) {
294 | //更新请求的activity
295 | if(easyPermission.getContext() != null){
296 | updateTopActivity(easyPermission.getContext());
297 | }
298 | // this.mCurrentEasyPermission = easyPermission;
299 | if (easyPermission.getResult() == null) {
300 | //无需回调
301 | requestPermission(easyPermission.getAlertInfo(), easyPermission.getPerms());
302 | } else {
303 | requestPermission(easyPermission.getRequestCode(),
304 | easyPermission.getResult(), easyPermission.getAlertInfo(), easyPermission.getPerms());
305 | }
306 | }
307 |
308 | /**
309 | * Request permission but no permission result callback is required
310 | * 申请权限但是不需要权限结果回调
311 | *
312 | * @param mAlertInfo 提示信息
313 | * @param permissions
314 | * @return
315 | */
316 | protected void requestPermission(PermissionAlertInfo mAlertInfo, @NonNull String... permissions) {
317 | this.requestPermission(REQUESTCODE_DEFAULT, mAlertInfo, permissions);
318 | }
319 |
320 |
321 | /**
322 | * To do request permission
323 | * 执行申请权限
324 | *
325 | * @param requestCode
326 | * @param permissions
327 | * @return
328 | */
329 | protected void doRequestPermission(int requestCode, @NonNull String... permissions) {
330 | ActivityCompat.requestPermissions(getTopActivity(),
331 | permissions, requestCode);
332 | }
333 |
334 | /**
335 | * Requesting permission requires a callback of the permission result
336 | * 申请权限 需要权限结果回调
337 | *
338 | * @param permissions
339 | * @return
340 | */
341 | protected void requestPermission(int requestCode, EasyPermissionResult result, PermissionAlertInfo mAlertInfo, @NonNull String... permissions) {
342 | //保存结果回调
343 | //Save the result callback
344 | if (requestCode != REQUESTCODE_DEFAULT || result != null) {
345 | getResults().append(requestCode, result);
346 | }
347 | this.requestPermission(requestCode, mAlertInfo, permissions);
348 | }
349 |
350 | /**
351 | * 顶部提示框
352 | */
353 | private Dialog alertDialog;
354 |
355 | /**
356 | * Display permission description information
357 | * 权限说明信息展示
358 | */
359 | private void showAlert(PermissionAlertInfo mAlertInfo) {
360 | if (mAlertInfo == null || TextUtils.isEmpty(mAlertInfo.alertMessage)) {
361 | return;
362 | }
363 | //避免弹出多个
364 | if(alertDialog != null && alertDialog.isShowing()){
365 | alertDialog.dismiss();
366 | }
367 | Activity topActivity = getTopActivity();
368 | if(topActivity == null) return;
369 | EasyPermissionLog.d("showAlert:"+topActivity.getLocalClassName());
370 | alertDialog = EasyAppDialogTool.showTopAlertStyle(mAlertInfo,mTopAlertStyle);
371 |
372 | //
373 | // View alertView = View.inflate(topActivity, R.layout.alert_info_top, null);
374 | // alertDialog = new Dialog(topActivity, R.style.theme_alertdialog_transparent);
375 | // alertDialog.setOwnerActivity(topActivity);
376 | // TextView titleView = alertView.findViewById(R.id.tvAlertTitle);
377 | // titleView.setText(mAlertInfo.alertTitle);
378 | // TextView messageView = alertView.findViewById(R.id.tvAlertMessage);
379 | // messageView.setText(mAlertInfo.alertMessage);
380 | // Window win = alertDialog.getWindow();
381 | //// int with = EasyViewUtil.getScreenWidth(topActivity);
382 | //// int side = EasyViewUtil.dip2px(topActivity,5);
383 | // win.getDecorView().setPadding(0, 0, 0, 0);
384 | // WindowManager.LayoutParams lp = win.getAttributes();
385 | // lp.width = WindowManager.LayoutParams.MATCH_PARENT;
386 | // lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
387 | // lp.gravity = Gravity.TOP;
388 | // win.setAttributes(lp);
389 | // alertDialog.getWindow().setBackgroundDrawable(new BitmapDrawable(topActivity.getResources(), (Bitmap) null));
390 | // alertDialog.setContentView(alertView);
391 | // alertDialog.show();
392 | }
393 |
394 | /**
395 | * When an activity needs to be destroyed, its attached dialog also needs to be destroyed
396 | * activity需要销毁时,依附的dialog也需要销毁
397 | */
398 | private void dismissAlert(Activity activity) {
399 | if (alertDialog != null && alertDialog.isShowing()) {
400 | EasyPermissionLog.d(" dismissAlert:activity:"+activity.getLocalClassName());
401 | EasyPermissionLog.d(" dismissAlert:getOwnerActivity:"+alertDialog.getOwnerActivity().getLocalClassName());
402 | boolean isCurrentAlert = activity.equals(alertDialog.getOwnerActivity());
403 | if(isCurrentAlert){
404 | alertDialog.dismiss();
405 | }
406 | }
407 | }
408 |
409 | /**
410 | * Hide the instructions when the authorization result is called back
411 | * 授权结果回调时,隐藏说明提示
412 | */
413 | private void dismissAlert() {
414 | if (alertDialog != null && alertDialog.isShowing()) {
415 | alertDialog.dismiss();
416 | }
417 | }
418 | /**
419 | * Permissions are disabled from pop-ups
420 | * 权限被禁止弹窗
421 | */
422 | private void showDialog(EasyPermission easyPermission) {
423 | if(mDialogStyle == null){
424 | //默认样式
425 | //The default styles
426 | EasyAppDialogTool.showDialogWithDefaultStyle(easyPermission);
427 | }else {
428 | switch (mDialogStyle.getStyle()){
429 | case STYLE_CUSTOM:
430 | //自定义样式
431 | //Custom styles
432 | EasyAppDialogTool.showDialogWithCustomStyle(easyPermission,mDialogStyle);
433 | break;
434 | case STYLE_SYSTEM:
435 | //系统样式
436 | //System style
437 | EasyAppDialogTool.showDialogWithSystemStyle(easyPermission);
438 | break;
439 | default:
440 | //默认样式
441 | //The default styles
442 | EasyAppDialogTool.showDialogWithDefaultStyle(easyPermission);
443 | break;
444 | }
445 | }
446 | }
447 |
448 | /**
449 | * After requesting a callback, you can determine whether a second request has been denied
450 | * The original intention of Google is:
451 | * 1,If you have not applied for permission, just apply, so return false.
452 | * 2. If the application is rejected by the user, you will prompt the user, so return true;
453 | * 3. If the user chooses to reject the application and does not prompt the user any more,
454 | * then you should not apply or prompt the user, so return false.
455 | * 4. It has been allowed. No application or prompt is required, so return false.
456 | * So the use of pure shouldShowRequestPermissionRationale to do judgment,
457 | * it is no use, can only be used request permission again after correction.
458 | *
459 | * 在请求回调后可以判断是否被拒绝再次请求
460 | * Google的原意是:
461 | * 1,没有申请过权限,申请就是了,所以返回false;
462 | * 2,申请了用户拒绝了,那你就要提示用户了,所以返回true;
463 | * 3,用户选择了拒绝并且不再提示,那你也不要申请了,也不要提示用户了,所以返回false;
464 | * 4,已经允许了,不需要申请也不需要提示,所以返回false;
465 | * 所以单纯的使用shouldShowRequestPermissionRationale去做什么判断,是没用的,只能在请求权限回调后再使用。
466 | *
467 | * @param permission
468 | */
469 | private boolean shouldShowRequestPermissionRationale(String permission) {
470 | return ActivityCompat.shouldShowRequestPermissionRationale(getTopActivity(), permission);
471 | }
472 |
473 | /**
474 | * you can determine whether a second request has been denied
475 | *
476 | * 可以判断是否被拒绝再次请求
477 | *
478 | * @param permissions
479 | */
480 | public boolean hasBeanDismissAsk(String... permissions) {
481 | boolean tempDismissAsk = false;
482 | for (String permission : permissions) {
483 | //读取本地存储的被拒绝权限
484 | tempDismissAsk = EasyCacheData.getInstance().getBoolean(permission);
485 | EasyPermissionLog.d("haveBeanDismissAsk:" + tempDismissAsk);
486 | if (tempDismissAsk) return true;
487 | }
488 | return false;
489 | }
490 |
491 | /**
492 | * Update forbidden permission information
493 | * 更新被禁止的权限信息
494 | *
495 | * @param permissions 权限
496 | * @param state true被禁止,false不被禁止可以询问
497 | */
498 | protected void updateDismissState(String[] permissions, boolean state) {
499 | for (String permission : permissions) {
500 | updateDismissState(permission, state);
501 | }
502 | }
503 |
504 | /**
505 | * Update forbidden permission information
506 | * 更新被禁止的权限信息
507 | *
508 | * @param permission 权限
509 | * @param permission true被禁止,false不被禁止可以询问
510 | */
511 | protected void updateDismissState(String permission, boolean state) {
512 | EasyCacheData.getInstance().save(permission, state);
513 | }
514 |
515 | /**
516 | * Denied permission and forbidden to ask
517 | *
518 | * 被拒绝请求权限,且禁止询问
519 | *
520 | * @param permissions
521 | * @return
522 | */
523 | protected boolean hasDismissedAsk(@NonNull String... permissions) {
524 | return !hasPermission(permissions)
525 | && hasBeanDismissAsk(permissions);
526 | }
527 |
528 | /**
529 | * Open the APP's permission details Settings
530 | * Receive the permission callback result of requestCode in the onActivityResult, and re-execute the permission related logic
531 | * 打开 APP 的权限详情设置
532 | * 在onActivityResult中接收requestCode的权限回调结果,重新执行权限相关逻辑
533 | */
534 | protected void openAppDetails(@NonNull EasyPermission easyPermission) {
535 | this.mCurrentEasyPermission = easyPermission;
536 | //更新请求的activity
537 | if(easyPermission.getContext() != null){
538 | updateTopActivity(easyPermission.getContext());
539 | }
540 | showDialog(easyPermission);
541 | }
542 |
543 | /**
544 | * Skip To the Settings
545 | * 跳转设置页
546 | */
547 | public void goToAppSettings(@NonNull EasyPermission easyPermission) {
548 | //更新请求的activity
549 | if(easyPermission.getContext() != null){
550 | updateTopActivity(easyPermission.getContext());
551 | }
552 | this.mCurrentEasyPermission = easyPermission;
553 | goToAppSettings(easyPermission.getRequestCode());
554 | }
555 |
556 | /**
557 | * Skip To the Settings
558 | * 跳转设置页
559 | *
560 | * @param requestCode
561 | */
562 | public void goToAppSettings(int requestCode) {
563 | Activity topActivity = getTopActivity();
564 | Intent intent = new Intent();
565 | intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
566 | intent.addCategory(Intent.CATEGORY_DEFAULT);
567 | intent.setData(Uri.parse("package:" + topActivity.getPackageName()));
568 | intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
569 | intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
570 | topActivity.startActivityForResult(intent, requestCode);
571 | }
572 |
573 | /**
574 | * Handle permissions result callbacks
575 | * In the activity of need to access the callback rewrite onRequestPermissionsResult calls to this function
576 | *
577 | * 处理权限结果回调
578 | * 在需要权限回调的activity中重写onRequestPermissionsResult调用此函数
579 | *
580 | * @param requestCode
581 | * @param permissions
582 | * @param grantResults
583 | */
584 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, int[] grantResults, @NonNull Activity context) {
585 | dismissAlert();
586 | EasyPermissionLog.d("权限结果回调,隐藏弹窗");
587 | // no callback required
588 | //不需要回调的情况
589 | if (requestCode == REQUESTCODE_DEFAULT) {
590 | return;
591 | }
592 | if (mResults == null || mResults.size() == 0) {
593 | return;
594 | }
595 | EasyPermissionResult permissionResult = mResults.get(requestCode);
596 | if (permissionResult == null) {
597 | return;
598 | }
599 | if (permissions.length <= 0) {
600 | return;
601 | }
602 | //Here are the situations where a callback is required
603 | //以下是需要回调的情况
604 |
605 | //grantResults is empty to indicate that permissions are not being asked but the request is being invoked
606 | //grantResults为空表示权限被禁止询问了但是还调用了申请请求
607 | if (grantResults == null) {
608 | //Do not process onpermissionsseparation when true
609 | //为true不处理onPermissionsDismiss
610 | boolean onPermissionsDismiss = false;
611 | //Permissions are forbidden to ask
612 | //权限被禁止询问
613 | EasyPermissionLog.d("权限已经被禁止询问");
614 | //保存被禁止的权限
615 | updateDismissState(permissions, true);
616 | onPermissionsDismiss = permissionResult.onDismissAsk(requestCode, Arrays.asList(permissions),true);
617 | //Permission not passed
618 | //权限未通过
619 | if (!onPermissionsDismiss) {
620 | permissionResult.onPermissionsDismiss(requestCode, Arrays.asList(permissions));
621 | }
622 | return;
623 | }
624 | if (grantResults.length < permissions.length) {
625 | return;
626 | }
627 | // permission to pass
628 | //通过的权限
629 | List granted = new ArrayList<>();
630 | // denied access
631 | //拒绝的权限
632 | List denied = new ArrayList<>();
633 | // rejected permissions that cannot be asked for
634 | //拒绝的且不能询问的权限
635 | List noask = new ArrayList<>();
636 | for (int i = 0; i < permissions.length; i++) {
637 | String perm = permissions[i];
638 | if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
639 | granted.add(perm);
640 | } else {
641 | denied.add(perm);
642 | // judgment cannot be questioned
643 | //判断不能被询问(未通化切不需要提示即为被禁止了)
644 | if (!shouldShowRequestPermissionRationale(perm)) {
645 | //保存被禁止的权限
646 | updateDismissState(perm, true);
647 | noask.add(perm);
648 | }
649 | }
650 | }
651 | //Do not process onpermissionsseparation when true
652 | //为true不处理onPermissionsDismiss
653 | boolean onPermissionsDismiss = false;
654 | // permission is forbidden to ask
655 | //有权限被禁止询问
656 | if (!noask.isEmpty()) {
657 | EasyPermissionLog.d("权限现在被禁止询问");
658 | onPermissionsDismiss = permissionResult.onDismissAsk(requestCode, noask,true);
659 | }
660 | // permission not passed
661 | //有权限未通过
662 | if (!onPermissionsDismiss && !denied.isEmpty()) {
663 | EasyPermissionLog.d("权限被拒绝");
664 | permissionResult.onPermissionsDismiss(requestCode, denied);
665 | }
666 | // all permissions passed
667 | // 所有权限都通过
668 | if (!granted.isEmpty() && granted.size() == permissions.length) {
669 | EasyPermissionLog.d("权限已通过");
670 | permissionResult.onPermissionsAccess(requestCode);
671 | }
672 | }
673 |
674 | /**
675 | * Handle permissions result callbacks from App-Settings
676 | * In the activity of need to access the callback rewrite onActivityResult calls to this function
677 | *
678 | * 处理从系统设置权限结果回调
679 | * 在需要权限回调的activity中重写onActivityResult调用此函数
680 | *
681 | * @param requestCode
682 | * @param resultCode
683 | * @param data
684 | */
685 | public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
686 | if (mCurrentEasyPermission == null || mCurrentEasyPermission.getResult() == null) {
687 | return;
688 | }
689 | if (mCurrentEasyPermission.getRequestCode() == requestCode) {
690 | //设置界面返回
691 | //Result from system setting
692 | if (mCurrentEasyPermission.hasPermission()) {
693 | //权限已通过
694 | //Permission approved
695 | mCurrentEasyPermission.onPermissionsAccess();
696 | } else {
697 | //从设置回来还是没给你权限
698 | //You still didn't get permission from Settings
699 | mCurrentEasyPermission.onPermissionsDismiss();
700 | }
701 | }
702 | }
703 |
704 |
705 | }
706 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/EasyPermissionLog.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission;
2 |
3 | import android.text.TextUtils;
4 | import android.util.Log;
5 |
6 | /**
7 | * Print log tool
8 | * 打印日志工具
9 | *
10 | * @author Zhang YanQiang
11 | * @date 2019/6/2 15:02.
12 | */
13 | public class EasyPermissionLog {
14 |
15 | /**
16 | * Print log
17 | * the debug level, EasyPermissionConfig. Info = false without printing
18 | *
19 | * 打印log日志
20 | * info级别,EasyPermissionConfig.DEBUG=false时不打印
21 | *
22 | * @param logString
23 | */
24 | public static void i(String logString) {
25 | if (TextUtils.isEmpty(logString)) {
26 | return;
27 | }
28 | if (EasyPermissionConfig.isDebug()) {
29 | Log.i(EasyPermissionConfig.LOG_TAG, logString);
30 | }
31 | }
32 |
33 | /**
34 | * Print log
35 | * the debug level, EasyPermissionConfig. Debug = false without printing
36 | *
37 | * 打印log日志
38 | * debug级别,EasyPermissionConfig.DEBUG=false时不打印
39 | *
40 | * @param logString
41 | */
42 | public static void d(String logString) {
43 | if (TextUtils.isEmpty(logString)) {
44 | return;
45 | }
46 | if (EasyPermissionConfig.isDebug()) {
47 | Log.d(EasyPermissionConfig.LOG_TAG, logString);
48 | }
49 | }
50 |
51 | /**
52 | * 打印log日志
53 | * error级别,不管是不是debug模式,都打印
54 | * 打印log日志
55 | * error级别,不管是不是debug模式,都打印
56 | *
57 | * @param logString
58 | */
59 | public static void e(String logString) {
60 | if (TextUtils.isEmpty(logString)) {
61 | return;
62 | }
63 | Log.e(EasyPermissionConfig.LOG_TAG, logString);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/EasyPermissionResult.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Request permission result callback
9 | * 请求权限结果回调
10 | *
11 | * @author Zhang YanQiang
12 | * @date 2019/6/2 14:55.
13 | */
14 | public abstract class EasyPermissionResult {
15 | /**
16 | * The currently bound permission application object
17 | * 当前绑定的权限申请对象
18 | */
19 | public EasyPermission mEasyPermission = null;
20 |
21 | public EasyPermissionResult() {
22 | }
23 |
24 | public EasyPermission getEasyPermission() {
25 | return mEasyPermission;
26 | }
27 |
28 | /**
29 | * Bind the permission application object for subsequent invocation
30 | * 绑定权限申请对象,方便后续调用
31 | * @param mEasyPermission
32 | */
33 | public void setEasyPermission(EasyPermission mEasyPermission) {
34 | this.mEasyPermission = mEasyPermission;
35 | }
36 |
37 | /**
38 | * Permissions allowed
39 | * do what you need to do
40 | * 权限被允许
41 | * 执行自己需要的操作
42 | *
43 | * @param requestCode 请求的code
44 | */
45 | public void onPermissionsAccess(int requestCode) {
46 | EasyPermissionLog.d("onPermissionsAccess:code =" + requestCode);
47 | }
48 |
49 | /**
50 | * Permissions are questioned and denied
51 | * 权限被询问并拒绝
52 | *
53 | * @param requestCode 请求的code
54 | * @param permissions 被拒绝的权限
55 | */
56 | public void onPermissionsDismiss(int requestCode, @NonNull List permissions) {
57 | EasyPermissionLog.d("onPermissionsDismiss:code =" + requestCode + " " + permissions.toString());
58 | }
59 | /**
60 | * Permissions are simply refused to be asked
61 | * 权限被直接拒绝询问,如果设置了mAlertInfo并且autoOpenAppDetails = true,就会自动处理,不需要再单独处理
62 | *
63 | * @param requestCode 请求的code
64 | * @param permissions 被拒绝的权限
65 | * @return 默认返回false,如果返回为true,将只处理onDismissAsk的回调,不再往下继续处理onPermissionsDismiss或者别的权限请求
66 | * Returns false by default, and if so, only the callback onDismissAsk will be processed,
67 | * so that the onPermissionsDismiss or other permission request will not be processed further down
68 | */
69 | public boolean onDismissAsk(int requestCode, @NonNull List permissions) {
70 | EasyPermissionLog.d("onDismissAsk:code =" + requestCode + " " + permissions.toString());
71 | if(autoOpenDialog()){
72 | openAppDetails();
73 | return true;
74 | }else {
75 | return false;
76 | }
77 | }
78 |
79 | /**
80 | * Permissions are simply refused to be asked
81 | * 权限被直接拒绝询问,如果设置了mAlertInfo并且autoOpenAppDetails = true,就会自动处理,不需要再单独处理
82 | *
83 | * @param requestCode 请求的code
84 | * @param permissions 被拒绝的权限
85 | * @param firstDismissAsk 是否首次被禁止
86 | * @return 默认返回false,如果返回为true,将只处理onDismissAsk的回调,不再往下继续处理onPermissionsDismiss或者别的权限请求
87 | * Returns false by default, and if so, only the callback onDismissAsk will be processed,
88 | * so that the onPermissionsDismiss or other permission request will not be processed further down
89 | */
90 | protected boolean onDismissAsk(int requestCode, @NonNull List permissions,boolean firstDismissAsk) {
91 | EasyPermissionLog.d("onDismissAsk:code =" + requestCode + " " + permissions.toString() + " firstDismissAsk:"+firstDismissAsk);
92 | if(firstDismissAsk){
93 | return false;
94 | }else {
95 | return onDismissAsk(requestCode,permissions);
96 | }
97 | }
98 |
99 | /**
100 | * Open the APP's permission details Settings
101 | * 打开 APP 的权限详情设置提示弹框
102 | */
103 | public void openAppDetails(){
104 | if(mEasyPermission != null){
105 | mEasyPermission.openAppDetails();
106 | }
107 | }
108 |
109 | /**
110 | * Determines whether the current request opens the Settings popup automatically
111 | * 判断当前请求是否自动打开设置弹窗
112 | * @return
113 | */
114 | private boolean autoOpenDialog(){
115 | if(mEasyPermission == null){
116 | return false;
117 | }else if(mEasyPermission.getAlertInfo() == null){
118 | return false;
119 | }else {
120 | return mEasyPermission.isAutoOpenAppDetails();
121 | }
122 | }
123 |
124 | /**
125 | * Skip To the Settings
126 | * 跳转设置页
127 | */
128 | public void goToAppSettings() {
129 | if(mEasyPermission != null){
130 | mEasyPermission.goToAppSettings();
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/bean/EasyAppSettingDialogStyle.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.bean;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 | import android.view.Gravity;
6 | import android.view.View;
7 |
8 | import com.zyq.easypermission.R;
9 |
10 | /**
11 | * App sets popover styles
12 | * app设置弹窗样式
13 | * @author by Zhang YanQiang
14 | * @date 2022/3/23.
15 | */
16 | public class EasyAppSettingDialogStyle {
17 | /**
18 | * 弹窗样式选择,默认 STYLE_DEFAULT
19 | * STYLE_DEFAULT - 蓝色弹窗,黑色文本内容
20 | * STYLE_SYSTEM - AlertDialog默认系统样式
21 | * STYLE_CUSTOM - 基于STYLE_DEFAULT自定义部分属性
22 | *
23 | * Popover style selection, STYLE_DEFAULT by default
24 | */
25 | public enum DialogStyle{
26 | STYLE_DEFAULT, STYLE_SYSTEM, STYLE_CUSTOM
27 | }
28 |
29 | /**
30 | * style=STYLE_CUSTOM时其它属性才会生效,STYLE_DEFAULT和STYLE_SYSTEM下有默认样式
31 | *
32 | * Other attributes take effect only when style=STYLE_CUSTOM. STYLE_DEFAULT and STYLE_SYSTEM have default styles
33 | * @param style {@link DialogStyle}
34 | */
35 | public EasyAppSettingDialogStyle(DialogStyle style) {
36 | this.style = style;
37 | }
38 |
39 | /**
40 | * 样式,默认STYLE_DEFAULT
41 | * Style, STYLE_DEFAULT by default
42 | */
43 | private DialogStyle style = DialogStyle.STYLE_DEFAULT;
44 |
45 | /**
46 | * 标题位置,默认居中 Gravity.CENTER
47 | */
48 | private int titleGravity = Gravity.CENTER;
49 | /**
50 | * 标题文字大小(sp),默认15sp
51 | */
52 | private int titleSize = 15;
53 | /**
54 | * 内容文字大小(sp),默认13sp
55 | */
56 | private int messageSize = 13;
57 | /**
58 | * 按钮文字大小(sp),默认14sp
59 | */
60 | private int buttonTextSize = 14;
61 | /**
62 | * 标题文字颜色(#333333),默认#333333
63 | */
64 | private String titleColor = "#333333";
65 | /**
66 | * 内容文字颜色(#333333),默认#333333
67 | */
68 | private String messageColor = "#333333";
69 | /**
70 | * 按钮主题颜色(#0086f6),左边边框和文字,右边背景色 默认#0086f6
71 | */
72 | private String buttonThemeColor = "#0086f6";
73 | /**
74 | * 左边的取消按钮文本:默认"取消"
75 | */
76 | private String cancelText = null;
77 | /**
78 | * 右边的确认按钮文本:默认"去打开"
79 | */
80 | private String confirmText = null;
81 |
82 |
83 | public DialogStyle getStyle() {
84 | return style;
85 | }
86 |
87 | /**
88 | * 设置一个新的样式
89 | * Set a new style
90 | * @param style {@link DialogStyle}
91 | * @return
92 | */
93 | public EasyAppSettingDialogStyle setStyle(DialogStyle style) {
94 | this.style = style;
95 | return this;
96 | }
97 |
98 | public int getTitleGravity() {
99 | return titleGravity;
100 | }
101 |
102 | /**
103 | * 设置标题位置,默认居中 Gravity.CENTER
104 | * Sets the horizontal alignment of the text and the vertical gravity that will be used when there is extra space in the TextView beyond what is required for the text itself.
105 | * See Also:{@link Gravity}
106 | * @param titleGravity
107 | */
108 | public EasyAppSettingDialogStyle setTitleGravity(int titleGravity) {
109 | this.titleGravity = titleGravity;
110 | return this;
111 | }
112 |
113 | public int getTitleSize() {
114 | return titleSize;
115 | }
116 | /**
117 | * 设置标题文字大小(sp),默认15sp
118 | *
119 | * Set the title text size (sp). Default: 15sp
120 | */
121 | public EasyAppSettingDialogStyle setTitleSize(int titleSize) {
122 | this.titleSize = titleSize;
123 | return this;
124 | }
125 |
126 | public int getMessageSize() {
127 | return messageSize;
128 | }
129 | /**
130 | * 设置内容文字大小(sp),默认13sp
131 | * Set the content text size (sp) to 13sp by default
132 | */
133 | public EasyAppSettingDialogStyle setMessageSize(int messageSize) {
134 | this.messageSize = messageSize;
135 | return this;
136 | }
137 |
138 | public int getButtonTextSize() {
139 | return buttonTextSize;
140 | }
141 |
142 | /**
143 | * 设置按钮文字大小(sp),默认14sp
144 | * Set the button text size (SP) to 14sp by default
145 | */
146 | public EasyAppSettingDialogStyle setButtonTextSize(int buttonTextSize) {
147 | this.buttonTextSize = buttonTextSize;
148 | return this;
149 | }
150 |
151 | public String getTitleColor() {
152 | return titleColor;
153 | }
154 |
155 | /**
156 | * 设置标题文字颜色(#333333),默认#333333
157 | * Set the title text color (#333333), default #333333
158 | */
159 | public EasyAppSettingDialogStyle setTitleColor(String titleColor) {
160 | this.titleColor = titleColor;
161 | return this;
162 | }
163 |
164 | public String getMessageColor() {
165 | return messageColor;
166 | }
167 | /**
168 | * 设置内容文字颜色(#333333),默认#333333
169 | *
170 | * Set the content text color (#333333), default #333333
171 | */
172 | public EasyAppSettingDialogStyle setMessageColor(String messageColor) {
173 | this.messageColor = messageColor;
174 | return this;
175 | }
176 |
177 | public String getButtonThemeColor() {
178 | return buttonThemeColor;
179 | }
180 |
181 | /**
182 | * 设置按钮主题颜色(#0086f6),左边边框和文字,右边背景色 默认#0086f6
183 | *
184 | * Set the button theme color (# 0086F6), left border and text, and the right background color defaults to #0086f6
185 | */
186 | public EasyAppSettingDialogStyle setButtonThemeColor(String buttonThemeColor) {
187 | this.buttonThemeColor = buttonThemeColor;
188 | return this;
189 | }
190 |
191 | public String getCancelText(Context context) {
192 | if(TextUtils.isEmpty(cancelText)){
193 | return context.getString(R.string.setting_alert_button_cancel);
194 | }
195 | return cancelText;
196 | }
197 |
198 | /**
199 | * 左边的取消按钮文本:默认"取消"
200 | * Cancel button text at Left:Default is "Cancel"
201 | * @param cancelText
202 | * @return
203 | */
204 | public EasyAppSettingDialogStyle setCancelText(String cancelText) {
205 | this.cancelText = cancelText;
206 | return this;
207 | }
208 |
209 | public String getConfirmText(Context context) {
210 | if(TextUtils.isEmpty(cancelText)){
211 | return context.getString(R.string.setting_alert_button_confirm);
212 | }
213 | return confirmText;
214 | }
215 |
216 | /**
217 | * 右边的确认按钮文本:默认"去打开"
218 | * Confirm button text at Right:Default is "Understand"
219 | * @param confirmText
220 | * @return
221 | */
222 | public EasyAppSettingDialogStyle setConfirmText(String confirmText) {
223 | this.confirmText = confirmText;
224 | return this;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/bean/EasyTopAlertStyle.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.bean;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 | import android.view.Gravity;
6 |
7 | import com.zyq.easypermission.R;
8 |
9 | /**
10 | * Set the top prompt style
11 | * 设置顶部提示样式
12 | * @author by Zhang YanQiang
13 | * @date 2022/4/6.
14 | */
15 | public class EasyTopAlertStyle {
16 | /**
17 | * 提示样式选择,默认 STYLE_DEFAULT
18 | * STYLE_DEFAULT - 白色背景,黑色文本内容
19 | * STYLE_CUSTOM - 基于STYLE_DEFAULT自定义部分属性
20 | *
21 | * Popover style selection, STYLE_DEFAULT by default
22 | */
23 | public enum AlertStyle{
24 | STYLE_DEFAULT, STYLE_CUSTOM
25 | }
26 |
27 | /**
28 | * style=STYLE_CUSTOM时其它属性才会生效,STYLE_DEFAULT有默认样式
29 | *
30 | * Other attributes take effect only when style=STYLE_CUSTOM. STYLE_DEFAULT have default styles
31 | * @param style {@link AlertStyle}
32 | */
33 | public EasyTopAlertStyle(AlertStyle style) {
34 | this.style = style;
35 | }
36 |
37 | /**
38 | * 样式,默认STYLE_DEFAULT
39 | * Style, STYLE_DEFAULT by default
40 | */
41 | private AlertStyle style = AlertStyle.STYLE_DEFAULT;
42 |
43 | /**
44 | * 标题位置,默认居中 Gravity.LEFT
45 | */
46 | private int titleGravity = Gravity.LEFT;
47 | /**
48 | * 标题文字大小(sp),默认16sp
49 | */
50 | private int titleSize = 16;
51 | /**
52 | * 内容文字大小(sp),默认13sp
53 | */
54 | private int messageSize = 14;
55 | /**
56 | * 标题文字颜色(#333333),默认#333333
57 | */
58 | private String titleColor = "#333333";
59 | /**
60 | * 内容文字颜色(#333333),默认#333333
61 | */
62 | private String messageColor = "#333333";
63 | /**
64 | * 背景颜色(#FFFFFF),提示框背景颜色 默认#FFFFFF
65 | */
66 | private String backgroundColor = "#FFFFFF";
67 | /**
68 | * 背景圆角弧度,默认8dp
69 | */
70 | private int backgroundRadius = 8;
71 | /**
72 | * 背景z轴高度(阴影效果),不需要时设置为0,默认6dp
73 | */
74 | private int backgroundElevation = 6;
75 | /**
76 | * 背景左右两边边距,不需要时设置为0,默认10dp
77 | */
78 | private int sideMargin = 10;
79 | /**
80 | * 背景顶部边距,不需要时设置为0,默认10dp
81 | */
82 | private int topMargin = 10;
83 |
84 | public AlertStyle getStyle() {
85 | return style;
86 | }
87 |
88 | /**
89 | * 设置一个新的样式
90 | * Set a new style
91 | * @param style {@link AlertStyle}
92 | * @return
93 | */
94 | public EasyTopAlertStyle setStyle(AlertStyle style) {
95 | this.style = style;
96 | return this;
97 | }
98 |
99 |
100 | public int getTitleGravity() {
101 | return titleGravity;
102 | }
103 |
104 | /**
105 | * 设置标题位置,默认居中 Gravity.CENTER
106 | * Sets the horizontal alignment of the text and the vertical gravity that will be used when there is extra space in the TextView beyond what is required for the text itself.
107 | * See Also:{@link Gravity}
108 | * @param titleGravity
109 | */
110 | public EasyTopAlertStyle setTitleGravity(int titleGravity) {
111 | this.titleGravity = titleGravity;
112 | return this;
113 | }
114 |
115 | public int getTitleSize() {
116 | return titleSize;
117 | }
118 | /**
119 | * 设置标题文字大小(sp),默认15sp
120 | *
121 | * Set the title text size (sp). Default: 16sp
122 | */
123 | public EasyTopAlertStyle setTitleSize(int titleSize) {
124 | this.titleSize = titleSize;
125 | return this;
126 | }
127 |
128 | public int getMessageSize() {
129 | return messageSize;
130 | }
131 | /**
132 | * 设置内容文字大小(sp),默认13sp
133 | * Set the content text size (sp) to 13sp by default
134 | */
135 | public EasyTopAlertStyle setMessageSize(int messageSize) {
136 | this.messageSize = messageSize;
137 | return this;
138 | }
139 |
140 |
141 | public String getTitleColor() {
142 | return titleColor;
143 | }
144 |
145 | /**
146 | * 设置标题文字颜色(#333333),默认#333333
147 | * Set the title text color (#333333), default #333333
148 | */
149 | public EasyTopAlertStyle setTitleColor(String titleColor) {
150 | this.titleColor = titleColor;
151 | return this;
152 | }
153 |
154 | public String getMessageColor() {
155 | return messageColor;
156 | }
157 | /**
158 | * 设置内容文字颜色(#333333),默认#333333
159 | *
160 | * Set the content text color (#333333), default #333333
161 | */
162 | public EasyTopAlertStyle setMessageColor(String messageColor) {
163 | this.messageColor = messageColor;
164 | return this;
165 | }
166 |
167 | public String getBackgroundColor() {
168 | return backgroundColor;
169 | }
170 |
171 | /**
172 | * 设置背景颜色(#FFFFFF),默认#FFFFFF
173 | *
174 | * Set the background color (#FFFFFF), default #FFFFFF
175 | */
176 | public EasyTopAlertStyle setBackgroundColor(String backgroundColor) {
177 | this.backgroundColor = backgroundColor;
178 | return this;
179 | }
180 |
181 | public int getBackgroundRadius() {
182 | return backgroundRadius;
183 | }
184 |
185 | /**
186 | * 设置背景圆角弧度,默认8dp
187 | *
188 | * Set the background fillet radian, default 8dp
189 | * @param backgroundRadius
190 | * @return
191 | */
192 | public EasyTopAlertStyle setBackgroundRadius(int backgroundRadius) {
193 | this.backgroundRadius = backgroundRadius;
194 | return this;
195 | }
196 |
197 | public int getBackgroundElevation() {
198 | return backgroundElevation;
199 | }
200 |
201 | /**
202 | * 设置背景z轴高度(阴影效果),不需要时设置为0,默认6dp
203 | *
204 | * Set the background z-axis height (shadow effect), 0 if not needed, 6dp by default
205 | * @param backgroundElevation
206 | * @return
207 | */
208 | public EasyTopAlertStyle setBackgroundElevation(int backgroundElevation) {
209 | this.backgroundElevation = backgroundElevation;
210 | return this;
211 | }
212 |
213 | public int getSideMargin() {
214 | return sideMargin;
215 | }
216 |
217 | /**
218 | * 设置背景左右两边边距,不需要时设置为0,默认10dp
219 | *
220 | * Set the left and right margins of the background. If not needed, set it to 0. The default is 10dp
221 | * @param sideMargin
222 | * @return
223 | */
224 | public EasyTopAlertStyle setSideMargin(int sideMargin) {
225 | this.sideMargin = sideMargin;
226 | return this;
227 | }
228 |
229 | public int getTopMargin() {
230 | return topMargin;
231 | }
232 |
233 | /**
234 | * 设置背景顶部边距,不需要时设置为0,默认10dp
235 | *
236 | * Set the top margin of the background, 0 if not needed, 10dp by default
237 | * @param topMargin
238 | * @return
239 | */
240 | public EasyTopAlertStyle setTopMargin(int topMargin) {
241 | this.topMargin = topMargin;
242 | return this;
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/bean/PermissionAlertInfo.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.bean;
2 |
3 | /**
4 | * 权限提示信息
5 | * @author by Zhang YanQiang
6 | * @date 2022/3/17.
7 | */
8 | public class PermissionAlertInfo {
9 | /**
10 | * Title of permission prompt, for example, need to locate permission
11 | * 权限提示的标题,如:需要定位权限
12 | */
13 | public String alertTitle;
14 | /**
15 | * Permission prompt content, such as: used to confirm your current location, convenient driver to accurately arrive at your side
16 | * 权限提示的内容,如:用于确认您当前的位置,方便司机准确地到达您的身边
17 | */
18 | public String alertMessage;
19 |
20 | public PermissionAlertInfo(String alertTitle) {
21 | this.alertTitle = alertTitle;
22 | }
23 |
24 | public PermissionAlertInfo(String alertTitle, String alertMessage) {
25 | this.alertTitle = alertTitle;
26 | this.alertMessage = alertMessage;
27 | }
28 |
29 | public String getAlertTitle() {
30 | return alertTitle;
31 | }
32 |
33 | public PermissionAlertInfo setAlertTitle(String alertTitle) {
34 | this.alertTitle = alertTitle;
35 | return this;
36 | }
37 |
38 | public String getAlertMessage() {
39 | return alertMessage;
40 | }
41 |
42 | public PermissionAlertInfo setAlertMessage(String alertMessage) {
43 | this.alertMessage = alertMessage;
44 | return this;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyAlphaTouchListener.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.view.MotionEvent;
4 | import android.view.View;
5 |
6 | /**
7 | * 使用的实现View点击改变透明度
8 | * 在ListView中只响应了ACTION_DOWN,先不要用于ListView
9 | * RecycleView可以用
10 | *
11 | * @author Zhang YanQiang
12 | * @date 2019/10/9 20:39.
13 | */
14 | public class EasyAlphaTouchListener implements View.OnTouchListener {
15 | private final float F_SCACLE_MIN = 0.5f;
16 | private final float F_SCACLE_MAX = 1f;
17 |
18 | @Override
19 | public boolean onTouch(final View v, MotionEvent event) {
20 | switch (event.getAction()) {
21 | case MotionEvent.ACTION_DOWN:
22 | v.setAlpha(F_SCACLE_MIN);
23 | break;
24 | case MotionEvent.ACTION_UP:
25 | v.setAlpha(F_SCACLE_MAX);
26 | break;
27 | case MotionEvent.ACTION_CANCEL:
28 | v.setAlpha(F_SCACLE_MAX);
29 | if (isOutterMotionEvent(event, v)) {
30 | if (v.getParent() != null) {
31 | v.getParent().requestDisallowInterceptTouchEvent(true);
32 | return true;
33 | }
34 | } else {
35 | break;
36 | }
37 | break;
38 | default:
39 | break;
40 | }
41 | return false;
42 | }
43 |
44 | /**
45 | * 事件触发是否超出View边界
46 | *
47 | * @param event
48 | * @param v
49 | * @return
50 | */
51 | private boolean isOutterMotionEvent(MotionEvent event, View v) {
52 | float touchX = event.getX();
53 | float touchY = event.getY();
54 | float maxX = v.getWidth();
55 | float maxY = v.getHeight();
56 |
57 | return touchX < 0 || touchX > maxX || touchY < 0 || touchY > maxY;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyAppDialogTool.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.app.Dialog;
6 | import android.content.DialogInterface;
7 | import android.graphics.Bitmap;
8 | import android.graphics.Color;
9 | import android.graphics.drawable.BitmapDrawable;
10 | import android.graphics.drawable.GradientDrawable;
11 | import android.os.Build;
12 | import android.text.TextUtils;
13 | import android.view.Gravity;
14 | import android.view.View;
15 | import android.view.ViewGroup;
16 | import android.view.Window;
17 | import android.view.WindowManager;
18 | import android.widget.RelativeLayout;
19 | import android.widget.TextView;
20 |
21 | import androidx.annotation.Nullable;
22 | import androidx.annotation.RequiresApi;
23 |
24 | import com.zyq.easypermission.EasyPermission;
25 | import com.zyq.easypermission.EasyPermissionHelper;
26 | import com.zyq.easypermission.EasyPermissionLog;
27 | import com.zyq.easypermission.R;
28 | import com.zyq.easypermission.bean.EasyAppSettingDialogStyle;
29 | import com.zyq.easypermission.bean.EasyTopAlertStyle;
30 | import com.zyq.easypermission.bean.PermissionAlertInfo;
31 |
32 | /**
33 | * App sets the popover controller
34 | * app设置弹窗控制器
35 | *
36 | * @author by Zhang YanQiang
37 | * @date 2022/3/23.
38 | */
39 | public class EasyAppDialogTool {
40 | /**
41 | * Permissions are disabled from pop-ups(default popover style)
42 | * 权限被禁止弹窗(默认弹窗样式)
43 | */
44 | public static void showDialogWithDefaultStyle(@Nullable final EasyPermission easyPermission) {
45 | final int requestCode = easyPermission.getRequestCode();
46 | PermissionAlertInfo mAlertInfo = easyPermission.getAlertInfo();
47 | if (mAlertInfo == null || TextUtils.isEmpty(mAlertInfo.alertMessage)) {
48 | return;
49 | }
50 | final Activity topActivity = EasyPermissionHelper.getInstance().getTopActivity();
51 | if (topActivity == null) return;
52 | View contentView = View.inflate(topActivity, R.layout.dialog_info_middle, null);
53 | AlertDialog.Builder builder = new AlertDialog.Builder(topActivity, R.style.theme_alertdialog_transparent);
54 | builder.setView(contentView);
55 | builder.setCancelable(false);
56 | final AlertDialog dialog = builder.create();
57 | View.OnClickListener cancelClick = new View.OnClickListener() {
58 | @Override
59 | public void onClick(View v) {
60 | dialog.dismiss();
61 | if(easyPermission.getResult() != null){
62 | easyPermission.onPermissionsDismiss();
63 | }
64 | }
65 | };
66 | View.OnClickListener confirmClick = new View.OnClickListener() {
67 | @Override
68 | public void onClick(View v) {
69 | dialog.dismiss();
70 | EasyPermissionHelper.getInstance().goToAppSettings(requestCode);
71 | }
72 | };
73 | //按钮点击
74 | EasyAlphaTouchListener alphaTouchListener = new EasyAlphaTouchListener();
75 | contentView.findViewById(R.id.btnCancel).setOnTouchListener(alphaTouchListener);
76 | contentView.findViewById(R.id.btnConfirm).setOnTouchListener(alphaTouchListener);
77 |
78 | ((TextView) contentView.findViewById(R.id.tvAlertTitle)).setText(mAlertInfo.alertTitle);
79 | ((TextView) contentView.findViewById(R.id.tvAlertMessage)).setText(mAlertInfo.alertMessage);
80 | contentView.findViewById(R.id.btnCancel).setOnClickListener(cancelClick);
81 | contentView.findViewById(R.id.btnConfirm).setOnClickListener(confirmClick);
82 | dialog.show();
83 | }
84 |
85 | /**
86 | * Permissions forbidden popover (system popover style)
87 | * 权限被禁止弹窗(系统弹窗样式)
88 | */
89 | public static void showDialogWithSystemStyle(@Nullable final EasyPermission easyPermission) {
90 | final int requestCode = easyPermission.getRequestCode();
91 | PermissionAlertInfo mAlertInfo = easyPermission.getAlertInfo();
92 | if (mAlertInfo == null || TextUtils.isEmpty(mAlertInfo.alertMessage)) {
93 | return;
94 | }
95 | final Activity topActivity = EasyPermissionHelper.getInstance().getTopActivity();
96 | if (topActivity == null) return;
97 | String title = mAlertInfo.alertTitle;
98 | String message = mAlertInfo.alertMessage;
99 | String confirm = topActivity.getString(R.string.setting_alert_button_confirm);
100 | String cancel = topActivity.getString(R.string.setting_alert_button_cancel);
101 | AlertDialog.Builder builder = new AlertDialog.Builder(topActivity);
102 | builder.setTitle(title);
103 | StringBuilder msg = new StringBuilder();
104 | msg.append("\n");
105 | msg.append(message);
106 | builder.setMessage(msg.toString());
107 | builder.setCancelable(false);
108 | builder.setPositiveButton(confirm, new DialogInterface.OnClickListener() {
109 | @Override
110 | public void onClick(DialogInterface dialog, int which) {
111 | EasyPermissionHelper.getInstance().goToAppSettings(requestCode);
112 | }
113 | });
114 | builder.setNegativeButton(cancel, new DialogInterface.OnClickListener(){
115 | @Override
116 | public void onClick(DialogInterface dialog, int which) {
117 | if(easyPermission.getResult() != null){
118 | easyPermission.onPermissionsDismiss();
119 | }
120 | }
121 | });
122 | builder.show();
123 | }
124 |
125 | /**
126 | * Permissions are disabled from pop-ups(default popover style)
127 | * 权限被禁止弹窗(自定义弹窗样式)
128 | */
129 | public static void showDialogWithCustomStyle(@Nullable final EasyPermission easyPermission, EasyAppSettingDialogStyle mStyle) {
130 | final int requestCode = easyPermission.getRequestCode();
131 | PermissionAlertInfo mAlertInfo = easyPermission.getAlertInfo();
132 | if (mAlertInfo == null || TextUtils.isEmpty(mAlertInfo.alertMessage)) {
133 | return;
134 | }
135 | final Activity topActivity = EasyPermissionHelper.getInstance().getTopActivity();
136 | if (topActivity == null) return;
137 | View contentView = View.inflate(topActivity, R.layout.dialog_info_middle, null);
138 | AlertDialog.Builder builder = new AlertDialog.Builder(topActivity, R.style.theme_alertdialog_transparent);
139 | builder.setView(contentView);
140 | builder.setCancelable(false);
141 | final AlertDialog dialog = builder.create();
142 | View.OnClickListener cancelClick = new View.OnClickListener() {
143 | @Override
144 | public void onClick(View v) {
145 | dialog.dismiss();
146 | if(easyPermission.getResult() != null){
147 | easyPermission.onPermissionsDismiss();
148 | }
149 | }
150 | };
151 | View.OnClickListener confirmClick = new View.OnClickListener() {
152 | @Override
153 | public void onClick(View v) {
154 | dialog.dismiss();
155 | EasyPermissionHelper.getInstance().goToAppSettings(requestCode);
156 | }
157 | };
158 | //按钮点击
159 | EasyAlphaTouchListener alphaTouchListener = new EasyAlphaTouchListener();
160 | contentView.findViewById(R.id.btnCancel).setOnTouchListener(alphaTouchListener);
161 | contentView.findViewById(R.id.btnConfirm).setOnTouchListener(alphaTouchListener);
162 | //获取控件
163 | TextView title = contentView.findViewById(R.id.tvAlertTitle);
164 | TextView message = contentView.findViewById(R.id.tvAlertMessage);
165 | TextView btnCancel = contentView.findViewById(R.id.btnCancel);
166 | TextView btnConfirm = contentView.findViewById(R.id.btnConfirm);
167 |
168 | title.setText(mAlertInfo.alertTitle);
169 | message.setText(mAlertInfo.alertMessage);
170 | btnCancel.setOnClickListener(cancelClick);
171 | btnConfirm.setOnClickListener(confirmClick);
172 | dialog.show();
173 | if (mStyle == null) {
174 | return;
175 | }
176 | //设置自定义属性
177 | //Set custom properties
178 | title.setGravity(mStyle.getTitleGravity());
179 | title.setTextSize(mStyle.getTitleSize());
180 | message.setTextSize(mStyle.getMessageSize());
181 | btnCancel.setTextSize(mStyle.getButtonTextSize());
182 | btnConfirm.setTextSize(mStyle.getButtonTextSize());
183 | //按钮文本
184 | btnCancel.setText(mStyle.getCancelText(topActivity));
185 | btnConfirm.setText(mStyle.getConfirmText(topActivity));
186 | try {
187 | title.setTextColor(Color.parseColor(mStyle.getTitleColor()));
188 | message.setTextColor(Color.parseColor(mStyle.getMessageColor()));
189 | String buttonColor = mStyle.getButtonThemeColor();
190 | String buttonFillColor = "#00000000";
191 | btnCancel.setTextColor(Color.parseColor(buttonColor));
192 | btnCancel.setBackground(
193 | EasyShapeUtil.createShape(
194 | EasyViewUtil.dip2px(topActivity, 1),
195 | EasyViewUtil.dip2px(topActivity, 20),
196 | GradientDrawable.RECTANGLE,
197 | buttonColor, buttonFillColor
198 | ));
199 | btnConfirm.setBackground(
200 | EasyShapeUtil.createShape(
201 | 0,
202 | EasyViewUtil.dip2px(topActivity, 20),
203 | GradientDrawable.RECTANGLE,
204 | buttonColor, buttonColor
205 | ));
206 | } catch (Exception e) {
207 | e.printStackTrace();
208 | }
209 | }
210 |
211 | /**
212 | * Permission request top alert
213 | * 权限申请顶部提醒
214 | */
215 | public static Dialog showTopAlertStyle(@Nullable final PermissionAlertInfo mAlertInfo, EasyTopAlertStyle mStyle) {
216 | final Activity topActivity = EasyPermissionHelper.getInstance().getTopActivity();
217 | if (topActivity == null) return null;
218 | EasyPermissionLog.d("showAlert:"+topActivity.getLocalClassName());
219 | View alertView = View.inflate(topActivity, R.layout.alert_info_top, null);
220 | Dialog alertDialog = new Dialog(topActivity, R.style.theme_alertdialog_transparent);
221 | alertDialog.setOwnerActivity(topActivity);
222 | TextView titleView = alertView.findViewById(R.id.tvAlertTitle);
223 | titleView.setText(mAlertInfo.alertTitle);
224 | TextView messageView = alertView.findViewById(R.id.tvAlertMessage);
225 | messageView.setText(mAlertInfo.alertMessage);
226 | ViewGroup alertContainer = alertView.findViewById(R.id.alertContainer);
227 | Window win = alertDialog.getWindow();
228 | // int with = EasyViewUtil.getScreenWidth(topActivity);
229 | // int side = EasyViewUtil.dip2px(topActivity,5);
230 | win.getDecorView().setPadding(0, 0, 0, 0);
231 | WindowManager.LayoutParams lp = win.getAttributes();
232 | lp.width = WindowManager.LayoutParams.MATCH_PARENT;
233 | lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
234 | lp.gravity = Gravity.TOP;
235 | win.setAttributes(lp);
236 | alertDialog.getWindow().setBackgroundDrawable(new BitmapDrawable(topActivity.getResources(), (Bitmap) null));
237 | alertDialog.setContentView(alertView);
238 | alertDialog.show();
239 | //设置自定义属性
240 | if(mStyle != null && mStyle.getStyle() == EasyTopAlertStyle.AlertStyle.STYLE_CUSTOM){
241 | try {
242 | titleView.setGravity(mStyle.getTitleGravity());
243 | titleView.setTextSize(mStyle.getTitleSize());
244 | messageView.setTextSize(mStyle.getMessageSize());
245 | titleView.setTextColor(Color.parseColor(mStyle.getTitleColor()));
246 | messageView.setTextColor(Color.parseColor(mStyle.getMessageColor()));
247 | //设置背景样式
248 | String bgColor = mStyle.getBackgroundColor();
249 | alertContainer.setBackground(
250 | EasyShapeUtil.createShape(
251 | 0,
252 | EasyViewUtil.dip2px(topActivity, mStyle.getBackgroundRadius()),
253 | GradientDrawable.RECTANGLE,
254 | bgColor, bgColor
255 | ));
256 | //设置间距
257 | int sideMargin = EasyViewUtil.dip2px(topActivity,mStyle.getSideMargin());
258 | int topMargin = EasyViewUtil.dip2px(topActivity,mStyle.getTopMargin());
259 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) alertContainer.getLayoutParams();
260 | params.leftMargin = sideMargin;
261 | params.rightMargin = sideMargin;
262 | params.topMargin = topMargin;
263 | params.bottomMargin = topMargin;
264 | //设置阴影
265 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
266 | float elevation = EasyViewUtil.dip2px(topActivity, mStyle.getBackgroundElevation());
267 | alertContainer.setElevation(elevation);
268 | }
269 | } catch (Exception e) {
270 | e.printStackTrace();
271 | }
272 | }
273 | return alertDialog;
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyCacheData.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.os.Parcelable;
4 |
5 | import com.tencent.mmkv.MMKV;
6 | import com.zyq.easypermission.EasyPermissionHelper;
7 |
8 | import java.util.Collections;
9 | import java.util.Set;
10 |
11 |
12 | /**
13 | * 一些关键信息的存取(增加缓存)
14 | *
15 | * @author Zhang YanQiang
16 | * @date 2021/9/11 10:43.
17 | */
18 | public class EasyCacheData {
19 | private static EasyCacheData instance;
20 | private static MMKV mv;
21 |
22 | private EasyCacheData() {
23 | if(EasyPermissionHelper.getInstance().alreadyInitialized){
24 | mv = MMKV.defaultMMKV();
25 | }
26 | }
27 |
28 | public static EasyCacheData getInstance() {
29 | if (instance == null) {
30 | synchronized (EasyCacheData.class) {
31 | if (instance == null) {
32 | instance = new EasyCacheData();
33 | }
34 | }
35 | }
36 | return instance;
37 | }
38 |
39 | /**
40 | * 保存基本类型数据
41 | *
42 | * @param key
43 | * @param t
44 | */
45 | public void save(String key, Object t) {
46 | if(mv == null){
47 | return;
48 | }
49 | if (t instanceof String) {
50 | mv.encode(key, (String) t);
51 | } else if (t instanceof Integer) {
52 | mv.encode(key, (Integer) t);
53 | } else if (t instanceof Boolean) {
54 | mv.encode(key, (Boolean) t);
55 | } else if (t instanceof Float) {
56 | mv.encode(key, (Float) t);
57 | } else if (t instanceof Long) {
58 | mv.encode(key, (Long) t);
59 | } else if (t instanceof Double) {
60 | mv.encode(key, (Double) t);
61 | } else if (t instanceof byte[]) {
62 | mv.encode(key, (byte[]) t);
63 | } else {
64 | mv.encode(key, t.toString());
65 | }
66 | }
67 |
68 | /**
69 | * 保存
70 | *
71 | * @param key
72 | * @param sets
73 | */
74 | public void saveSet(String key, Set sets) {
75 | if(mv == null){
76 | return;
77 | }
78 | mv.encode(key, sets);
79 | }
80 |
81 | /**
82 | * 保存Parcelable序列化的
83 | *
84 | * @param key
85 | * @param obj
86 | */
87 | public void saveParcelable(String key, Parcelable obj) {
88 | if(mv == null){
89 | return;
90 | }
91 | mv.encode(key, obj);
92 | }
93 |
94 | /**
95 | * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
96 | *
97 | * @param key
98 | * @return
99 | */
100 | public Integer getInt(String key) {
101 | if(mv == null){
102 | return 0;
103 | }
104 | return mv.decodeInt(key, 0);
105 | }
106 |
107 | public Double getDouble(String key) {
108 | if(mv == null){
109 | return 0.00;
110 | }
111 | return mv.decodeDouble(key, 0.00);
112 | }
113 |
114 | public Long getLong(String key) {
115 | if(mv == null){
116 | return 0L;
117 | }
118 | return mv.decodeLong(key, 0L);
119 | }
120 |
121 | public Boolean getBoolean(String key) {
122 | if(mv == null){
123 | return false;
124 | }
125 | return getBoolean(key, false);
126 | }
127 | public Boolean getBoolean(String key, boolean defaultValue) {
128 | if(mv == null){
129 | return false;
130 | }
131 | return mv.decodeBool(key, defaultValue);
132 | }
133 |
134 | public Float getFloat(String key) {
135 | if(mv == null){
136 | return 0F;
137 | }
138 | return mv.decodeFloat(key, 0F);
139 | }
140 |
141 | public byte[] getBytes(String key) {
142 | if(mv == null){
143 | return new byte[0];
144 | }
145 | return mv.decodeBytes(key);
146 | }
147 |
148 | public String getString(String key) {
149 | if(mv == null){
150 | return "";
151 | }
152 | return mv.decodeString(key, "");
153 | }
154 |
155 | public Set getStringSet(String key) {
156 | if(mv == null){
157 | return Collections.emptySet();
158 | }
159 | return mv.decodeStringSet(key, Collections.emptySet());
160 | }
161 |
162 | public Parcelable getParcelable(String key) {
163 | if(mv == null){
164 | return null;
165 | }
166 | return mv.decodeParcelable(key, null);
167 | }
168 |
169 | /**
170 | * 移除某个key对
171 | *
172 | * @param key
173 | */
174 | public void removeKey(String key) {
175 | if(mv == null){
176 | return;
177 | }
178 | mv.removeValueForKey(key);
179 | }
180 |
181 | /**
182 | * 清除所有key
183 | */
184 | public void clearAll() {
185 | if(mv == null){
186 | return;
187 | }
188 | mv.clearAll();
189 | }
190 |
191 | }
192 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyFloatWindowTool.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.os.Build;
7 | import android.provider.Settings;
8 |
9 | /**
10 | * Hover window permission management
11 | * 悬浮窗权限管理
12 | * @author by Zhang YanQiang
13 | * @date 2022/3/22.
14 | */
15 | public class EasyFloatWindowTool {
16 | /**
17 | * Whether you have suspension window permission
18 | * 是否有悬浮窗权限
19 | *
20 | * @return
21 | */
22 | public static boolean isFloatWindowEnabled(Context context) {
23 | //在6.0以前的系统版本,悬浮窗权限是默认开启的,直接使用即可
24 | //In system versions prior to 6.0, hover window permission is enabled by default and can be used directly
25 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
26 | return Settings.canDrawOverlays(context);
27 | } else {
28 | return true;
29 | }
30 | }
31 | /**
32 | * Go set hover window permissions
33 | * 去设置悬浮窗权限
34 | *
35 | * @return
36 | */
37 | public static void gotoAppSettings(Context context) {
38 | try {
39 | Intent intent = new Intent();
40 | intent.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
41 | intent.addCategory(Intent.CATEGORY_DEFAULT);
42 | intent.setData(Uri.parse("package:" + context.getPackageName()));
43 | intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
44 | intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
45 | context.startActivity(intent);
46 | } catch (Exception e) {
47 | e.printStackTrace();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyLocationTool.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Build;
7 | import android.provider.Settings;
8 | import android.text.TextUtils;
9 |
10 | /**
11 | * Location service management tool
12 | * 定位服务管理工具
13 | * @author by Zhang YanQiang
14 | * @date 2022/3/22.
15 | */
16 | public class EasyLocationTool {
17 |
18 | /**
19 | * Check whether the location service is enabled
20 | * 判断定位服务是否开启
21 | * @param
22 | * @return true 表示开启 true-open
23 | */
24 | public static boolean isLocationEnabled(Context context) {
25 | int locationMode = 0;
26 | String locationProviders;
27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
28 | try {
29 | locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
30 | } catch (Settings.SettingNotFoundException e) {
31 | e.printStackTrace();
32 | return false;
33 | }
34 | return locationMode != Settings.Secure.LOCATION_MODE_OFF;
35 | } else {
36 | locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
37 | return !TextUtils.isEmpty(locationProviders);
38 | }
39 | }
40 |
41 | /**
42 | * The page for setting location information is displayed
43 | * 直接跳转至位置信息设置界面
44 | */
45 | public static void gotoAppSettings(Activity context) {
46 | Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
47 | context.startActivity(intent);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyNotificationTool.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.app.AppOpsManager;
4 | import android.app.NotificationManager;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.pm.ApplicationInfo;
8 | import android.net.Uri;
9 | import android.os.Build;
10 |
11 | import java.lang.reflect.Field;
12 | import java.lang.reflect.InvocationTargetException;
13 | import java.lang.reflect.Method;
14 |
15 | /**
16 | * Notification permission management tool
17 | * 通知权限管理工具
18 | * @author Zhang YanQiang
19 | * @date 2019/1/30 15:49.
20 | */
21 |
22 | public class EasyNotificationTool {
23 |
24 | private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
25 | private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
26 |
27 | /**
28 | * Determine notification permission
29 | * 判断通知权限
30 | *
31 | * @param context
32 | * @return
33 | */
34 | public static boolean isNotificationEnabled(Context context) {
35 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
36 | return isEnableV26(context);
37 | } else {
38 | return isEnableV19(context);
39 | }
40 |
41 |
42 | }
43 |
44 | /**
45 | * Go to set notification permissions
46 | * 去设置通知权限
47 | *
48 | * @param mContext
49 | */
50 | public static void gotoAppSettings(Context mContext) {
51 |
52 | Intent intent = new Intent();
53 | if (Build.VERSION.SDK_INT >= 26) {
54 | // android 8.0引导
55 | intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
56 | intent.putExtra("android.provider.extra.APP_PACKAGE", mContext.getPackageName());
57 | } else if (Build.VERSION.SDK_INT >= 21) {
58 | // android 5.0-7.0
59 | intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
60 | intent.putExtra("app_package", mContext.getPackageName());
61 | intent.putExtra("app_uid", mContext.getApplicationInfo().uid);
62 | } else {
63 | // 其他
64 | intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
65 | intent.setData(Uri.fromParts("package", mContext.getPackageName(), null));
66 | }
67 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
68 | mContext.startActivity(intent);
69 | }
70 |
71 | /**
72 | * Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
73 | * 4.4 and above
74 | *
75 | * @param context
76 | * @return
77 | */
78 | public static boolean isEnableV19(Context context) {
79 | AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
80 | ApplicationInfo appInfo = context.getApplicationInfo();
81 | String pkg = context.getApplicationContext().getPackageName();
82 | int uid = appInfo.uid;
83 |
84 | Class appOpsClass;
85 | try {
86 | appOpsClass = Class.forName(AppOpsManager.class.getName());
87 | Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE,
88 | String.class);
89 | Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
90 |
91 | int value = (Integer) opPostNotificationValue.get(Integer.class);
92 | return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) == AppOpsManager.MODE_ALLOWED);
93 |
94 | } catch (ClassNotFoundException e) {
95 | e.printStackTrace();
96 | } catch (NoSuchMethodException e) {
97 | e.printStackTrace();
98 | } catch (NoSuchFieldException e) {
99 | e.printStackTrace();
100 | } catch (InvocationTargetException e) {
101 | e.printStackTrace();
102 | } catch (IllegalAccessException e) {
103 | e.printStackTrace();
104 | }
105 | return false;
106 | }
107 |
108 | /**
109 | * Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
110 | * For devices 8.0 and above
111 | *
112 | * @param context
113 | * @return
114 | */
115 | public static boolean isEnableV26(Context context) {
116 | try {
117 | NotificationManager notificationManager = (NotificationManager)
118 | context.getSystemService(Context.NOTIFICATION_SERVICE);
119 | Method sServiceField = notificationManager.getClass().getDeclaredMethod("getService");
120 | sServiceField.setAccessible(true);
121 | Object sService = sServiceField.invoke(notificationManager);
122 |
123 | ApplicationInfo appInfo = context.getApplicationInfo();
124 | String pkg = context.getApplicationContext().getPackageName();
125 | int uid = appInfo.uid;
126 |
127 | Method method = sService.getClass().getDeclaredMethod("areNotificationsEnabledForPackage"
128 | , String.class, Integer.TYPE);
129 | method.setAccessible(true);
130 | return (boolean) method.invoke(sService, pkg, uid);
131 | } catch (Exception e) {
132 | e.printStackTrace();
133 | }
134 | return false;
135 | }
136 | }
137 |
138 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyShapeUtil.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.graphics.Color;
4 | import android.graphics.drawable.GradientDrawable;
5 |
6 | /**
7 | * 动态创建shape获得drawable
8 | *
9 | * @author by Zhang YanQiang
10 | * @date 2022/3/24.
11 | */
12 | public class EasyShapeUtil {
13 |
14 | /**
15 | * 创建一个Shape - GradientDrawable
16 | *
17 | * @param _strokeWidth - 沿边线厚度(px);无需传入-1
18 | * @param _roundRadius - 圆角半径(px);无需传入-1
19 | * @param _shape - shape绘制类型(GradientDrawable.RECTANGLE、oval等);无需传入-1,将采用默认的GradientDrawable.RECTANGLE
20 | * @param _strokeColor - 沿边线颜色;无需传入null/""
21 | * @param _fillColor - 内部填充颜色
22 | * @return
23 | */
24 | public static GradientDrawable createShape(int _strokeWidth,
25 | int _roundRadius, int _shape,
26 | String _strokeColor, String _fillColor) {
27 | GradientDrawable gd = null;
28 | try {
29 | int strokeWidth = _strokeWidth; // px not dp
30 | int roundRadius = _roundRadius; // px not dp
31 | int strokeColor = -1;
32 | if (null != _strokeColor && !_strokeColor.equals("")) {
33 | strokeColor = Color.parseColor(_strokeColor);
34 | }
35 | int fillColor = Color.parseColor(_fillColor);
36 |
37 | gd = new GradientDrawable();
38 | gd.setColor(fillColor);
39 |
40 | if (-1 == _shape) {
41 | gd.setShape(GradientDrawable.RECTANGLE);
42 | } else {
43 | gd.setShape(_shape);
44 | }
45 |
46 | if (-1 != roundRadius) {
47 | gd.setCornerRadius(roundRadius);
48 | }
49 | if (-1 != strokeWidth && -1 != strokeColor) {
50 | gd.setStroke(strokeWidth, strokeColor);
51 | }
52 | } catch (Exception e) {
53 | e.printStackTrace();
54 | }
55 | return gd;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/java/com/zyq/easypermission/util/EasyViewUtil.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission.util;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.util.DisplayMetrics;
6 | import android.view.Display;
7 | import android.view.WindowManager;
8 |
9 | import androidx.annotation.RequiresApi;
10 |
11 | public class EasyViewUtil {
12 | /**
13 | * 根据手机分辨率从DP转成PX
14 | *
15 | * @param context
16 | * @param dpValue
17 | * @return
18 | */
19 | public static int dip2px(Context context, float dpValue) {
20 | float scale = context.getResources().getDisplayMetrics().density;
21 | return (int) (dpValue * scale + 0.5f);
22 | }
23 |
24 | /**
25 | * 将sp值转换为px值,保证文字大小不变
26 | *
27 | * @param spValue
28 | * @return
29 | */
30 | public static int sp2px(Context context, float spValue) {
31 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
32 | return (int) (spValue * fontScale + 0.5f);
33 | }
34 |
35 | /**
36 | * 根据手机的分辨率PX(像素)转成DP
37 | *
38 | * @param context
39 | * @param pxValue
40 | * @return
41 | */
42 | public static int px2dip(Context context, float pxValue) {
43 | float scale = context.getResources().getDisplayMetrics().density;
44 | return (int) (pxValue / scale + 0.5f);
45 | }
46 |
47 | /**
48 | * 将px值转换为sp值,保证文字大小不变
49 | *
50 | * @param pxValue
51 | * @return
52 | */
53 |
54 | public static int px2sp(Context context, float pxValue) {
55 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
56 | return (int) (pxValue / fontScale + 0.5f);
57 | }
58 |
59 | /**
60 | * 获取屏幕高度
61 | *
62 | * @param context
63 | * @return
64 | */
65 | public static int getScreenHeight(Context context) {
66 | DisplayMetrics dm = new DisplayMetrics();
67 | EasyViewUtil.getDisplay(context).getMetrics(dm);
68 | return dm.heightPixels;
69 | }
70 |
71 | /**
72 | * 获取屏幕宽度
73 | *
74 | * @param context
75 | * @return
76 | */
77 | public static int getScreenWidth(Context context) {
78 | DisplayMetrics dm = new DisplayMetrics();
79 | EasyViewUtil.getDisplay(context).getMetrics(dm);
80 | return dm.widthPixels;
81 | }
82 |
83 | /**
84 | * 是否是长屏幕
85 | *
86 | * @param context
87 | * @return
88 | */
89 | public static boolean isHighScreen(Context context) {
90 | try {
91 | float height = (float)getScreenHeight(context);
92 | float width = (float)getScreenWidth(context);
93 | //获取长宽比
94 | float ratio = height / width;
95 | return ratio > 1.9;
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | return false;
99 | }
100 | }
101 |
102 | /**
103 | * 最后一次点击的时间
104 | */
105 | private static long last_time = 0;
106 | /**
107 | * 设置连续点击间隔
108 | */
109 | public static void setIntervalClick(){
110 |
111 | long current_time = System.currentTimeMillis();
112 | long d_time = current_time - last_time;
113 | if (d_time <= 150) {
114 | return;
115 | } else {
116 | last_time = current_time;
117 | }
118 | }
119 |
120 | /**
121 | * 兼容API获取屏幕信息
122 | * @param context
123 | * @return
124 | */
125 | public static Display getDisplay(Context context){
126 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
127 | return getDisplayApiR(context);
128 | }else {
129 | return getDisplayApiL(context);
130 | }
131 | }
132 |
133 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
134 | private static Display getDisplayApiL(Context context){
135 | WindowManager wm=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
136 | return wm.getDefaultDisplay();
137 | }
138 | @RequiresApi(api = Build.VERSION_CODES.R)
139 | private static Display getDisplayApiR(Context context){
140 | return context.getDisplay();
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/drawable/bg_alert_white_shape8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/drawable/bg_button_blue_shape20.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/drawable/bg_button_blueline_shape20.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/layout/alert_info_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
22 |
23 |
32 |
33 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/layout/dialog_info_middle.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
22 |
23 |
34 |
42 |
52 |
53 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/values-en/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | The APP needs to be authorized
3 | Go to "APP info -> permissions" to grant!
4 | Understand
5 | Cancel
6 |
7 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #0086f6
4 | #ffffff
5 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 需要给该应用授权
3 | 请到 “应用信息 -> 权限” 中授予!
4 | 去打开
5 | 取消
6 |
7 |
--------------------------------------------------------------------------------
/easypermissionlib/src/main/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/easypermissionlib/src/test/java/com/zyq/easypermission/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zyq.easypermission;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | android.enableJetifier=true
10 | android.useAndroidX=true
11 | org.gradle.jvmargs=-Xmx1536m
12 | # When configured, Gradle will run in incubating parallel mode.
13 | # This option should only be used with decoupled projects. More details, visit
14 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
15 | # org.gradle.parallel=true
16 |
17 |
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/githubZYQ/easypermission/1018b79e1de8c99d017b4fc9676efec10c5c73d4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Jun 03 11:40:41 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':easypermissionlib'
2 |
--------------------------------------------------------------------------------