Skip to content

如何检测程序是否获得了某项权限? #174

Open
@start141

Description

@start141

众所周知,MIUI、Flyme等Android定制系统在程序请求打开相机、录音等操作时,系统会先弹出对话框提示用户是否允许程序执行这些操作,如果用户选择允许,则接下来的操作一切正常,如果用户选择拒绝之后,程序后面的工作将无法正常允许,甚至崩溃。

提问:在这种情况下,如何判断用户是拒绝还是允许了操作?
目前我知道用try catch可以粗暴的判断,但我不确定所有的权限请求被拒绝后都会抛异常。

各位有更好的办法吗?

Activity

t12x3456

t12x3456 commented on May 21, 2015

@t12x3456

PackageManager有个checkPermission(String permName, String pkgName)方法可以判断.返回PackageManager.PERMISSION_GRANTED即为已经授权,PackageManager.PERMISSION_DENIED为被拒绝. 当然这里要注意一点, 这个api没办法在所有机型上通用,某些系统上把特定权限的名字已经修改掉了. 另外定位权限比较特殊,没办法同步获取是否已授权.

start141

start141 commented on May 21, 2015

@start141
Author

checkPermission测试的是manifest有没有注册某项权限吧,并不能判断用户是否允许了某项权限。

t12x3456

t12x3456 commented on May 21, 2015

@t12x3456

@start141 ,checkPermission就是用来判断用户是否授予权限的,比如是否开启获取联系人,录音的权限,你可以看下api,并且检验下,这个是具体的api解释:

public abstract int checkPermission (String permName, String pkgName)

Added in API level 1
Check whether a particular package has been granted a particular permission.

Parameters
permName The name of the permission you are checking for,
pkgName The name of the package you are checking against.
Returns
If the package has the permission, PERMISSION_GRANTED is returned. If it does not have the permission, PERMISSION_DENIED is returned.
See Also
PERMISSION_GRANTED
PERMISSION_DENIED

start141

start141 commented on May 21, 2015

@start141
Author

api的注释我的理解是指menifest注册了权限就返回PERMISSION_GRANTED,否则就返回PERMISSION_DENIED。也可能是我理解错了。

不过重要的是这个方法我测试过,无效。

newtonker

newtonker commented on Aug 24, 2015

@newtonker

@start141 楼主这个问题,最后有没有什么解决方案?

start141

start141 commented on Aug 24, 2015

@start141
Author

@newtonker 我目前知道的只有try catch,我们的app里面目前是用try catch来判断的。

newtonker

newtonker commented on Aug 24, 2015

@newtonker

@start141 本来我也用的try catch,在其他手机上(华为,小米,魅族低版本)都是好的。但是在测试MX5 Android 5.1的系统时,在打开相机的那一刻,如果在弹出的权限对话框中拒绝了权限,会直接闪退。报的闪退居然是RuntimeException,Method called after release() 。但是我表示都正常release了。

public void releaseCamera() {
    if (camera != null) {
        camera.setPreviewCallback(null);
        camera.stopPreview();
        camera.release(); 
        camera = null;
    }
}
Qixingchen

Qixingchen commented on Aug 24, 2015

@Qixingchen

Method called after release() 的意思是,你在release后又进行了操作。
可能是系统自动帮你release了,也可能是你的release函数在其他地方调用了,具体看报错栈才知道。

2015-08-24 13:50 GMT+08:00 newtonker notifications@github.com:

@start141 https://github.com/start141 本来我也用的try
catch,在其他手机上(华为,小米,魅族低版本)都是好的。但是在测试MX5 Android
5.1的系统时,在打开相机的那一刻,如果在弹出的权限对话框中拒绝了权限,会直接闪退。报的闪退居然是RuntimeException,Method
called after release() 。但是我表示都正常release了。
public void releaseCamera() {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
}


Reply to this email directly or view it on GitHub
#174 (comment)
.

start141

start141 commented on Aug 24, 2015

@start141
Author

这个问题可能是因为你在多个地方release()了,你可以在release()之后设置camera=null,下次release()的时候先判断camera是不是等于null。
还有可能是你try catch之后没有return后面的操作。

总之你看一次Log的错误行数吧,跟一下流程。@Qixingchen 已经说了原因。

newtonker

newtonker commented on Aug 24, 2015

@newtonker

@Qixingchen , @start141 多谢你们两个人的帮助,我最终还是通过try catch解决了。MX 5 的相机权限和之前碰到的不一样。之前碰到华为,小米里弹出权限对话框时,如果禁止了相机权限,camera对象会返回null, MX 5 禁止了之后还是会返回一个相机对象,导致if(null != camera)方法判断无效了,所以会出现上面的问题。扩大了Exception的范围,捕获这个异常就行了。

1207229280

1207229280 commented on Feb 12, 2016

@1207229280

我没做任何处理的话也不会出现异常 所以没办法catch 日志里只说明app不允许跳转

1207229280

1207229280 commented on Feb 12, 2016

@1207229280

照相机权限

l123456789jy

l123456789jy commented on Mar 14, 2016

@l123456789jy

手机里面不是有个应用权限列表吗?看下framework层的那个列表的权限状态,如何获取,能获取到这个我觉得就可以了!

Labmem003

Labmem003 commented on May 12, 2016

@Labmem003

各位,除了try catch 外有新的进展吗?我在尝试发短信,需要检查android.permission.SEND_SMS权限,但是发短信这个调用连异常都不会抛出。。。

imhet

imhet commented on May 30, 2016

@imhet

@Labmem003 小米手机上拒绝发送短信的权限异常确实没有抛出,可以加一个超时(比如3秒)没有返回短信是否发送成功的消息则判断发送短信权限被拒绝。

26 remaining items

H-mate1001

H-mate1001 commented on Aug 23, 2017

@H-mate1001

至今..... 问题依旧啊 采用 Rx 的 RxPermissions 库来处理改问题,得到的结果是 Android 6.0 以上(包含6.0)均正确, 测试机型 : 小米 4C 5.1.1、华为 5.1.1 、华为 6.0、三星 5.0 、三星、6.0 , 7.0 ;
其中 小米 4C 5.1.1、华为 5.1.1 ;返回结果 均 为 true 也就是权限均存在,在进入 OCR 页面时 UI 变形 SurfaceView 绘制失败,后修改为 Google 的 http://wuxiaolong.me/2017/03/07/easypermissions/ ; 结果一致,
以下为 Google easypermissions 源码
/**
* Check if the calling context has a set of permissions.
*
* @param context the calling context.
* @param perms one ore more permissions, such as {@link Manifest.permission#CAMERA}.
* @return true if all permissions are already granted, false if at least one permission is not
* yet granted.
* @see Manifest.permission
*/
public static boolean hasPermissions(Context context, @nonnull String... perms) {
// Always return true for SDK < M, let the system deal with the permissions
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log.w(TAG, "hasPermissions: API version < M, returning true by default");

        // DANGER ZONE!!! Changing this will break the library.
        return true;
    }

    // Null context may be passed if we have detected Low API (less than M) so getting
    // to this point with a null context should not be possible.
    if (context == null) {
        throw new IllegalArgumentException("Can't check permissions for null context");
    }

    for (String perm : perms) {
        if (ContextCompat.checkSelfPermission(context, perm)
                != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }

    return true;
}
tianshaokai

tianshaokai commented on Aug 23, 2017

@tianshaokai

@forYueji 你把问题搞复杂了

  1. 你要先弄明白你的绘制框变形是什么问题导致的
  2. 如果变形的手机你可以在程序里手动给app设置权限,看是否会变形
  3. 如果不变形,那说明没问题,如果变形就是说明你的扫描代码就有问题
  4. 扫描框设置权限应该在view加载之前赋予权限就行了
H-mate1001

H-mate1001 commented on Aug 23, 2017

