简体   繁体   English

Android BLE,扫描开始,找到设备但未连接过滤器(ESP32 和三星)

[英]Android BLE, scan started, finds devices but does not connect with filter (ESP32 & Samsung)

I have been working through several BLE tutorials to develop an app to connect to an ESP32, but I cannot get the code to connect to the ESP32.我一直在研究几个 BLE 教程来开发一个连接到 ESP32 的应用程序,但我无法获得连接到 ESP32 的代码。 I am using a Samsung phone which requires a time delay, but I have tried other phones and still cannot connect the ESP32 to the mobile app.我使用的是需要延时的三星手机,但我尝试了其他手机,但仍然无法将 ESP32 连接到移动应用程序。

If I run a BLE scanner app I can connect to the ESP32, so I believe the ESP32 side is okay.如果我运行 BLE 扫描仪应用程序,我可以连接到 ESP32,所以我相信 ESP32 端没问题。 If we scan for devices we can see it in the bluetooth device list.如果我们扫描设备,我们可以在蓝牙设备列表中看到它。

The code is setup to detect and connect, I have tried a UUID and device name filer, but it will not connect.代码设置为检测和连接,我尝试了 UUID 和设备名称文件管理器,但无法连接。 The ScanCallback is been triggered and we get the function onBatchScanResults been called, so we can see a list of devices but it will not connect to the ESP32. ScanCallback 被触发,我们调用了 onBatchScanResults 函数,所以我们可以看到一个设备列表,但它不会连接到 ESP32。 I think it should connect automatically with the gatt functions.我认为它应该自动与 gatt 函数连接。

I cannot workout why it will not auto connect to the ESP32, as it's seen the devices and the scan connect is been trigged.我无法弄清楚为什么它不会自动连接到 ESP32,因为它已经看到设备并且扫描连接已被触发。 Any help would be highly appreciated to fix this issue, as I have ran out of idea to fix it.任何解决此问题的帮助将不胜感激,因为我已经没有办法解决它了。

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

Manifest file清单文件

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

Log file日志文件

 2020-10-28 20:02:58.856 3867-4291/? I/SurfaceFlinger: createSurf start. lock debugging [Surface(name=AppWindowToken{5872671 token=Token{bc8c18 ActivityRecord{8ccf3fb 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=AppWindowToken{49e6a47 token=Token{9d5c186 ActivityRecord{4490261 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=AppWindowToken{49e6a47 token=Token{9d5c186 ActivityRecord{4490261 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

From the logs I see "found something 2" is logged in onBatchScanResults() method of ScanCallback.从日志中,我看到“找到了 2”记录在 ScanCallback 的 onBatchScanResults() 方法中。 You should handle this event.你应该处理这个事件。 Call the same connectGatt which is used in onScanResult() method.调用在 onScanResult() 方法中使用的相同 connectGatt。

When device connection successful in order to read messages from device you should subscribe to services and setCharacteristicNotification for PROPERTY_NOTIFY type characteristics.当设备连接成功以便从设备读取消息时,您应该订阅服务并为 PROPERTY_NOTIFY 类型特征设置特征通知。

For example you can do something like this in your onBatchScanResults()例如,您可以在onBatchScanResults()执行类似的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);
                }
            }
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM