guolindev / PermissionX

An open source Android library that makes handling runtime permissions extremely easy.
Apache License 2.0
3.35k stars 387 forks source link

通讯录没有给权限,然后PermissionX却回调回来权限是通过的 #43

Closed zhouhuandev closed 3 years ago

zhouhuandev commented 3 years ago

最近在开发关于读取通讯录的一款App,在开发的过程当中,先使用了PermissionX进行请求可以读写通讯录的操作权限

PermissionUtil.checkContacts(activity,(allGranted, grantedList, deniedList) -> {
                                if (allGranted){
                                   Log.i(TAG,"权限通过");
                                }
                            });

主要读取了以上的权限,但是回调回来的结果竟然是通过,导致项目多次无法正常的运行

现在又抓紧时间使用了其他的方式进行了权限的请求,还望做着可以查一下为什么会出现这样的问题

guolindev commented 3 years ago

额,你确定这段代码是使用的PermissionX?

zhouhuandev commented 3 years ago

额,你确定这段代码是使用的PermissionX?

不好意思,郭老师,忘记给您贴出来代码了

我使用您这套开源项目为了方便使用,简单封装了一个工具类使用,主要就是使用到了申请通讯录的地方,明明用户没有给权限,却回来了权限通过,不清楚是我的操作有误,还是哪里的问题,您参考一下

/**
 * Describe:
 * Android运行时权限申请
 * <p>
 * 需要申请的权限列表,<a "href=https://developer.android.google.cn/guide/topics/security/permissions.html?hl=zh-cn#normal-dangerous">Google Doc</a>
 * <p>
 * -CALENDAR<br>
 * {@link android.Manifest.permission#READ_CALENDAR}<br>
 * {@link android.Manifest.permission#WRITE_CALENDAR}<br>
 * <p>
 * -CAMERA<br>
 * {@link android.Manifest.permission#CAMERA}<br>
 * <p>
 * -CONTACTS<br>
 * {@link android.Manifest.permission#READ_CONTACTS}<br>
 * {@link android.Manifest.permission#WRITE_CONTACTS}<br>
 * {@link android.Manifest.permission#GET_ACCOUNTS}<br>
 * <p>
 * -LOCATION<br>
 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}<br>
 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}<br>
 * <p>
 * -MICROPHONE<br>
 * {@link android.Manifest.permission#RECORD_AUDIO}<br>
 * <p>
 * -PHONE<br>
 * {@link android.Manifest.permission#READ_PHONE_STATE}<br>
 * {@link android.Manifest.permission#CALL_PHONE}<br>
 * {@link android.Manifest.permission#READ_CALL_LOG}<br>
 * {@link android.Manifest.permission#WRITE_CALL_LOG}<br>
 * {@link android.Manifest.permission#ADD_VOICEMAIL}<br>
 * {@link android.Manifest.permission#USE_SIP}<br>
 * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS}<br>
 * <p>
 * -SENSORS<br>
 * {@link android.Manifest.permission#BODY_SENSORS}<br>
 * <p>
 * -SMS<br>
 * {@link android.Manifest.permission#SEND_SMS}<br>
 * {@link android.Manifest.permission#RECEIVE_SMS}<br>
 * {@link android.Manifest.permission#READ_SMS}<br>
 * {@link android.Manifest.permission#RECEIVE_WAP_PUSH}<br>
 * {@link android.Manifest.permission#RECEIVE_MMS}<br>
 * <p>
 * -STORAGE<br>
 * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}<br>
 * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE}<br>
 * <p>权限请求工具</p>
 *
 * @author zhouhuan
 * @Date 2020/9/16
 */
public class PermissionUtil {

    /**
     * 检查网络权限
     *
     * @param activity
     */
    public static void checkInternet(final Activity activity) {
        checkInternet(activity, false, null);
    }

    /**
     * 检查网络权限
     *
     * @param fragment
     */
    public static void checkInternet(final Fragment fragment) {
        checkInternet(fragment, false, null);
    }

    /**
     * 检查网络权限
     *
     * @param activity
     */
    public static void checkInternet(final Activity activity, OnRequestCallback callback) {
        checkInternet(activity, false, callback);
    }

