如何通过 android 应用程序获取 BLE 设备的名称列表?

How to get BLE devices' names list by android app?

您好,我正在制作蓝牙连接 android 应用程序。 我遵循了 developer.android.com 的指示 当我正在测试我的应用程序时,我期待它能正常工作,但它没有。 我试图获取检测到的 BLE 设备名称,但不知道它不显示设备名称的原因...

Arduino nano 33 IOT 在我的 android phone 旁边宣传蓝牙,我正在尝试检测它并获取 Adrduino 的 BLE 设备名称和地址。

这是我的 MainActivity.java

public class MainActivity extends AppCompatActivity {

    //View Contents Elements
    public Button btnActivateBluetooth;
    public Button btnSearchBluetooth;
    public Button btnSendData;
    public ListView lvSearchedDevice;
    public ListView lvLog;
    public TextView tvStatus;
    public EditText etData;

    //etc values
    public ArrayAdapter<String> logAdapter;
    private final int REQUEST_ENABLE_BT = 1;
    private boolean mScanning = true;

    //bluetooth values
    public BluetoothAdapter btAdapter;
    public BluetoothManager btManager;
    private Handler handler;


    @SuppressLint("MissingPermission")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //View Elements
        btnSearchBluetooth = (Button) findViewById(R.id.btnSearchBluetooth);
        btnSendData = (Button) findViewById(R.id.btnSendData);
        lvSearchedDevice = (ListView) findViewById(R.id.lvSearchedDevice);
        lvLog = (ListView) findViewById(R.id.log);
        tvStatus = (TextView) findViewById(R.id.tvStatus);
        etData = (EditText) findViewById(R.id.etData);

        //etc
        logAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
        lvLog.setAdapter(logAdapter);
        handler = new Handler();

        // Initializes Bluetooth adapter.
        btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        btAdapter = btManager.getAdapter();

        // displays a dialog requesting user permission to enable Bluetooth.
        if (btAdapter == null || !btAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

        btnSearchBluetooth.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                scanLeDevice(true);
            }
        });
    }

    //Scan devices
    @SuppressLint("MissingPermission")
    private void scanLeDevice(final boolean enable){
        if(enable){
            handler.postDelayed(new Runnable() {
                @SuppressLint("MissingPermission")
                @Override
                public void run() {
                    btAdapter.stopLeScan(leScanCallback);
                }
            },5000);
            btAdapter.startLeScan(leScanCallback);
        }
        else
        {
            btAdapter.stopLeScan(leScanCallback);
        }
    }

    //Callback method
    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            runOnUiThread(new Runnable() {
                @SuppressLint("MissingPermission")
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, device.getName(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    };
}

这是我的 Arduino nano 33 IOT 的代码。

#include <ArduinoBLE.h>
BLEService Toothbrush("00001101-0000-1000-8000-00805F9B34FB");
BLEStringCharacteristic ToothbrushChar("00001101-0000-1000-8000-00805F9B34FB",BLEWrite|BLERead | BLENotify, 10);

void setup() {
  Serial.begin(9600);
  if(!BLE.begin()){
    Serial.println("Starting BLE failed.");
    while(1);
  }
  BLE.setLocalName("HayanToothbrush");
  BLE.setAdvertisedService(Toothbrush);
  Toothbrush.addCharacteristic(ToothbrushChar);
  BLE.addService(Toothbrush);
  BLE.advertise();

  Serial.println("Bluetooth device active, wating for connections...");
}

void loop() {
  BLEDevice central = BLE.central();
  
  if(central) {
    Serial.print("Connected to central : ");
    Serial.println(central.address());

    while(central.connected()){
      
    }
    Serial.print("Disconnected from central:");
    Serial.println(central.address());
  }
}

我在 Mainfest 中添加权限如下。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.bluetooth0523">

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Bluetooth0523"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

但它仍然没有找到我扫描的设备名称。 我认为这是关于 LeScanCallBack 的问题。 运行启动LeScan时,好像没有运行回调方法。 另外,我在 SDK_VERSION_30 上 运行 这个应用程序 并且 Arduino nano IOT 33 是​​可发现的 如果我使用我的 phone 具有的蓝牙功能,而不是我的应用程序,它将显示在扫描结果列表中。 我想在我自己的应用程序上获得扫描结果。 但不知道问题出在哪里。

必须根据 Android 版本声明和请求权限。主要区别是:

目标 Android 12 或更高

BLUETOOTH_SCAN

目标 Android 11 或更低

ACCESS_FINE_LOCATION

详情见Bluetooth permissions