蓝牙LE扫描有时无法查找设备

时间:2017-10-31 18:00:05

标签: android bluetooth bluetooth-lowenergy android-bluetooth

我正在扫描蓝牙LE设备并作为外围设备运行(在Moto G第二代上运行Android 6.0)

我遇到的问题是,有时(似乎经常随机)它找不到我的任何其他外围设备,其他时候它工作正常。

我有一个配套的iOS设备运行类似的代码(扫描外围设备和充当外围设备),当Android扫描无法找到iOS设备时,我的iOS发现Android设备充当外围设备就好了。因此,似乎只是扫描方面的问题。

这不仅仅是找不到我的配套iOS设备,而且找不到任何蓝牙设备。当它工作时,它会找到我的配套iOS设备以及许多其他设备。

我在使用和不使用ScanFilters的情况下尝试过它,并得到同样的问题。 我正在使用最低SDK为23的SDK 26构建。

我正在设置所需的权限,因为它有时会起作用。

以下相关代码:

private void startScanning() {
    mHandler = new Handler(mContext.getMainLooper());

    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            ScanSettings settings = new ScanSettings.Builder()
                                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                                        .setReportDelay(0)
                                        .build();

            mBluetoothLeScanner.startScan(null, settings, mScanCallback);
        }
    }, 1000);
}

private ScanCallback mScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);

        if( result == null || result.getDevice() == null )
            return;

        Log.e("myTest", "Found Device");

        BluetoothDevice device = result.getDevice();
        final String deviceAddress = device.getAddress();

        List<ParcelUuid> parcel = result.getScanRecord().getServiceUuids();

        if (parcel != null) {
            String parcelUUID = parcel.toString().substring(1,37);

            if (parcelUUID.equalsIgnoreCase(mContext.getString(R.string.service_uuid))) {
                final BluetoothDevice bleDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(deviceAddress);

                if (!seenPeripherals.contains(deviceAddress)) {
                    stopScanning();

                    mHandler = new Handler(mContext.getMainLooper());

                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Log.e("AppToApp", "Trying to connect to device " + deviceAddress);

                            mGatt = bleDevice.connectGatt(mContext, false, mGattCallback);
                        }
                    }, 1000);
                }
            }
        }   
    }
}

3 个答案:

答案 0 :(得分:2)

我面临同样的问题。这是因为针对 Marshmallow API 23 及更高版本的Google政策已更改,要使用BLE用户需要转为 ON GPS 。对于Google文档,请查看此Permission @ Runtime链接。要解决此问题,您必须在手机设置中启用“位置”,并在运行时中的应用中请求位置权限。两者都需要完成扫描才能正常工作。

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

myActivity.requestPermissions(new String[]{Manifest.permission.ACCESS_COURSE_LOCATION}, yourPermissionRequestCode);

并实施:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] Results){
    if(requestCode == yourPermissionRequestCode)
    {
        ... //Do something based on Results
    }
}
<{1>}在myActivity处理用户选择的任何内容。您还需要执行以下操作才能打开设备的位置服务:

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

您可以通过实施以下方式检查用户是否开启了位置服务:

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

。您还可以通过执行以下操作手动启用位置服务:

Enter phone settings -> Select "Apps" -> Select your app -> Select the "Permissions" option -> Switch the "Location" permission on.

一旦用户启用了权限并启动了位置服务,您就可以开始扫描外围设备了。 我注意到,如果您在启用时正在扫描允许/启用位置服务,它仍然不会在onScanResults

中放置任何内容

这使公司可以查看您的位置并将您引导到他们想要的位置。

在扫描设备时,一旦连接到BLE设备,您可以关闭手机上的位置服务,您仍然可以保持与外围设备的连接。但是,一旦连接到固件(外围设备),则在断开与配对设备的连接之前无法连接到任何新外围设备,并且所有其他扫描设备(移动设备)无法在扫描列表中看到外围设备名称(当用户当外围设备已经连接到任何其他移动设备时,通过外围设备搜索附近,因为外围设备一次只能连接到1个设备。 对于BLE基本样本,您可以查看Truiton Ble tutorial。这个片段将解决我认为的问题。快乐的编码:)

答案 1 :(得分:0)

这个问题与我之前发布的内容有关。请查看此链接https://stackoverflow.com/a/39084810/3997720和此https://stackoverflow.com/a/39597845/3997720

你需要两个方法,一个用于旧api,一个用于最新api。

对于SDK 23及更高版本,您必须请求运行时权限。要求获得位置许可。

答案 2 :(得分:0)

可能只是Android手机有一个糟糕的蓝牙芯片。你看过hci日志了吗?还是logcat?

蓝牙4.0芯片(在你的机芯中)有严格的限制,你不能同时成为中央和外围设备,即使应该一直允许扫描。因此,在BT 4.0逐步淘汰之前,我不会制作依赖于Android外围功能的产品。

您应该使用至少具有蓝牙4.1芯片的新手机进行测试。