Android系统蓝牙的使用

概述

本文基于 gitee 项目 administer/AndroidBluetooth。 实现了经典蓝牙的查找、配对、连接,低功耗蓝牙的查找、连接、通信。

1.Android系统蓝牙

1.1 Android系统支持经典蓝牙和低功耗蓝牙:

  • Classic Bluetooth(经典蓝牙)。 用于大量的通信时,例如:音频、短信和电话。
  • Bluetooth Low Energy(低功耗蓝牙)。 用于低频的通信时,例如:心率监测器、无线键盘,要求Android4.3及更高版本。

1.2 蓝牙堆栈的常规结构

蓝牙应用通过 Binder 与蓝牙进程进行通信。蓝牙进程使用 JNI 与蓝牙堆栈通信,并向开发者提供对各种蓝牙配置文件的访问权限。如下图:

2.经典蓝牙

2.1 申请蓝牙权限

java 复制代码
    <!--蓝牙 API30及以下需要申请4个权限,API31及以上时权限列表将不会列出这些权限-->
    <!--蓝牙 连接、通信-->
    <uses-permission
        android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" />
    <!--蓝牙 扫描、设置-->
    <uses-permission
        android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" />
    <!--蓝牙 API30及以下需要定位权限 -->
    <uses-permission
        android:name="android.permission.ACCESS_COARSE_LOCATION"
        android:maxSdkVersion="30" />
    <uses-permission
        android:name="android.permission.ACCESS_FINE_LOCATION"
        android:maxSdkVersion="30" />

    <!--蓝牙 API31及以上需要申请3个权限-->
    <!--蓝牙 扫描,可不申请定位权限-->
    <uses-permission
        android:name="android.permission.BLUETOOTH_SCAN"
        android:usesPermissionFlags="neverForLocation"
        tools:targetApi="s" />
    <!--蓝牙 广播,被发现-->
    <!--<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />-->
    <!--蓝牙 连接、通信-->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

2.2 设置蓝牙

java 复制代码
//蓝牙适配器
BluetoothManager bluetoothManager = context.getSystemService(BluetoothManager.class);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
//注册广播接收者
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
mContext.registerReceiver(receiver, intentFilter);
//广播接收者
private final BroadcastReceiver receiver = new BroadcastReceiver() {
   public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (BluetoothDevice.ACTION_FOUND.equals(action)) {//扫描-发现设备
         BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
      } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {//扫描结束
      } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {//配对状态变化
         BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
         int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
      } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {//连接状态变化
         BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
         int connectState = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.ERROR);
      }
   }
};

2.3 查找蓝牙设备

java 复制代码
//查询已配对设备
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
//扫描 大概12s,扫描中不能立即重新扫描
if (!bluetoothAdapter.isDiscovering()) {
   bluetoothAdapter.startDiscovery();
}

2.3 连接蓝牙设备

java 复制代码
public void connectDevice(BluetoothDevice device) {
   if (bluetoothAdapter != null) {//取消扫描
      bluetoothAdapter.cancelDiscovery();
    }
   //已配对的取消配对,配对后自动连接。
   if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
      removeBondDevice(device);//取消配对
      AppExecutors.getInstance().scheduledWork().schedule(() -> {
         device.createBond();//延时配对
      }, 1, TimeUnit.SECONDS);
   } else if (device.getBondState() == BluetoothDevice.BOND_NONE) {
            device.createBond();//配对
   }
}

//判断设备是否连接
public static boolean isDeviceConnected(BluetoothDevice device) {
   boolean isConnected = false;
   try {
      isConnected = (boolean) device.getClass().getMethod("isConnected").invoke(device);
   } catch (Exception e) {
      e.printStackTrace();
   }
   return isConnected;
}

//解绑设备
public static boolean removeBondDevice(BluetoothDevice device) {
   boolean state = false;
   try {
      state = (boolean) device.getClass().getMethod("removeBond").invoke(device);
   } catch (Exception e) {
      e.printStackTrace();
   }
   return state;
}

3.低功耗蓝牙

3.1 查找蓝牙设备

java 复制代码
//扫描一段时间后结束
AppExecutors.getInstance().scheduledWork().schedule(() -> {
   bluetoothAdapter.getBluetoothLeScanner().stopScan(scanCallback);
}, 10, TimeUnit.SECONDS);
bluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback);

3.2 连接蓝牙设备

java 复制代码
//连接
bluetoothGatt = device.connectGatt(mContext, false, gattCallback, BluetoothDevice.TRANSPORT_LE)
//断开连接
bluetoothGatt.disconnect();

3.3 写入数据

java 复制代码
byte[] data;
writeCharacteristic.setValue(data);
bluetoothGatt.writeCharacteristic(writeCharacteristic);

4.官方文档

通信技术-蓝牙概览

通信技术-蓝牙开发

相关推荐
00后程序员张10 小时前
python 抓包在实际项目中的合理位置,结合代理抓包、设备侧抓包与数据流分析
android·ios·小程序·https·uni-app·iphone·webview
灵感菇_11 小时前
Android Service全面解析
android·service·四大组件
alexhilton11 小时前
Jetpack ViewModel内幕:内部机制与跨平台设计
android·kotlin·android jetpack
_李小白14 小时前
【Android FrameWork】延伸阅读: Android应用安装过程
android
光头闪亮亮14 小时前
Android手持机扫码出入库的开发详解-6.APP下载更新
android
光头闪亮亮14 小时前
Android手持机扫码出入库的开发详解-7.SQLite CRUD操作
android
键来大师14 小时前
Android16 设置壁纸出现APK重启问题和悬浮控件等图标变成黑色图框
android·framework·rk3576
_李小白15 小时前
【Android FrameWork】第四十二天:PMS main函数
android
BoomHe15 小时前
Android LMK(Low Memory Killer)机制
android
时光呀时光慢慢走16 小时前
MAUI 开发安卓 MQTT 客户端:实现远程控制 (完整源码 + 避坑指南)
android·物联网·mqtt·c#