    /**
     * 检查网络权限
     *
     * @param fragment
     */
    public static void checkInternet(final Fragment fragment, OnRequestCallback callback) {
        checkInternet(fragment, false, callback);
    }

    /**
     * 检查网络权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkInternet(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.INTERNET);
    }

    /**
     * 检查网络权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkInternet(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.INTERNET);
    }

    /**
     * 检查存储权限
     *
     * @param activity
     */
    public static void checkStorage(final Activity activity) {
        checkStorage(activity, false, null);
    }

    /**
     * 检查存储权限
     *
     * @param fragment
     */
    public static void checkStorage(final Fragment fragment) {
        checkStorage(fragment, false, null);
    }

    /**
     * 检查存储权限
     *
     * @param activity
     */
    public static void checkStorage(final Activity activity, OnRequestCallback callback) {
        checkStorage(activity, false, callback);
    }

    /**
     * 检查存储权限
     *
     * @param fragment
     */
    public static void checkStorage(final Fragment fragment, OnRequestCallback callback) {
        checkStorage(fragment, false, callback);
    }

    /**
     * 检查存储权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkStorage(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.READ_CONTACTS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    /**
     * 检查存储权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkStorage(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.READ_CONTACTS, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    /**
     * 检查通讯录权限
     *
     * @param activity
     */
    public static void checkContacts(final Activity activity, OnRequestCallback callback) {
        checkContacts(activity, false, callback);
    }

    /**
     * 检查通讯录权限
     *
     * @param fragment
     */
    public static void checkContacts(final Fragment fragment, OnRequestCallback callback) {
        checkContacts(fragment, false, callback);
    }

    /**
     * 检查通讯录权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkContacts(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS, Manifest.permission.GET_ACCOUNTS);
    }

    /**
     * 检查通讯录权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkContacts(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS, Manifest.permission.GET_ACCOUNTS);
    }

    /**
     * 检查定位权限
     *
     * @param activity
     */
    public static void checkLocation(final Activity activity) {
        checkLocation(activity, false, null);
    }

    /**
     * 检查定位权限
     *
     * @param fragment
     */
    public static void checkLocation(final Fragment fragment) {
        checkLocation(fragment, false, null);
    }

    /**
     * 检查定位权限
     *
     * @param activity
     */
    public static void checkLocation(final Activity activity, OnRequestCallback callback) {
        checkLocation(activity, false, callback);
    }

    /**
     * 检查定位权限
     *
     * @param fragment
     */
    public static void checkLocation(final Fragment fragment, OnRequestCallback callback) {
        checkLocation(fragment, false, callback);
    }

    /**
     * 检查定位权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkLocation(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION);
    }

    /**
     * 检查定位权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkLocation(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION);
    }

    /**
     * 检查日历权限
     *
     * @param activity
     */
    public static void checkCalendar(final Activity activity, OnRequestCallback callback) {
        checkCalendar(activity, false, callback);
    }

    /**
     * 检查日历权限
     *
     * @param fragment
     */
    public static void checkCalendar(final Fragment fragment, OnRequestCallback callback) {
        checkCalendar(fragment, false, callback);
    }

    /**
     * 检查日历权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkCalendar(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR);
    }

    /**
     * 检查日历权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkCalendar(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR);
    }

    /**
     * 检查摄像机权限
     *
     * @param activity
     */
    public static void checkCamera(final Activity activity) {
        checkCamera(activity, false, null);
    }

    /**
     * 检查摄像机权限
     *
     * @param fragment
     */
    public static void checkCamera(final Fragment fragment) {
        checkCamera(fragment, false, null);
    }

    /**
     * 检查摄像机权限
     *
     * @param activity
     */
    public static void checkCamera(final Activity activity, OnRequestCallback callback) {
        checkCamera(activity, false, callback);
    }

    /**
     * 检查摄像机权限
     *
     * @param fragment
     */
    public static void checkCamera(final Fragment fragment, OnRequestCallback callback) {
        checkCamera(fragment, false, callback);
    }

    /**
     * 检查摄像机权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkCamera(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.CAMERA);
    }

    /**
     * 检查摄像机权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkCamera(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.CAMERA);
    }

    /**
     * 检查麦克风权限
     *
     * @param activity
     */
    public static void checkMicroPhone(final Activity activity) {
        checkMicroPhone(activity, false, null);
    }

