低功耗蓝牙(BLE)和传感器的使用

    技术2022-07-11  120

    一、低功耗蓝牙的使用

    Android中关于蓝牙的开发文档,可以参考Google提供的官方蓝牙文档:https://developer.android.google.cn/guide/topics/connectivity/bluetooth.html

    在Android开发中,应用可通过官方提供的蓝牙API执行以下操作:

    扫描其他蓝牙设备查询本地蓝牙适配器的配对蓝牙设备建立 RFCOMM 通道通过服务发现连接到其他设备与其他设备进行双向数据传输管理多个连接

    蓝牙

    一个近距离无线通信技术,最早是由爱立信研发出来。蓝牙 Bluetooth 这个词是一个丹麦的国王的绰号,当时研发它的工程师正在看一个关于这个国王的书,就起了这个名字。蓝牙的技术特点是:

    近距离通信:典型距离是 10 米以内;传输效率:传输速度最高可达 24 Mbps多连接:蓝牙技术支持多设备连接、安全性高

    蓝牙从被发明到目前,经过了几个版本的变化:

    1.0版本:99年发布2.1版本:使用范围最广泛,经典蓝牙3.0版本:高速蓝牙,最高传输速度达到24Mbps4.0/4.1版本:新增低功耗蓝牙5.0版本:物联网

    低功耗蓝牙

    低功耗蓝牙全称为Bluetooth Low Energy,简称为BLE,最大特点就是低功耗,另外低功耗蓝牙还具备成本低,连接速度快,安全性高的特点。当然,低功耗蓝牙也相应的会有一些不足,比如说:低功耗对应的是低传输效率,因此低功耗蓝牙主要用来传输少量数据,结合低功耗的特点,非常适合用在移动智能设备上。

    低功耗蓝牙分为两种模式:单模和双模。

    单模:只能执行低功耗协议栈,即只支持BLE。双模:既支持传统蓝牙又支持BLE蓝牙。

    注意:需要在Android 4.3及以上版本才能支持具备低功耗功能的蓝牙4.0。

    BLE协议栈

    首先来看一下使用蓝牙的基本流程:

    先简单来了解一下低功耗蓝牙的协议框架,在BLE协议栈中,大致分为三个部分,从下到上依次为:控制器(Controller) 、主机(Host)、应用(Applications)。

    控制器:协议栈的最底层,直接与硬件相关,由厂商直接实现。主机:硬件层的抽象层,与具体的硬件和常见无关,可以理解为接口。应用层:使用Host层提供的API,进而开发的应用。

    协议层从下往上,依次包含如下协议:

    Attribute Protocol:简称为 ATT,属性协议,Host层的一个协议,是BLE通信的基础。ATT 把数据封装,向外暴露为“属性”,提供“属性”的为服务端,获取“属性”的为客户端。ATT 是专门为低功耗蓝牙设计的,结构非常简单,数据长度很短。每个属性都有一个唯一的UUID,属性以characteristics and services的形式传输。Generic Attribute Profile:简称为GATT,通用属性配置文件,建立在前面说的 ATT 的基础上,对 ATT 进行进一步的逻辑封装,定义数据的交互方式和含义。GATT 按照层级定义了三个概念: Service:服务,一个 Service 包含若干个 Characteristic。Characteristic:特征,一个 Characteristic 可以包含若干 Descriptor。Descriptor:描述,数据的读写操作。Generic Access Profile:简称为GAP,通用访问控制配置文件,用来控制设备连接和广播,GAP使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。

    Android BLE API

    Android SDK 中 BLE 相关的 API 都在 android.bluetooth.* 中。5.0版本中:android.bluetooth.le*

    权限

    要在 APP 中使用蓝牙功能,需要在 Manifest 中申请蓝牙相关的权限。Android 6.0及以上版本:蓝牙 + 定位权限。为什么会有定位权限?BLE有定位的功能和能力。

    BLE核心API

    BluetoothManager:蓝牙管理服务。在Android基本框架中可以发现蓝牙属于最底层的驱动模块中,可以公国context.getSystemService(Context.BLUETOOTH_SERVICE) 来进行获取。BluetoothAdapter:本地设备蓝牙适配器。BluetoothAdapter可以完成:启动设备发现,查询已绑定(配对)设备的列表,使用已知MAC地址实例化 BluetoothDevice,并创建一个 BluetoothServerSocket 以监听来自其他设备的连接请求,并启动扫描蓝牙LE设备等操作,该类属于核心中的核心。BluetoothAdapter.LeScanCallback:BLE扫描结果回调接口,在 Android 5.0以上 使用抽象类 ScanCallback。BluetoothLeScanner:蓝牙LE设备执行扫描相关操作类,使用该API要求Android 5.0(API21)以上。BluetoothDevice:远程蓝牙设备,BluetoothDevice允许创建与相应设备的连接或关于它的查询信息,例如名称,地址,类和绑定状态等。BluetoothProfile:配置文件代理。每个公共配置文件实现这个接口。它有几个直接子类,每个子类再不同场景中使用,如 BluetoothA2dp, BluetoothGatt, BluetoothGattServer, BluetoothHeadset, BluetoothHealth。在当前例子中使用到的是 BluetoothGatt。BluetoothGatt:提供蓝牙GATT功能,以实现与蓝牙智能或智能就绪设备的通信。使用该类做连接、断开、关闭等操作。BluetoothGattCallback:设备连接时的回调接口。

    UUID

    UUID 是全局唯一标识,是128bit的值,为了便于识别和阅读,一般标示成:8-4-4-12 的16进制格式。

    Android 中提供了 UUID.randomUUID() 来生成一个随机的 UUID。

    在低功耗蓝牙中,长度为128bit的UUID数据长度是受限的,因此蓝牙中又产生出来了16bit和32bit的UUID,本质上和128bit的UUID一样。

    Android 中BLE的操作步骤

    ① 获取到BluetoothAdapter:代表设备自己的蓝牙适配器,整个系统只有一个蓝牙适配器,应用程序可以使用此对象与其交互。获取方法是通过 BluetoothManager 获取。② 启用蓝牙设备:isEnable() 查看是否启用,通过 BluetoothAdapter.ACTION_REQUEST_ENABLE 来启动③ 查找BLE设备:通过startLeScan(callBack); 方法来开启扫描;另外还可以使用BluetoothLeScanner来扫描。

    与Android BLE设备通信

    开发BLE应用,主要有两大类:

    基于非连接的通信应用:使用的是BLE的广播机制,又称作是Beacon。共有两个角色:发送方负责发送广播,称之为Boradcaster,另外一方为监听方,监听广播信号,称之为Observer。基于连接的通信应用:基于连接的通信是通过建立GATT连接,让后进行数据的收发。也有两个角色:连接发起方,称之为中心设备(Central),另外一方是被连接的设备,称之为外设Peripheral。

    本篇文章中,我们来讨论面向连接的通信的情况。如果要与另外一个BLE设备进行通信,需要经过连接,确认状态,然后再通信的过程。首先是开启连接,然后会触发对应的连接回调,然后发现服务,触发发现服务回调,获取服务内部的特征值,对其读写命令(和 BLE 共同约束的规范),就是这么一个过程,比较简单。

    连接到GATT服务器:如果要与BLE进行通信,第一步就是要连接到该设备的 GATT 服务。使用connectGatt方法链接,有三个参数,最后一个参数为连接的回调函数,表是处理链接的状态,所有交互均从回调中进行处理。读 BLE 属性:一旦Android设备连接到GATT的服务器并且发现了BLE服务,则可以读取或者写入相关的属性,执行相关的操作了。释放GATT:当操作完成后,要记得关闭设备bluetoothGatt.close()。

    二、WIFI的使用

    每个移动智能设备几乎都带有WIFI连接功能,在Android系统中,同样也提供了WIFI开发的相关的API。

    WIFI API

    Android系统提供的WIFI API,主要包含在两个包中:

    android.net.wifi包android.net.wifi.p2p包

    和wifi相关的核心API主要有以下几个内容:

    WifiManager:提供管理WiFI连接的大部分APIScanResult:已经检测出的接入点(包括接入点的地址、名称、身份认证、频率、信号强度)WifiConfiguration:WiFi连接的网络配置(包括安全配置等)WifiInfo:WiFi无线连接的描述,主要包括接入点、网络连接状态、隐藏的接入点、IP地址、连接速度、MAC地址、网络ID、信号强度等等信息。WifiManager.WifiLock:通常情况下当用户在一段时间内没有任何操作的时候,WiFi网络会自动关闭。我们使用WifiLock来锁定WiFi网络,使其一直保持连接,直到这个锁被释放。多个应用程序可能有多个锁,当多有的应用程序的锁都被释放的时候,WiFi才被关闭。

    WIFI 使用说明

    WifiManager:context.getSystemService(Context.WIFI_SERVICE);打开WiFi:mWifiManager.setWifiEnabled(true); 关闭wifi为false创建一个WifiLock:mWifiManager.createWifiLock("lock_name");锁定WifiLock:mWifiLock.acquire();释放WifiLock:mWifiLock.release();WiFi连接: public void addNetworkAndConn(WifiConfiguration wcg) { int netId = mWifiManager.addNetwork(wcg); mWifiManager.enableNetwork(netId, true); } 断开一个指定ID的WiFi: public void disconnectWifi(int netId) { mWifiManager.disableNetwork(netId); mWifiManager.disconnect(); } 扫描可接入的WiFi: public void startScan() { mWifiManager.startScan(); // 得到扫描结果 List<ScanResult> wifiList = mWifiManager.getScanResults(); // 得到配置好的网络连接 List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks(); }

    WIFI 权限

    在进行wifi开发时,既要用到网络,也要用到硬件资源,因此需要申请一些必要的权限,而且涉及到的还比较的多,主要的权限如下:

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <uses-permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"></uses-permission> <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"></uses-permission>

    WIFI直连

    WIFI Direct 意为通过 WIFI 直接建立连接。允许无线网络中的设备无须通过无线路由器即可相互连接。这种标准支持 WIFI 的无线设备像蓝牙那样以点对点的形式互连,但是在传输速度与传输距离方面都比蓝牙有大幅提升。

    WIFI Direct 提供 WifiP2pManager 类,其功能主要分为以下三部分:

    WifiP2pManager 类提供相关 API 用于发现可连接的点,并进行请求和建立连接。每个 WifiP2pManager 的方法都要求传入对应的监听器,用于监听对该方法是否成功运行。当检测到特定事件,如可连接的点减少或者发现了新的可连接的点,WIFI Direct 框架会通过 Intent 通知用户。

    WifiP2pManager的核心API用法说明如下所示:

    initialize:为应用程序注册 WIFI 框架。该方法必须在任何其他 WIFI Direct 方法被调用前调用,常放在Application中调用。connect:与具有指定配置的 WIFI 设备建立点对点连接cancelConnect:断开连接requestConnectInfo:获取设备的连接信息createGroup:以当前设备为拥有者创建一个点对点组removeGroup:删除当前的点对点组requestGroupInfo:获取点对点组的信息discoverPeers:初始化发现对等点设备服务requestPeers:获取当前已发现的对等点设备列表

    在WifiP2pManager使用时,同样支持使用各种监听回调接口:

    ActionListener:Wifi连接过程中的某个动作监听。主要包括:connect、cancelConnect、createGroup、removeGroup、discoverPeers等回调函数ChannelListener:initialize初始化的回调ConnectionInfoListener:请求连接的回调,回传连接信息GroupInfoListener:点对点组的监听信息PeerListListener:点对点设备的监听回调接口

    三、传感器

    Android 传感器属于虚拟设备,可提供来自以下各种物理传感器的数据:

    加速度计陀螺仪磁力计、气压计湿度传感器压力传感器光传感器近程传感器心率传感器

    以上的这些均可以归纳为传感器类别,在Android中,这些传感器有一个相同的定义文件,存在一个 sensors.h文件,其中定义了Android系统支持的每一种传感器。格式为:ENSOR_TYPE_传感器名称。

     

     

    该图为Android系统中传感器的的架构和分层。可以看出,几乎和Android系统整体的架构一样。从上层到下层,从应用层到底层内核层。

    传奇器核心API

    Android传感器框架放在android.hardware包中,核心的API如下所示:

    SensorManager:用于创建传感器服务实例。该类提供了访问和罗列传感器的各种方法,用于注册和注销传感器事件监听器并获取方向信息。该类也提供了几个常量,用于报告传感器的精度、数据获取率和校正传感器。Sensor:用作创建某个特定传感器的实例。该类提供了用于确定传感器能力的各种方法。SensorEvent:创建传感器事件对象。传感器事件对象包含传感器事件的相关信息,包括原始的传感器数据、传感器类型、产生的事件、事件精度以及事件发生的时间戳等。SensorEventListener:是一个接口,包含两个回调方法。当传感器的值发生改变或者传感器的精度发生改变时,相关方法就会自动被调用。

    传感器核心操作

    无论如何变化,其实通过上面的描述和介绍,我们看到,传感器是底层系统提供的,数据也是相关的API返回获取的。因此,在涉及到传感器开发时,开发者的核心操作只有两个:

    分析需求,明确使用哪个一个类别的传感器,明确要获取的传感器数据。调用系统的API方法,监听传感器的的回调时间,获取数据。

    因此,Android中的传感器部分的应用开发,重点不是在于传感器的使用,是开发者自己特定的应用,在获取到数据后,对数据的处理和挖掘,是重中之重。

    Android传感器分类

    Android中支持的传感器分为很多类别,主要有:

    TYPE_ACCELEROMETER:运动探测传感器,硬件传感器TYPE_AMBIENT_TEMPERATURE:环境温度传感器,硬件传感器TYPE_GRAVITY:运动探测,软件或者硬件传感器TYPE_GYROSCOPE:旋转,硬件传感器TYPE_LIGHT:屏幕亮度传感器,属于硬件传感器TYPE_LINEAR_ACCELERATION:加速度传感器,软件或者硬件都有TYPE_ORIENTATION:方向传感器,属于软件传感器TYPE_PRESSURE:空气压力传感器,属于硬件传感器TYPE_PROXIMITY:距离传感器,用于监测打电话时手机与耳朵的距离,属于硬件传感器

    四、SystemService

    经过本篇文档的介绍,结合之前的课程内容,我们可以总结出一个规律。在Android开发时,很多情况下我们都可以直接通过某个上下文,获取xxxManager,往往是某个管理者。这些管理者是Android系统提供的系统服务,我们可以统称为SystemService,现在我们了解一下SystemService有关的内容,并做个总结。

    SystemService

    SystemService是系统提供给开发者的调用系统层的控制接口,应用层的开发者只需要了解这些接口的使用方式,就可以非常方便的进行系统控制,完成自己想要的功能操作,获取系统的相关信息,而不需要了解接口的具体内部实现方式。这些SystemManager是在framework层或者更底层进行实现的。

    相反的对于Framework层的开发者而言,需要了解XXXManager服务的实现细节和方式,并维护Manager接口,扩展或者实现新接口等。

    我们可以列举一下我们在学习过程中遇到的Manager,比如:

    WindowManager:窗口操作的窗口管理服务NotifacationManager:通知管理AudioManager:Android系统的音频管理者LocationManager:GPS定位服务管理StatusBarManager:状态栏的管理者

    除此以外,还有很多很多,以上这些管理者,其实背后都是有一个系统服务SystemService。

    getSystemService

    getSystemService是Android很重要的一个API,它是Activity的一个方法,根据传入的NAME来取得对应的Object,然后转换成相应的服务对象。

    Processed: 0.009, SQL: 9