• Android 蓝牙开发(2)——低功耗蓝牙


    低功耗蓝牙官方文档

    本文章是参考官网,然后加入自己实践中的理解完成!没有看上一篇的读者,可以先阅读一下前一篇,这是一个系列。
    官网地址:https://developer.android.com/guide/topics/connectivity/bluetooth-le

    Android 4.3 (API 18 )引入了低功耗蓝牙,应用可以查询周围设备、查询设备的服务、传输信息。

    关键术语和概念

    • 通用属性配置文件(GATT Generic Attribute Profile)

      GATT 配置文件是一种传输数据规范,用于在 BLE 链路上发送和接受被称为属性的短数据的通用规范。目前所有低功耗应用配置文件基本都是基于 GATT

    • Bluetooth SIG (蓝牙技术联盟)

      是为低功耗设备定义了许多配置文件。配置文件是设备在特定应用程序中的工作方式的规范。设备可以实现多个配置文件。例如,设备可以包含心率监测器和电池水平检测器。

      定义规范的

    • 属性协议(ATT Attribute Protocol)

      GATT 是建立在属性协议(ATT)之上的。也被称为 GATT/ATT 。ATT 经过优化,可在 BLE 设备上使用。为此,它使用了尽可能少的字节。每个属性由通用唯一标识符(UUID)来唯一标识。ATT 传输的属性被格式化为 特征服务

    • 特征

      特征包含单个值和描述特征值的 0 ~ n 个描述符。特征值可以被称为类型。类似于类。(是在和 BLE 设备进行通信的时候主要的操作内容)

    • 描述符

      是用来定义特征值的已定义属性。用来描述特征值的。例如:描述符可以指定人类可读的描述,特征值的可接受范围或者特征值特定的度量单位

    • 服务

      服务中包含一系列的特征值。例如,我们可以使用名为 “心率监测器”的服务,其中包括"心率测量"等特征。可以在 bluetooh.org 上找到基于 GATT 的现有配置文件的服务的列表。

    角色和责任

    Android 设备和 BLE 设备交互时应用的角色和职责

    • 中央与外围设备。
    • GATT 服务器和 GATT 客户端。确定了两个设备建立连接后如何进行相互通信

    BLE 权限

    应用在使用蓝牙设备的时候必须要声明蓝牙权限 BLUETOOTH 需要这个权限才可以进行蓝牙通信,例如:请求连接、接受连接、和传输数据。

    如果还需要发现或者操作蓝牙设置,则需要声明 BLUETOOTH_ADMIN 权限。使用这个权限的前提是要有 BLUETOOTH 权限。

    如果要声明我们的应用仅适用于支持 BLE 的设备,需要清单文件中做如下声明

    <uses-feature android:name = "android.hardware.bluetooth_le" android:required = true />
    

    如果我们希望我们的应用程序在不支持 BLE 的设备上也可以运行的时候,只需要将 true 修改成 false 就可以了。

    还可以在代码中作出判断

    if(!getPackageManager().hasSystemFeature(PackgeManger.FEATURE_BLUETOOTH_LE)){
        // 不支持 BLE 设备
    }
    

    BLE 通常和位置有关系,因此还需要声明位置权限 ACCESS_COARSE_LOCATION 或者 ACCESS_FINE_LOCATION 没有这些权限扫描将不会返回任何结果。

    设置 BLE

    1. 获得 BluetoothAdapter

      BluetoothAdapter 代表设备自己的蓝牙适配器,整个系统只有一个蓝牙适配器,我们的应用程序可以使用此对象与其交互。

      这里的获取方法是通过 BluetoothManager 来获取的

      BluetoothManager bluetoothManger = getSystemSerive(Context.BULETOOTH_SERVIcE);
      BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
      
    2. 启用蓝牙设备

      其实这些和普通蓝牙的启动都是一样的。

      isEnable() 查看当前是否启用了蓝牙

      通过 BluetoothAdapter.ACTION_REQUEST_ENABLE 来启动

    3. 查找 BLE 设备

      这一点和发现普通的蓝牙设备是不一样的

      // 通过 Adapter 的 startLeScan(callBack); 方法来开启扫描
      // 如果我们有指定的蓝牙设备可以使用
      sartLeScan(UUID[],BluetoothAdapter.LeScanCallBakc) 通过 UUID 来指定 BLe
      // 这个方法已经过时了,官方文档最新支持的扫描蓝牙的方法是通过一个专门的对象 BluetoothLeScanner 用来开启扫描低功耗蓝牙
      BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
      // 这个方法可以有参数,用来过滤要扫描的低功耗蓝牙的,具体的后面讲
      scanner.startScan();
      
      

      只能单独扫描普通蓝牙设备或者 BLE 设备,没有方法同时执行

    连接到 GATT 服务器

    与 BLE 设备通信,第一步就是要连接到它,就是连接到该设备的 GATT 服务。使用方法 connectGatt()有三个参数:Context 对象 autoConnect (表示是否在可用的时候自己连接到 BLE 设备) 还有一个回调,所有的交互都在这个回调里面完成。

    调用这个方法会返回一个 BluetoothGatt 对象,通过这个对象进行和 BLE 设备的交互。交互的结果会在回调方法中触发。

    public class BluetoothLeService extends Service{
        private final static String TAG = BluetoothLeService.class.getSimpleName();
        private BluetoothManger bluetoothManger;
        private BluetoothAdapter bluetoothAdapter;
        private String bluetoothDeviceAddress;
        private BluetoothGatt bluetoothGatt;
        private int connectionState = STATE_DISCONNECTED;
        
        private static final int STATE_DISCONNECTED = 0;
        private static final int STATE_CONNETING = 1;
        private static final int STATE_CONNECTED = 2;
        
        public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
        public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
        public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
        public final satic String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
        public final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA";
        
        public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.formString(SampleGattAttributes.HEART_RATE_MEASURMENT);
        
        private final BluetoothGattCallback gattCallback = new BluetoothGattCallback(){
            // 你的中央设备连接上 ble 设备后,会回调这个这方法。
            @Override
            public viod onConnectionStateChange(BluetoothGatt gatt,int status,int newState){
                String intenAction;
                if(newState == BluetoothProfile.STATE_CONNECTED){
                    intentaction = ACTION_GATT_CONNECTED;
                    connectionState = STATE_CONNECTED;
                    broadcastUpdate(intentAction);
                    // 连接上后,紧接着就是要寻找里面 Service
                    bluetoothGatt.discoverServices();
                }else if(newState = BluetoothProfile.STATE_STATE_DISCONNECTED{
                    intentAction = ACTION_GATT_DISCONNECTED;
                    connectionState = STATE_DISCONNECTED;
                    broadcastUpdate(intentAction);
                    
                }
               
            }
            @Override
            // service 发现后就会触发这个方法,然后你就需要找到你和 ble 约定好的 service
            public void onServicesDiscovered(BluetoothGatt gatt,int status){
                if(status == BluetoothGatt.GATT_SUCCESS){
                    broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
                }            
            }
    		
            public void onCharacteristicREad(。。。){
                             
            } 
            .......
                     
            
            
        }
        
    }
    

    当触发特定的回调的时候,会调用适当的 broadcastUpdate() 辅助方法并向其传递操作。具体的数据解析格式是根据配置文件规范执行的(是你和你的BLE 设备共同约定好的规范)

    大体的过程中:开启连接,然后会触发对应的连接回调,然后发现服务,触发发现服务回调,获取服务内部的特征值,对其读写命令(和 BLE 共同约束的规范)。就是这么一个过程,很简单。

    读 BLE 属性

    一旦我们的 Android 设备连接到了 GATT 服务器并发现了服务,我们就可以在支持的位置读取或者写入属性了。

    完成后要记得关闭设备 bluetoothGatt.close();

    关于蓝牙框架的一个库:https://github.com/Alex-Jerry/Android-BLE

  • 相关阅读:
    CentOS 中安装和更新 git 客户端工具
    Python 快速入门笔记(2):数据类型
    Python 快速入门笔记(1):简介
    JavaScript快速入门笔记(15):Web storage 之 localStorage 和 sessionStorage
    JavaScript快速入门笔记(14):session
    JavaScript快速入门笔记(13):cookie
    JavaScript快速入门笔记(12):Ajax之XMLHttpRequest、jQuery、fetch()
    JavaScript快速入门笔记(11):事件处理
    python的线程和进程
    python中字符串编码转换
  • 原文地址:https://www.cnblogs.com/sydmobile/p/11161182.html
Copyright © 2020-2023  润新知