Android扫描蓝牙问题,你是不是位置权限和GPS都打开了还是扫不出东西

看看你的问题是否一样

首先你检查一下,你手机是不是把GPS打开了(Android10后搜索蓝牙要打开GPS),再看一下你的app在系统设置里面的位置权限是不是已经打开。如果都打开,但按照别人的demo、博客执行的搜索蓝牙的代码,发现什么都搜不到,不过另外一台手机同样的app同样的代码,woc咋那台手机就能搜出蓝牙,这台手机就不行。
那接下来这样试一下,搜不出蓝牙的那台手机,你自己去系统设置,手动把位置权限关了,然后又手动把权限打开,再试一下看是不是就能把蓝牙搜出来了,如果是……
恭喜你,你的问题可能和我一样。

心历路程

遇到这种问题是真坑爹,耗了我半天,无意中才发现了猫腻。下面是我遇到这问题到解决的整过程,如果大家不想看心历路程,可以直接跳到解决办法就行了。
首先自己写了个关于蓝牙功能的demo,在手机A上使用,可以搜到蓝牙没问题。那我就把demo蓝牙相关的代码移到公司要开发的项目中,一跑就糟糕,咋同样的代码公司的项目就扫不出蓝牙。
作为一个专业的程序员,肯定拿其他手机试试,拿了手机B试一下公司的项目,咦,可以搜到蓝牙啊。
于是第一反应肯定以为是机型问题,然后各种百度、谷歌,改啊改,调啊调,我就纳闷了。如果是机型的问题,为啥我一开始写的小demo在手机A上又能搜出东西。然后就无意中想到,发现到……

我的demo就一个小demo而已,我没有为它写一套动态申请权限的代码,因为公司项目已经有动态申请权限的代码,我的demo只管蓝牙行不行。所以我用demo的时候,都是先自己去系统把位置权限打开。又想到刚才公司项目装到手机B的时候,还没打开app之前,我好像就自己去系统给了它权限。这样一想,我就试一下把手机A对应app的那个位置权限关了,然后有打开,纳尼,突然就搜到蓝牙了。
然后经过多次跑代码验证,终于发现问题所在了。


首先看过官方文档的大家,都知道,我们是要申请以下这两个权限才能搜索蓝牙

Manifest.permission.ACCESS_COARSE_LOCATION
Manifest.permission.ACCESS_FINE_LOCATION

但这两个权限的打开,对于你手机上的表现,都是系统设置里面的位置权限打开了。打个比方,就像我的项目,以前它已经申请过Manifest.permission.ACCESS_COARSE_LOCATION的权限,那还要加一个权限,那我就加咯。

if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                PermissionManager.instance().with(this).request(new OnPermissionCallback() {
                    @Override
                    public void onRequestAllow(String permissionName) {
                    }

                    @Override
                    public void onRequestRefuse(String permissionName) {
                        finish();
                    }

                    @Override
                    public void onRequestNoAsk(String permissionName) {
                        finish();
                    }
                }, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);
            }

直接拿以前类似的代码搬过来,然后最后那里加个逗号和Manifest.permission.ACCESS_FINE_LOCATION,那就申请多个权限啦,就是这样写坑了自己半天。

这段话才是关键。 前面的其实看不看都没所谓,关键的就是下面这段结果,经我验证:

  1. 假如你自己去系统设置把位置权限打开,系统就会赋予你,这两个权限ACCESS_COARSE_LOCATION
    ACCESS_FINE_LOCATION
  2. 但假如你是用代码动态申请了ACCESS_COARSE_LOCATION权限,然后发现系统设置那里位置权限的确打开了,就以为自己应用也有了ACCESS_FINE_LOCATION权限,那你就大错特错了。

由于我在项目中判断权限那里,只判断ACCESS_COARSE_LOCATION是否已经有,而项目以前动态申请过这个权限,所以上面的if判断代码就不会走进去,去申请ACCESS_FINE_LOCATION了。
一开始我觉得这样写没什么问题,因为判断ACCESS_COARSE_LOCATION就知道那个位置权限有没有打开啦,现在才知道原来差别这么大。然后我就改成下面这样:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                PermissionManager.instance().with(this).request(new OnPermissionCallback() {
                    @Override
                    public void onRequestAllow(String permissionName) {
                        Log.e("test", "aaaaa");
                    }

                    @Override
                    public void onRequestRefuse(String permissionName) {
                        finish();
                    }

                    @Override
                    public void onRequestNoAsk(String permissionName) {
                        finish();
                    }
                }, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);
            }

改成上面这样,打印日志就能发现一个有趣的现象。以前每当你动态去申请一个权限的时候,手机系统会弹一个窗问要不要给app权限的嘛。
假如你手机已经动态申请过ACCESS_COARSE_LOCATION权限,然后再跑上面的代码,它判断了你没有ACCESS_FINE_LOCATION权限,所以就进入申请权限的逻辑,但这次系统就没弹窗,而是直接帮你允许了ACCESS_FINE_LOCATION这个权限,代码会直接跑进onRequestAllow方法里。

解决办法

同时检查是否有下面两个权限,并两个权限都去申请

Manifest.permission.ACCESS_COARSE_LOCATION
Manifest.permission.ACCESS_FINE_LOCATION
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED 
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                PermissionManager.instance().with(this).request(new OnPermissionCallback() {
                    @Override
                    public void onRequestAllow(String permissionName) {
                        Log.e("test", "aaaaa");                     
                    }

                    @Override
                    public void onRequestRefuse(String permissionName) {
                        finish();
                    }

                    @Override
                    public void onRequestNoAsk(String permissionName) {
                        finish();
                    }
                }, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);
            }
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值