@H-mate1001

@tianshaokai 谢谢 提醒 ,上述问题可能没有表述清楚,在 自定义相机的过程中失败的原因是因为 我在设置中手动将相机 权限设置为拒绝状态 ,那么在 camera 获取的时候 出现异常了, 在这里我对 camera 出现异常 做了 处理,目的是为了防止 闪退,那么外层所表现出现的结果就是 UI 变形,这其实是一个 错误的 UI ,即 因为相机权限 设置为拒绝状态

tianshaokai

tianshaokai commented on Aug 23, 2017

@tianshaokai

@forYueji 你可以拒绝后不让进入扫一扫页面啊,必须同意

tianshaokai

tianshaokai commented on Aug 23, 2017

@tianshaokai

@forYueji 你是做的什么功能啊,开源吗看看你的代码

CaptainJno

CaptainJno commented on Aug 23, 2017

@CaptainJno

@forYueji 直接try catch,捕获到异常,就提醒用户去设置界面手动开启摄像头权限。
可参考这篇文章:http://www.jianshu.com/p/1f072a248a37

H-mate1001

H-mate1001 commented on Aug 23, 2017

@H-mate1001

@tianshaokai 是这样的 ,我这是在这深究这个问题呢 😄 😄

imkarl

imkarl commented on Sep 3, 2017

@imkarl

oppo checkPermission(Manifest.permission.READ_CONTACTS)始终返回true,即使禁用了该权限
我测试的机型:OPPO R9s(android 6.0),有什么方法可以辨别权限是否被禁用吗?

xinglonglcu

xinglonglcu commented on Sep 13, 2017

@xinglonglcu

@luffykou 我也遇到这种问题,vivo 不会报出Exception,这种方法不适用,你是怎么解决的呢 ??

waylife

waylife commented on Oct 31, 2017

@waylife

如果简单的判断摄像头是否异常来区分是否有权限,那如何区分摄像头是真的有问题(比如硬件损坏)还是真的是没有权限呢?

skylixinxin

skylixinxin commented on Jan 29, 2018

@skylixinxin

oppo checkPermission(Manifest.permission.READ_CONTACTS)始终返回true,即使禁用了该权限
我测试的机型:OPPO R9s(android 6.0),有什么方法可以辨别权限是否被禁用吗?同样遇到了这个问题,有人能给解答一下吗

WindyIT

WindyIT commented on Jul 9, 2018

@WindyIT

public boolean hasPermission(@nonnull Context context, @nonnull List permissions) {
if (VERSION.SDK_INT < 23) {
return true;
} else {
Iterator var3 = permissions.iterator();

        int result;
        do {
            if (!var3.hasNext()) {
                return true;
            }

            String permission = (String)var3.next();
            result = context.checkPermission(permission, Process.myPid(), Process.myUid());
            if (result == -1) {
                return false;
            }

            String op = AppOpsManager.permissionToOp(permission);
            if (TextUtils.isEmpty(op)) {
                return true;
            }

            AppOpsManager appOpsManager = (AppOpsManager)context.getSystemService(AppOpsManager.class);
            result = appOpsManager.noteProxyOp(op, context.getPackageName());
        } while(result == 0);

        return false;
    }
}

摘自CPermission 可以尝试下 @skylixinxin

earthWo

earthWo commented on Nov 21, 2018

@earthWo

@luffykou 我也遇到这种问题,vivo 不会报出Exception,这种方法不适用,你是怎么解决的呢 ??

用了这篇博客的方法,测试有效。
https://blog.csdn.net/lvwenbo0107/article/details/81035831

EspoirX

EspoirX commented on Mar 12, 2019

@EspoirX

我就问下,vivo 怎么判断有没有悬浮窗权限,这个适配真的是非常操蛋。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @zijing07@imkarl@waylife@gordonpro@Qixingchen

        Issue actions

          如何检测程序是否获得了某项权限? · Issue #174 · android-cn/android-discuss