蓝牙低功耗在Android 6.0上的startScan无法找到设备。

48

我正在使用Nexus 5开发一个基于蓝牙低功耗的应用程序。在Lollipop版本上可以运行,但现在在Marshmallow版本上无法工作。 我在清单文件中设置了ACCESS_COARSE_LOCATION和ACCESS_FINE_LOCATION权限,并在Activity运行时设置了这些权限。

这是ScanFilters的列表:

mScanFilterTest = new ScanFilter.Builder().build();
mScanFilter = new ArrayList<ScanFilter>();
mScanFilter.add(mScanFilterTest);

以下是设置:

mScanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER).setReportDelay(0)
                .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();

这些是我的回调函数:

 mBLEScan = new ScanCallback() {
     @Override
     public void onScanResult(int callbackType, ScanResult result) {
         super.onScanResult(callbackType, result);
         Log.i(TAG, "******************************************");
         Log.i(TAG, "The scan result " + result);
         Log.i(TAG, "------------------------------------------");
         }
     };
这是我的呼叫:
mBluetoothLeScanner.startScan(mScanFilter, mScanSettings, mBLEScan);

扫描已开始,但未发现任何设备。请帮忙!!!

3个回答

72

我曾经也遇到过同样的问题。为了解决它,你需要在手机设置中启用“位置”(GPS),并且在应用程序运行时请求位置权限。这两者都需要完成,才能使扫描正常工作。

要请求位置权限,请将以下内容放入对话框或类似环境中:

yourActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, yourPermissionRequestCode);

并实现:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){
    if(requestCode == yourPermissionRequestCode)
    {
        ... //Do something based on grantResults
    }
}

yourActivity中处理用户选择,您还需要执行以下操作才能开启设备的位置服务:

Intent enableLocationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
yourActivity.startActivityForResult(enableLocationIntent, yourServiceRequestCode);

您可以通过实现以下代码来检查用户是否已经打开了位置服务:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if(requestCode == yourServiceRequestCode)
    {
        ...//Do whatever you need to
    }
}

yourActivity 中。您还可以通过以下方式手动打开位置(GPS)服务:

进入手机设置 -> 选择“位置” -> 然后打开它

在手机设置中,应该看起来像这样:

Location (GPS) services enabled in Phone Settings

或者在快速设置下拉菜单中,看起来像这样:

Location (GPS) services enabled in drop down settings

一旦用户已启用权限并启动了位置服务,那么您应该开始扫描。 我注意到,如果您在启用权限/打开位置服务时已经在扫描,则仍然不会将任何内容放入您的 onScanResults 中。

我不确定这是iBeacons/蓝牙广告的一个错误还是“功能”,以便公司可以查看您的位置并将您引导到他们想要的地方。(注意:广告指销售产品而非技术性蓝牙广告)

希望这可以解决您的问题!

编辑 我想要添加的是:您只需要在扫描时使用此功能。一旦您连接到BLE设备,您可以关闭手机上的位置服务,您仍将连接到您的设备。但是,您将无法发现或连接到任何新设备,所有广告设备都将从 onScanResults 中删除。


4
这个功能能够使用,但似乎是安卓系统的一个严重缺陷。为什么扫描需要开启 GPS?我的应用程序只为想要使用该功能的客户使用 GPS,因此对于在我们的应用程序中禁用了 GPS 的客户来说,被提示打开 GPS 以便扫描蓝牙设备是很困扰的。请问是否有其它解决方案? - Matt Wolfe
6
@Matt Wolfe 是的,我同意,这似乎是一个巨大的漏洞。事实上,已经发布了一个错误报告此处,询问发生了什么。我对为什么会出现这种情况的假设是它允许广告公司使用BLE GAP-only广告设备(iBeacon设备等)在零售店中找到客户的物理位置(使用三角定位),并能够将他们引导到商店其他地方的产品。但我可能完全错了。 - V-PTR
4
我只是打开了GPS,一切都没有使用requestPermissions()就可以运行。我以为添加requestPermissions()后,即使没有打开GPS,扫描也能正常工作,但我错了。谷歌到底怎么回事? - Lo-Tan
4
@V-PTR 似乎是一个严重的漏洞 -- 我读了问题跟踪器,但我得出结论它不是一个漏洞。这是Google旨在保护用户的功能。现在,由于物联网,蓝牙设备的MAC地址可以用于位置识别。我想Google的设计师认为当用户可能处于隐私风险时应该始终给予通知。我认为,相反,Marshmallow之前的设备在处理蓝牙设备信息方面存在隐私保护问题。 - hata
2
@MrColes 我认为它不一定非得是GPS。只要开启了位置服务,任何服务都可以使用。我之所以提到GPS,只是因为我个人将位置服务与GPS联系在一起。我没有明确尝试过不同的位置模式,但我认为这应该没有影响。 - V-PTR
显示剩余11条评论

2

就像@Jacopo Tosi所说,您必须请求位置权限。 您可以在这里了解如何操作。 同时,您还必须打开位置信息。我不知道为什么要这样做,但这是我成功让它工作的唯一方法。


我打开了位置,它开始扫描,但在回调中没有任何响应。 - Jacopo Tosi
1
这并不能真正改善情况,但其背后的原因是BLE信标通常被用作一种室内GPS来跟踪用户位置。因此,你必须与用户进行尴尬的对话,请求权限并承诺不会尝试跟踪他们,尽管他们刚刚授予心率监测器该权限。 - caller9

0
在我的情况下(HTC M9),我还必须进入 Android 设置菜单下的蓝牙,并手动扫描 BT 设备。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接