uniapp如何获取蓝牙广播包数据?

通过uni.onBluetoothDeviceFound可以获取到advertisData值,uni api中advertisData值为广播数据段中的 ManufacturerData,结合蓝牙工具查看,advertisData值仅是广播数据中type为0xFF对应的值,如图中的type为0x01和0x0A的数据应该是否能通过uni获取https://ask.dcloud.net.cn/question/184235

阅读 479
1 个回答

一、Android 原生插件代码

  1. BleScanModule.java
package com.example.ble;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.*;
import android.os.Build;

import org.json.JSONObject;

import io.dcloud.feature.uniapp.common.UniModule;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;

public class BleScanModule extends UniModule {

    private BluetoothLeScanner scanner;
    private ScanCallback scanCallback;

    @UniJSMethod(uiThread = true)
    public void startScan(UniJSCallback callback) {

        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null || !adapter.isEnabled()) {
            return;
        }

        scanner = adapter.getBluetoothLeScanner();

        scanCallback = new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {

                try {
                    byte[] raw = result.getScanRecord().getBytes();
                    String hex = bytesToHex(raw);

                    JSONObject obj = new JSONObject();
                    obj.put("deviceId", result.getDevice().getAddress());
                    obj.put("name", result.getDevice().getName());
                    obj.put("rssi", result.getRssi());
                    obj.put("rawData", hex);

                    callback.invokeAndKeepAlive(obj);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        scanner.startScan(scanCallback);
    }

    @UniJSMethod(uiThread = true)
    public void stopScan() {
        if (scanner != null && scanCallback != null) {
            scanner.stopScan(scanCallback);
        }
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }
}

二、插件注册

  1. dcloud_uniplugins.json
{
  "plugins": [
    {
      "name": "BleScanModule",
      "class": "com.example.ble.BleScanModule"
    }
  ]
}
  1. AndroidManifest.xml 权限
<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"/>

三、uni-app 前端调用

  1. 调用代码
const ble = uni.requireNativePlugin("BleScanModule")

// 开始扫描
function startScan() {
  ble.startScan((res) => {
    console.log("发现设备:", res)

    const raw = res.rawData

    // 解析广播
    const parsed = parseAdData(raw)
    console.log("解析结果:", parsed)
  })
}

// 停止扫描
function stopScan() {
  ble.stopScan()
}

四、广播数据解析

  1. 通用解析函数
function parseAdData(hex) {
  let i = 0
  const result = []

  while (i < hex.length) {
    const len = parseInt(hex.substr(i, 2), 16)
    if (!len) break

    const type = hex.substr(i + 2, 2)
    const value = hex.substr(i + 4, (len - 1) * 2)

    result.push({
      type,
      value
    })

    i += (len + 1) * 2
  }

  return result
}