ChatGPT解决这个技术问题 Extra ChatGPT

需要为 Android 6.0 上的蓝牙低功耗扫描启用位置

升级到 Android 6.0 版后,蓝牙低功耗 (BLE) 扫描仅在设备上启用了定位服务的情况下才能工作。请参阅此处以供参考:Bluetooth Low Energy startScan on Android 6.0 does not find devices

基本上,您需要为应用程序和手机启用权限。这是一个错误吗?是否可以在没有实际启用定位服务的情况下进行扫描?我不想为我的所有应用程序提供位置。

编辑我没有提到我正在使用 API 21 中提供的 BluetoothLeScanner 中的 startScan() 方法。我可以接受此方法所需的清单中的课程和精细位置权限。我只是不希望我的应用程序的用户必须在他们的设备(GPS 等)上启用位置服务才能使用我的应用程序。

以前,startScan() 方法将在手机上禁用位置服务的情况下运行并返回结果。然而,在 Marshmallow 上,当手机上未启用定位服务并且课程/精细定位权限仍在清单中时,相同的应用程序将“扫描”但静默失败并且不返回任何结果。

您使用什么设备?我在使用 Moto G 第二代时遇到了同样的问题。 Moto G 1st Generation 和 Nexus 6 使用完全相同的代码运行良好,无需明确启用定位服务。
我在任何运行 Marshmallow 的设备上都注意到了它 - Nexus 5X、三星 S6、三星 S7、LG G4

V
V-PTR

不,这不是错误。

issue 已提交给 Google,他们回复说这是预期的行为,他们不会修复它。他们将开发人员引导至 this site,其中指出硬件标识符访问现在需要位置许可。现在,开发人员有责任让他们的用户了解需求。

然而,在这个问题中,它没有解决为什么需要定位服务(GPS 等),而且他们似乎不会重新讨论这个问题来解释这一点,因为它已被标记为预期行为。

回答问题的第二部分:是的,可以在不启用定位服务的情况下进行扫描。您可以使用 BluetoothAdapter.getDefaultAdapter().startDiscovery() 进行蓝牙经典扫描,这将在位置服务关闭的情况下工作。这将发现所有蓝牙设备、BLE 和其他设备。但是,如果 BLE 设备被视为 startScan() 的结果,它们将没有扫描记录。


谷歌声称这不是一个错误让我感到很冷。他们的态度很简单。
这并不是一个真正的错误 - 如果恶意应用程序开发人员可以扫描已知的蓝牙信标,那么他们可以通过询问位置权限来找出您的位置,而不会引起用户的怀疑。因此,不幸的是,请求 BLE 访问权限必须与请求您的大致位置相同。
让我看看我有没有这个直。 BLE 的最大优势是“LE”位,即低能量,这意味着减少了我的电池消耗。当然,为了获得这些节省,我必须打开 GPS,这是一种已知的电池消耗,因此否定了我可能从使用 BLE 中获得的任何电力节省。 /me 难以置信地摇头。
这难以置信。当然,如果谷歌担心 BLE 扫描被用来推断位置,他们应该为此添加一个单独的权限,而不是通过强制用户允许 GPS 访问来将婴儿和洗澡水一起扔出去!
@Pierre-LucPaour 强制打开 GPS 意味着其他实际使用位置服务的应用程序可以在幕后“合法”地使用它。用户手动关闭 GPS 的原因之一是为了防止应用程序定期使用它并耗尽电池电量,强制 GPS 搜索蓝牙是让用户知道他们的位置可能被使用的最反直觉的方式。
J
JiTHiN

我通过在 Gradle 文件中将 targetSdkVersion 设置为 22 解决了这个问题。您必须在清单中声明 ACCESS_COARSE_LOCATION,但即使用户从应用设置中拒绝此权限,BLE 扫描也将起作用。

这只是避免请求位置许可的一种技巧。最好针对最新的 android 版本。

编辑

此解决方案不应再使用,因为 Google Play 将要求新应用程序至少面向 Android 8.0(API 级别 26)。应用程序应请求位置许可以进行 BLE 扫描。


