蓝牙LE扫描有时不会查找设备

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

我遇到的问题是,有时(随机看起来,但经常),它不会find我的任何其他外围设备,其他时间工作正常。

我有一个运行相似代码的伴侣iOS设备(既可以扫描外围设备,也可以作为外设),当Android扫描找不到iOS设备时,我的iOS会发现Android设备充当外设。 所以似乎只是在事物的扫描方面存在问题。

这不仅仅是找不到我的伴侣iOS设备,而是没有find任何蓝牙设备。 当它工作,它发现我的伴侣iOS设备以及一堆其他设备。

我曾尝试过,没有ScanFilters,并得到同样的问题。 我正在build立一个最低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); } } } } } 

Solutions Collecting From Web of "蓝牙LE扫描有时不会查找设备"

我面临同样的问题。 这是因为Google政策已经更改为棉花糖API 23及更高版本,要使用BLE用户需要打开GPS 。 对于Google文档,请选中“ Permission @ Runtime”链接。 要解决这个问题,您必须在手机的设置中启用“位置”,并在运行系统中的应用程序请求位置权限 。 两者都需要完成扫描才能正常工作。

要请求位置权限,请在对话框中input以下内容:

 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 } } 

myActivity处理任何用户select。 您还需要执行以下操作来打开设备的位置服务:

 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设备,您可以closures手机上的位置服务,并且仍然保持与外围设备的连接。 但是,一旦连接到固件(外设),您将无法连接到任何新的外围设备,直到断开与配对设备的连接,而其他所有扫描设备(移动设备)都无法在其扫描列表中看到外围设备名称(用户在外围设备已连接到任何其他移动设备时,由于外设一次只能连接到一个设备,因此请在外围设备附近search)。 对于BLE基本示例,您可以查看这个Truiton Ble教程 。 这段代码将解决我认为的问题。 快乐编码:)

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

你需要两个方法一个旧的API和一个最新的API。

至于SDK 23及更高版本,您必须请求运行时权限。 请求位置权限。

这可能只是简单的情况下,Android手机有一个蹩脚的蓝牙芯片。 你看过hci日志吗? 或者logcat?

蓝牙4.0芯片(这是你的机器人)有严格的限制,你不能成为一个中央和外设在同一时间,即使应该允许扫描所有的时间。 因此,在BT 4.0被淘汰之前,我不会生产依赖于Android外设function的产品。

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

如果您将应用程序用于非商业用途(意思是预计用户less于5K),则可以使用P2Pkit 。

除了BLE和非BLE蓝牙之外,它还在老版本的android上使用P2P wifi连接,实际上在发现附近的手机时获得了很好的效果。

它们也可以在IOS上运行,它有一个相当简单的界面。

下降超过5K用户你必须支付..