升级到 Android 6.0 版后,蓝牙低功耗 (BLE) 扫描仅在设备上启用了定位服务的情况下才能工作。请参阅此处以供参考:Bluetooth Low Energy startScan on Android 6.0 does not find devices
基本上,您需要为应用程序和手机启用权限。这是一个错误吗?是否可以在没有实际启用定位服务的情况下进行扫描?我不想为我的所有应用程序提供位置。
编辑我没有提到我正在使用 API 21 中提供的 BluetoothLeScanner
中的 startScan()
方法。我可以接受此方法所需的清单中的课程和精细位置权限。我只是不希望我的应用程序的用户必须在他们的设备(GPS 等)上启用位置服务才能使用我的应用程序。
以前,startScan()
方法将在手机上禁用位置服务的情况下运行并返回结果。然而,在 Marshmallow 上,当手机上未启用定位服务并且课程/精细定位权限仍在清单中时,相同的应用程序将“扫描”但静默失败并且不返回任何结果。
不,这不是错误。
此 issue 已提交给 Google,他们回复说这是预期的行为,他们不会修复它。他们将开发人员引导至 this site,其中指出硬件标识符访问现在需要位置许可。现在,开发人员有责任让他们的用户了解需求。
然而,在这个问题中,它没有解决为什么需要定位服务(GPS 等),而且他们似乎不会重新讨论这个问题来解释这一点,因为它已被标记为预期行为。
回答问题的第二部分:是的,可以在不启用定位服务的情况下进行扫描。您可以使用 BluetoothAdapter.getDefaultAdapter().startDiscovery()
进行蓝牙经典扫描,这将在位置服务关闭的情况下工作。这将发现所有蓝牙设备、BLE 和其他设备。但是,如果 BLE 设备被视为 startScan()
的结果,它们将没有扫描记录。
我通过在 Gradle 文件中将 targetSdkVersion
设置为 22 解决了这个问题。您必须在清单中声明 ACCESS_COARSE_LOCATION
,但即使用户从应用设置中拒绝此权限,BLE 扫描也将起作用。
这只是避免请求位置许可的一种技巧。最好针对最新的 android 版本。
编辑
此解决方案不应再使用,因为 Google Play 将要求新应用程序至少面向 Android 8.0(API 级别 26)。应用程序应请求位置许可以进行 BLE 扫描。
ACCESS_COARSE_LOCATION
我发现在 Android 6 之后你必须授予 ACCESS_COARSE_LOCATION 权限。但在某些设备上,您的手机定位服务 (GPS) 也需要打开,以便您可以发现外围设备。我发现使用带有 Android 7.0 的 Nexus 5x。
我也在清单上试过这个,但没有请求许可,不知道为什么。您的应用程序是否在启动时提示位置权限?如果不是,我们需要request for permission on runtime。
您还可以检查它以测试您的应用程序是否正常工作:
打开设置 > 应用程序 > YourApplication > 权限并启用位置,然后尝试扫描结果。
仅当您在清单上提供了 ACCESS_COARSE_LOCATION 时,才会在此处列出位置。
您可以使用 BluetoothAdapter.startDiscovery()
。
它将扫描蓝牙智能设备和经典蓝牙设备,但不需要启用位置服务。
(在 Android 6 上您仍需要 ACCESS_COARSE_LOCATION
权限。)
您可以在找到的设备上调用 BluetoothDevice.getType
来过滤蓝牙智能/低功耗设备。
将 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();
}
}
为我工作!
您可以使用 CompanionDeviceManager (API26) 扫描没有位置访问权限的 BLE 设备。 https://developer.android.com/reference/android/companion/CompanionDeviceManager。
好吧,我查看了用 Eclipse 编写的代码,并在那里使用了 startScan (API 21) 函数,而没有在清单文件中声明位置内容。我仍然得到正确的回调。您是否尝试过在没有位置声明的情况下运行代码?另一方面 - 您可以使用不需要这些权限的已弃用 startLeScan (API 18)。但是,在我看来,使用 API 18 方法在服务中搜索和读取所需的特性更加复杂。
BluetoothLeScanner
中使用 startScan
函数。我有目的地使用未弃用的方法。事实上,我正在检查使用大于 21 的 API 的设备,以专门使用所提供的新方法。我试过没有这个位置,它只是默默地失败了。扫描运行但没有返回任何内容(使用 post-API 21 方法)
从我最近在 android 8.0 上注意到的情况来看,不需要打开你的 GPS 来进行 BLE 扫描,但你必须在清单中声明它,但用户必须允许权限。
当您尝试使用 startScan()
方法进行扫描时,Android 将提示用户允许位置权限。如果不允许该权限,您的扫描将失败。
不定期副业成功案例分享