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

通信技术-蓝牙概览

通信技术-蓝牙开发

相关推荐
雨白1 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
漫步企鹅2 小时前
【蓝牙】Linux Qt4查看已经配对的蓝牙信息
linux·qt·蓝牙·配对
kk爱闹3 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空5 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭5 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日6 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安6 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑6 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟10 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡12 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio