Android BLE,扫描开始,找到设备但未连接过滤器(ESP32 和三星)
Posted
技术标签:
【中文标题】Android BLE,扫描开始,找到设备但未连接过滤器(ESP32 和三星)【英文标题】:Android BLE, scan started, finds devices but does not connect with filter (ESP32 & Samsung) 【发布时间】:2021-02-11 06:03:58 【问题描述】:我一直在学习几个 BLE 教程来开发一个连接到 ESP32 的应用程序,但我无法获得连接到 ESP32 的代码。我使用的是三星手机,需要延时,但我尝试过其他手机,仍然无法将 ESP32 连接到移动应用程序。
如果我运行 BLE 扫描仪应用程序,我可以连接到 ESP32,所以我相信 ESP32 端没问题。如果我们扫描设备,我们可以在蓝牙设备列表中看到它。
代码设置为检测和连接,我尝试了 UUID 和设备名称文件管理器,但无法连接。 ScanCallback 被触发,我们调用了 onBatchScanResults 函数,因此我们可以看到设备列表,但它不会连接到 ESP32。我认为它应该与 gatt 函数自动连接。
我无法确定为什么它不会自动连接到 ESP32,因为它已经看到了设备并且触发了扫描连接。非常感谢任何帮助来解决这个问题,因为我已经没有办法解决它了。
package com.example.sandpit_ble002;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
// Based on the following resource
// https://medium.com/@martijn.van.welie/making-android-ble-work-part-1-a736dcd53b02
// https://developer.android.com/guide/topics/connectivity/bluetooth-le#java
public class MainActivity extends AppCompatActivity
UUID BLP_SERVICE_UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
private static final int REQUEST_ENABLE_BT = 1;
private static final int ACCESS_COARSE_LOCATION_REQUEST = 2;
private boolean mScanning;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState)
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
CheckPermissions();
hasPermissions();
if (!bluetoothAdapter.isEnabled())
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
ScanSettings scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
.setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
.setReportDelay(10)
.build();
/*
UUID[] serviceUUIDs = new UUID[]BLP_SERVICE_UUID;
List<ScanFilter> filters = null;
Log.d("Debug", "debug 005");
if(serviceUUIDs != null)
Log.d("Debug", "debug 004");
filters = new ArrayList<>();
for (UUID serviceUUID : serviceUUIDs)
ScanFilter filter = new ScanFilter.Builder()
.setServiceUuid(new ParcelUuid(serviceUUID))
.build();
filters.add(filter);
*/
String[] names = new String[]"ESP32 UART Test";
List<ScanFilter> filters = null;
if(names != null)
filters = new ArrayList<>();
for (String name : names)
ScanFilter filter = new ScanFilter.Builder()
.setDeviceName(name)
.build();
filters.add(filter);
if (scanner != null)
scanner.startScan(filters, scanSettings, scanCallback);
Log.d("Debug", "scan started");
else
Log.e("Debug", "could not get scanner object");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
private boolean hasPermissions()
Log.i("Debug", "Debug 020");
if (getApplicationContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
Log.i("Debug", "Debug 021");
requestPermissions(new String[] Manifest.permission.ACCESS_COARSE_LOCATION , ACCESS_COARSE_LOCATION_REQUEST);
return false;
return false;
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState)
if (newState == BluetoothProfile.STATE_CONNECTED)
Log.i("Debug", "Debug 014");
gatt.discoverServices();
else
Log.i("Debug", "Debug 015");
gatt.close();
private final ScanCallback scanCallback = new ScanCallback()
@Override
public void onScanResult(int callbackType, ScanResult result)
BluetoothDevice device = result.getDevice();
Log.i("Debug", "fScanCallback");
// ...do whatever you want with this found device
Log.i("Debug", "found something 1");
BluetoothGatt gatt = device.connectGatt( getApplicationContext(), true, mGattCallback, BluetoothDevice.TRANSPORT_LE);
Log.d("Debug", "Trying to create a new connection.");
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState)
Log.i("Debug", "Debug 017");
if (status == BluetoothGatt.GATT_SUCCESS)
if (newState == BluetoothProfile.STATE_CONNECTED)
// We successfully connected, proceed with service discovery
Log.i("Debug", "Debug 013");
gatt.discoverServices();
else if (newState == BluetoothProfile.STATE_DISCONNECTED)
// We successfully disconnected on our own request
Log.i("Debug", "Debug 012");
gatt.close();
else
// We're CONNECTING or DISCONNECTING, ignore for now
Log.i("Debug", "Debug 011");
else
// An error happened...figure out what happened!
Log.i("Debug", "Debug 010");
gatt.close();
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED)
Log.i("Debug", "Connected to GATT server.");
// Attempts to discover services after successful connection.
else if (newState == BluetoothProfile.STATE_DISCONNECTED)
Log.i("Debug", "Debug 009");
;
@Override
public void onBatchScanResults(List<ScanResult> results)
Log.i("Debug", "found something 2");
@Override
public void onScanFailed(int errorCode)
Log.i("Debug", "found something 3");
;
private boolean CheckPermissions()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
if (getApplicationContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
Log.i("Debug", "Debug 001");
requestPermissions(new String[] Manifest.permission.ACCESS_COARSE_LOCATION , ACCESS_COARSE_LOCATION_REQUEST);
return false;
Log.i("Debug", "Debug 002");
return true;
清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sandpit_ble002">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
日志文件
2020-10-28 20:02:58.856 3867-4291/? I/SurfaceFlinger: createSurf start. lock debugging [Surface(name=AppWindowToken5872671 token=Tokenbc8c18 ActivityRecord8ccf3fb u0 com.sec.android.app.launcher/.activities.LauncherActivity t256)/@0x319a60 - animation-bounds]
2020-10-28 20:02:58.859 3867-4291/? I/SurfaceFlinger: createSurf start. lock debugging [Surface(name=AppWindowToken49e6a47 token=Token9d5c186 ActivityRecord4490261 u0 com.example.sandpit_ble002/.MainActivity t333)/@0x5fb6af6 - animation-leash]
2020-10-28 20:02:58.860 3867-4291/? I/SurfaceFlinger: createSurf start. lock debugging [Surface(name=AppWindowToken49e6a47 token=Token9d5c186 ActivityRecord4490261 u0 com.example.sandpit_ble002/.MainActivity t333)/@0x5fb6af6 - animation-bounds]
2020-10-28 20:02:59.075 10090-10090/com.example.sandpit_ble002 I/Debug: Debug 002
2020-10-28 20:02:59.075 10090-10090/com.example.sandpit_ble002 I/Debug: Debug 020
2020-10-28 20:02:59.085 10090-10090/com.example.sandpit_ble002 D/Debug: scan started
2020-10-28 20:02:59.295 3867-4291/? I/SurfaceFlinger: createSurf start. lock debugging [1aaa92c com.example.sandpit_ble002/com.example.sandpit_ble002.MainActivity]
2020-10-28 20:02:59.322 3867-4291/? I/SurfaceFlinger: createSurf start. lock debugging [com.example.sandpit_ble002/com.example.sandpit_ble002.MainActivity$_10090]
2020-10-28 20:02:59.382 3867-3941/? I/SurfaceFlinger: createSurf start. lock debugging [Surface(name=e0e9827 Splash Screen com.example.sandpit_ble002)/@0x3d1cb48 - animation-leash]
2020-10-28 20:03:04.132 10090-10090/com.example.sandpit_ble002 I/Debug: found something 2
2020-10-28 20:03:09.159 10090-10090/com.example.sandpit_ble002 I/Debug: found something 2
2020-10-28 20:03:14.180 10090-10090/com.example.sandpit_ble002 I/Debug: found something 2
【问题讨论】:
你能粘贴日志吗? 是的,用唯一的TAG名称记录上面的代码日志并过滤它。例如:BleIssue 请将 Log.i("Debug", ...) 和 Log.d("Debug", ..) 更改为 Log.d("BLEISSUE", ..) 并显示给我们 我看到了日志。首先检查 device.type 值。它可以是经典的、ble 或双重的。如果是经典蓝牙设备,则无法通过 LE 传输连接 从日志中我看到“found something 2”已登录 onBatchScanResults() 方法。你应该处理这个事件。调用同一个connectGatt 【参考方案1】:从日志中我看到“找到了一些东西 2”登录了 ScanCallback 的 onBatchScanResults() 方法。 你应该处理这个事件。调用与 onScanResult() 方法相同的 connectGatt。
当设备连接成功以便从设备读取消息时,您应该订阅服务并为 PROPERTY_NOTIFY 类型特征设置CharacteristicNotification。
【讨论】:
这是一个巨大的帮助,非常感谢你,你能帮助解决最后一个问题如何使用从扫描列表中选择一个设备,即 ScanResult scanResult = results.get(0);把它连接到关贸总协定? device.connect 如何以及需要什么,我们如何从列表中获取该连接? BluetoothGatt gatt = device.connectGatt(getApplicationContext(), true, mGattCallback, BluetoothDevice.TRANSPORT_LE); 你应该处理 mGattCallback 事件 onConnectionStateChange -> 如果状态为 STATE_CONNECTED 调用 discoverServices onServicesDiscovered -> 订阅服务 onCharacteristicWrite -> 从队列 onCharacteristicChanged 发送下一个数据 -> 从 ble 设备读取传入数据 接受的答案不是主要问题的答案,而是我们谈话中出现的下一个问题。【参考方案2】:例如,您可以在 onBatchScanResults()
中执行类似的操作
@Override
public void onBatchScanResults(List<ScanResult> results)
for (ScanResult result: results)
BluetoothDevice myDevice = result.getDevice();
Log.i("Debug", "onBatchScanResults: " + myDevice.getName());
if(myDevice.getName().equals("ESP32 UART Test"))
BluetoothGatt bluetoothGatt = myDevice.connectGatt(getApplicationContext(), true, mGattCallback, BluetoothDevice.TRANSPORT_LE);
【讨论】:
非常感谢那是辉煌的,非常解决了头撞到工作的日子以上是关于Android BLE,扫描开始,找到设备但未连接过滤器(ESP32 和三星)的主要内容,如果未能解决你的问题,请参考以下文章
android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser
android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser
Android 4.4:低功耗蓝牙;无需扫描 BLE 设备即可连接