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.官方文档

通信技术-蓝牙概览

通信技术-蓝牙开发

相关推荐
CYRUS_STUDIO1 天前
用 Frida 控制 Android 线程:kill 命令、挂起与恢复全解析
android·linux·逆向
CYRUS_STUDIO1 天前
Frida 实战:Android JNI 数组 (jobjectArray) 操作全流程解析
android·逆向
用户091 天前
Gradle Cache Entries 深度探索
android·java·kotlin
循环不息优化不止1 天前
安卓 View 绘制机制深度解析
android
叽哥1 天前
Kotlin学习第 9 课:Kotlin 实战应用:从案例到项目
android·java·kotlin
雨白2 天前
Java 线程通信基础:interrupt、wait 和 notifyAll 详解
android·java
诺诺Okami2 天前
Android Framework-Launcher-UI和组件
android
潘潘潘2 天前
Android线程间通信机制Handler介绍
android
潘潘潘2 天前
Android动态链接库So的加载
android
潘潘潘2 天前
Android多线程机制简介
android