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

一、低功耗蓝牙的使用

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版本:高速蓝牙,最高传输速度达到24Mbps
  • 4.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连接的大部分API
  • ScanResult:已经检测出的接入点(包括接入点的地址、名称、身份认证、频率、信号强度)
  • 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,然后转换成相应的服务对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值