    /**
     * 检查麦克风权限
     *
     * @param fragment
     */
    public static void checkMicroPhone(final Fragment fragment) {
        checkMicroPhone(fragment, false, null);
    }

    /**
     * 检查麦克风权限
     *
     * @param activity
     */
    public static void checkMicroPhone(final Activity activity, OnRequestCallback callback) {
        checkMicroPhone(activity, false, callback);
    }

    /**
     * 检查麦克风权限
     *
     * @param fragment
     */
    public static void checkMicroPhone(final Fragment fragment, OnRequestCallback callback) {
        checkMicroPhone(fragment, false, callback);
    }

    /**
     * 检查麦克风权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkMicroPhone(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.RECORD_AUDIO);
    }

    /**
     * 检查麦克风权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkMicroPhone(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.RECORD_AUDIO);
    }

    /**
     * 检查手机状态权限
     *
     * @param activity
     */
    public static void checkPhone(final Activity activity) {
        checkPhone(activity, false, null);
    }

    /**
     * 检查手机状态权限
     *
     * @param fragment
     */
    public static void checkPhone(final Fragment fragment) {
        checkPhone(fragment, false, null);
    }

    /**
     * 检查手机状态权限
     *
     * @param activity
     */
    public static void checkPhone(final Activity activity, OnRequestCallback callback) {
        checkPhone(activity, false, callback);
    }

    /**
     * 检查手机状态权限
     *
     * @param fragment
     */
    public static void checkPhone(final Fragment fragment, OnRequestCallback callback) {
        checkPhone(fragment, false, callback);
    }

    /**
     * 检查手机状态权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkPhone(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback) {
        request(activity, isForwardToSettings, callback, Manifest.permission.READ_PHONE_STATE, Manifest.permission.CALL_PHONE);
    }

    /**
     * 检查手机状态权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     */
    public static void checkPhone(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback) {
        request(fragment, isForwardToSettings, callback, Manifest.permission.READ_PHONE_STATE, Manifest.permission.CALL_PHONE);
    }

    /**
     * 请求权限
     *
     * @param activity
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     * @param callback
     * @param permissions         权限
     */
    public static void request(final Activity activity, boolean isForwardToSettings, OnRequestCallback callback, String... permissions) {
        PermissionCollection init = PermissionX.init((FragmentActivity) activity);
        PermissionBuilder permissionBuilder = init.permissions(permissions);
        permissionBuilder.onExplainRequestReason((scope, deniedList) -> scope.showRequestReasonDialog(deniedList, "核心基础基于这些权限", "确定", "取消"));
        if (isForwardToSettings) {
            permissionBuilder.onForwardToSettings((scope, deniedList) -> scope.showForwardToSettingsDialog(deniedList, "您需要手动在“设置”中允许必要的权限", "确定", "取消"));
        }
        permissionBuilder.request((allGranted, grantedList, deniedList) -> {
            if (callback != null) {
                callback.onResult(allGranted, grantedList, deniedList);
            }
        });
    }

    /**
     * 请求权限
     *
     * @param fragment
     * @param isForwardToSettings true:转到设置中心 false:不转入设置中心
     * @param callback
     * @param permissions
     */
    public static void request(final Fragment fragment, boolean isForwardToSettings, OnRequestCallback callback, String... permissions) {
        PermissionCollection init = PermissionX.init(fragment);
        PermissionBuilder permissionBuilder = init.permissions(permissions);
        permissionBuilder.onExplainRequestReason((scope, deniedList) -> scope.showRequestReasonDialog(deniedList, "核心基础基于这些权限", "确定", "取消"));
        if (isForwardToSettings) {
            permissionBuilder.onForwardToSettings((scope, deniedList) -> scope.showForwardToSettingsDialog(deniedList, "您需要手动在“设置”中允许必要的权限", "确定", "取消"));
        }
        permissionBuilder.request((allGranted, grantedList, deniedList) -> {
            if (callback != null) {
                callback.onResult(allGranted, grantedList, deniedList);
            }
        });
    }