太谢谢了!您是否知道如何处理模拟 AltBeacon 等监控的库?没有位置就无法工作:(并且它们使用基本相同的机制......那么最小编译版本呢?@JiTHiN
从 23 降级到 22,它甚至可以在 Android 7.0 上运行。我最初的问题是您必须启用本地化,现在我可以扫描禁用本地化的 BLE 设备。
这是一个 hack,但这是不推荐最好针对最新的 sdk 版本。这样做的正确方法是在运行时请求 ACCESS_COARSE_LOCATION
这不再是一个解决方案(请参阅 developer.android.com/distribute/best-practices/develop/…“Google Play 将要求新应用从 2018 年 8 月 1 日起至少面向 Android 8.0(API 级别 26),并且从 2018 年 11 月 1 日起应用更新面向 Android 8.0。” )
I
Ivaylo Pankov

我发现在 Android 6 之后你必须授予 ACCESS_COARSE_LOCATION 权限。但在某些设备上,您的手机定位服务 (GPS) 也需要打开,以便您可以发现外围设备。我发现使用带有 Android 7.0 的 Nexus 5x。


Nexus 5x 和 Android 6 对我来说也是如此
Moto G5 plus 与 Android 7.1.1 相同
K
Kamal Kishore

我也在清单上试过这个,但没有请求许可,不知道为什么。您的应用程序是否在启动时提示位置权限?如果不是,我们需要request for permission on runtime

您还可以检查它以测试您的应用程序是否正常工作:

打开设置 > 应用程序 > YourApplication > 权限并启用位置,然后尝试扫描结果。

仅当您在清单上提供了 ACCESS_COARSE_LOCATION 时,才会在此处列出位置。


是的,您必须在运行时明确请求权限,并为设备打开位置服务。但我想知道是否有一种方法可以进行 BLE 扫描,而无需在运行时打开位置服务或请求课程位置权限。
请求权限是不够的,您还需要检查是否启用了位置服务。
为什么谷歌允许这个问题?说真的我不明白
N
Neuron

您可以使用 BluetoothAdapter.startDiscovery()
它将扫描蓝牙智能设备和经典蓝牙设备,但不需要启用位置服务。
(在 Android 6 上您仍需要 ACCESS_COARSE_LOCATION 权限。)

您可以在找到的设备上调用 BluetoothDevice.getType 来过滤蓝牙智能/低功耗设备。


b
batsheva

ACCESS_COARSE_LOCATION 添加到 Manifest 后,在运行时请求许可:

 public void checkPermission() {
            if (Build.VERSION.SDK_INT >= 23) {
                if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

            } else {
                ActivityCompat.requestPermissions(this, new String[]{
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION,}, 1);
            }
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
        } else {
            checkPermission();
        }
    }

为我工作!


a
antaki93

您可以使用 CompanionDeviceManager (API26) 扫描没有位置访问权限的 BLE 设备。 https://developer.android.com/reference/android/companion/CompanionDeviceManager


请注意,它在 Android 8 和 9 中不起作用甚至崩溃。我可以在 Pixel 3a 上使用它,但在我的三星测试设备上,系统服务只是崩溃了。所以不幸的是不是一个非常稳定的解决方案。
谢谢@Peterdk。我只是在实验中使用了这个组件。可惜没有好好发展。
当我使用过滤器扫描时,伴侣设备管理器在没有扫描过滤器的情况下崩溃(三星 Android 8),它可以工作。我认为这个功能不是一个稳定的解决方案。该文档也无济于事。
M
Michał Dobi Dobrzański

好吧,我查看了用 Eclipse 编写的代码,并在那里使用了 startScan (API 21) 函数,而没有在清单文件中声明位置内容。我仍然得到正确的回调。您是否尝试过在没有位置声明的情况下运行代码?另一方面 - 您可以使用不需要这些权限的已弃用 startLeScan (API 18)。但是,在我看来,使用 API 18 方法在服务中搜索和读取所需的特性更加复杂。


我在 BluetoothLeScanner 中使用 startScan 函数。我有目的地使用未弃用的方法。事实上,我正在检查使用大于 21 的 API 的设备,以专门使用所提供的新方法。我试过没有这个位置,它只是默默地失败了。扫描运行但没有返回任何内容(使用 post-API 21 方法)
L
Lee Boon Kong

从我最近在 android 8.0 上注意到的情况来看,不需要打开你的 GPS 来进行 BLE 扫描,但你必须在清单中声明它,但用户必须允许权限。

当您尝试使用 startScan() 方法进行扫描时,Android 将提示用户允许位置权限。如果不允许该权限,您的扫描将失败。