    public interface OnRequestCallback {
        /**
         * Callback for the request result.
         *
         * @param allGranted  Indicate if all permissions that are granted.
         * @param grantedList All permissions that granted by user.
         * @param deniedList  All permissions that denied by user.
         */
        void onResult(boolean allGranted, List<String> grantedList, List<String> deniedList);

    }
}
guolindev commented 3 years ago

从代码上看,感觉你的写法很正确,并没有发现什么明显的问题。

但是从表现上看,我不知道具体的表现是什么样子,是弹出了通讯录权限申请框,然后你点击了拒绝,结果却回调了授权吗?

zhouhuandev commented 3 years ago

嗯呢,代码上应该是没有问题,具体的表现形式记得是没有进行提示申请权限,然后直接就返回了 true 进行授予,然后就导致报错,提示权限不足。

zhouhuandev commented 3 years ago

在进入到手机的应用设置里面的权限管理里面,读取通讯录的权限并未进行更改,权限依然是询问状态。所以就导致失败

guolindev commented 3 years ago

这个让我也感觉有点困惑了,因为Permissionx并没有自己发明权限的新用法,只是在原生API上面做了层封装,所以理论上,原生API返回的是什么,Permissionx返回的就是什么。

那么你或许可以试一试,在那台手机上,用原生API的方式去请求通讯录权限,看看是什么样的结果呢?

zhouhuandev commented 3 years ago

嗯呢,谢谢郭老师,这个主意不错,我再搞个测试demo看看具体问题看看是出自哪里。把Permissionx源码依赖进去debug看看,然后使用原生的方式再试试看。试出来给过到时候给您反馈一下。

zhouhuandev commented 3 years ago

郭老师,就使用这一句话,然后点击按钮获取权限,可以弹出授予的框,但是弹出以后,点击始终允许,就打印出下面的Log了。

我使用的测试机环境

button.setOnClickListener {
            PermissionUtil.checkContacts(this,object :PermissionUtil.OnRequestCallback{
                override fun onResult(
                    allGranted: Boolean,
                    grantedList: List<String?>?,
                    deniedList: List<String?>?
                ) {
                    if (allGranted){
                        Log.i(TAG,"权限通过")
                    }else{
                        Log.i(TAG,"权限未通过")
                    }
                }
            })
        }
2020-11-29 23:13:14.148 11169-11169/com.sdzhaotai.zt.kotlintestdemo I/MainActivity: 权限未通过
2020-11-29 23:13:14.202 1414-2370/? D/HwGameAssistantController: pid=11169, uid=10274, component=ComponentInfo{com.sdzhaotai.zt.kotlintestdemo/com.sdzhaotai.zt.kotlintestdemo.MainActivity}
2020-11-29 23:14:05.241 11169-11169/com.sdzhaotai.zt.kotlintestdemo I/MainActivity: 权限未通过
2020-11-29 23:14:05.252 1414-7650/? D/HwGameAssistantController: pid=11169, uid=10274, component=ComponentInfo{com.sdzhaotai.zt.kotlintestdemo/com.sdzhaotai.zt.kotlintestdemo.MainActivity}
guolindev commented 3 years ago

我建议你可以把grantedList和deniedList也一起打印一下,看看到底什么权限授权了,什么权限没授权,别光依赖allGranted这一个变量,这样很难发现真正的问题。

zhouhuandev commented 3 years ago

嗯呢, 我详细的测试测试看看是什么原因呢,谢谢郭老师

guolindev commented 3 years ago

怎么样,后来有没有找到新的原因?如果没有新的反馈的话,我就准备把这个issue关闭掉了。

zhouhuandev commented 3 years ago

嗯呢,最后还是没有找到原因,也debug了,但是,写的demo都是好好的去按照正常的流程去走的。也正常的去请求权限。放到业务里面有时候就会出现这个问题。但是会不会有这样一个问题呢,用户拒绝了权限,然后再次进行请求,又或者是用户使用了仅在使用过程中允许权限呢,这几个过程的话,我暂时没有测试出来。

guolindev commented 3 years ago

如果你在自己手机上无法重现,那就不好测试这个问题了,我可能也给不出什么更好的建议,获取加点日志打印,然后把用户那边的日志上传到服务器,或许能对定位问题有所帮助。