公司最近的项目是一款带投影的智能Android手表开发,提及到穿戴设备,便携设备以及车载多媒体肯定设计到蓝牙开发。对于一般的软件开发人员,蓝牙基本不会用到,或许只用来传文件。其实蓝牙不仅仅可以做这些,还可以进行设备间通信,收发指令等等。公司一代产品用的是经典蓝牙进行通信,由于耗电的原因改为BLE通信。

哇,第一次这么认真的坐下来写笔记,长话短说,接下来主要从经典蓝牙和BLE两方面聊聊蓝牙开发的这些事儿。

一 蓝牙是什么?能做什么?

蓝牙是一种无线技术标准,可实现设备间短距离数据交换。

蓝牙可以以一定的周期发送广播,手机端接收到广播后,解析广播包,可做设备识别、配对,事件通知以及指令控制等。低精度定位根据设备的信号强度,可以估算出大概方位和距离。

二关于蓝牙4.0

相对比较新的蓝牙标准。蓝牙4.0标准包含两个蓝牙标准,准确的说,是一个双模的标准,它包含传统蓝牙部分(也有称之为经典蓝牙Classic Bluetooth)和低功耗蓝牙部分(Bluetooth Low Energy)。

传统蓝牙可以用于数据量比较大的传输,如语音,音乐,较高数据量传输等,但是比较耗电,低功耗蓝牙这样应用于实时性要求比较高,功耗比较低,但是数据速率比较低的产品,如遥控类的,如鼠标,键盘,遥控鼠标(Air Mouse),传感设备的数据发送,如心跳带,血压计,温度传感器等。公司Android手表就是考虑到功耗问题,把通信由原来的经典蓝牙改成BLE通信!

三蓝牙通信

前置条件:

首先,要操作蓝牙,先要在AndroidManifest.xml里加入权限
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permissionandroid:name="android.permission.BLUETOOTH" />

除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature:

通信流程:

发现设备->配对/绑定设备->建立连接->数据通信

1. 发现设备

经典蓝牙设备发现其它经典蓝牙设备的方式是调用BluetoothAdapter的startDiscovery()方法,这个方法只能够发现经典蓝牙设备。

低功耗蓝牙中则有一个主设备(Central)和从设备(Peripheral,也叫外围设备)的概念。主设备作为发现方(一般为手机)调用发现设备的方法,通过BluetoothAdapter的startLeScan()方法实现。从设备则作为被发现方(穿戴设备,便携设备等),发出广播,以供发现。同样,这个startLeScan()方法也仅能够发现低功耗蓝牙从设备,在整个搜索过程中,功耗是比较大的,应尽快结束搜索。

发现设备比较重要,实践中有2个比较重要的点:

1 经典蓝牙配对前,如果没有扫描过程,通过蓝牙地址直接配对,配对对话框可能不出现,以消息通知栏的方式呈现。如果扫描过,则会弹出配对对话框。

2 ble连接前,如果没有扫描过程,通过蓝牙地址直接连接,可能连不上。如果扫描并发现外围设备,则会连接成功。

2. 配对/绑定

配对指的是BLE设备的配对。配对的作用在于和设备做相互确认,一方面是确定要操作的设备,另一方面是考虑到安全因素。

经典蓝牙可通过createRfcommSocketToServiceRecord 和 Method creMethod = BluetoothDevice.class.getMethod("createBond"); creMethod.invoke(mBluetoothDevice);

ble蓝牙在连接的过程中 自动配对,但不弹出配对对话框。

3. 建立连接

在建立连接的方式上,两者就千差万别了。

——蓝牙小知识——

在蓝牙设备中,存在着物理地址,我们也叫作蓝牙的MAC地址,这个地址是唯一的,就像咱们网络上的IP地址。同时还存在着一个叫做UUID的东西,可以把它理解为是IP地址中的端口号。正如知道了IP地址和端口号,就知道了怎么链接到目标网络服务器位置,知道了蓝牙设备的MAC地址和UUID也就能够确定到具体是哪一台蓝牙设备了,这两者合起来就是蓝牙的唯一身份标识。BLE扫描的过程,设备会生成随机地址。根据随机地址也能进行连接。

经典蓝牙建立连接的方式实际上就是Socket的连接的建立。只不过这里不是直接用Socket,而是BluetoothSocket。获取BluetoothSocket的方式也很简单,利用搜索找到的BluetoothDevice,调用其方法createRfcommSocketToServiceRecord(UUID)。最后,使用获取到的BluetoothDevice调用其方法connect()就建立了经典蓝牙设备之间的连接通道。

低功耗蓝牙则用了一种看起来比较怪异的方式建立连接(JACK的机器人被这种建立连接的方式折腾了好久)。

——关于BLE的一些基本概念——

Generic Attribute Profile (GATT)

通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。

Attribute Protocol (ATT)

GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。

Characteristic

Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。

Descriptor

对Characteristic的描述,例如范围、计量单位等。

Service

Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement”的Characteristic。

这里举个例子,例如现在需要使用一个智能手机作为主设备去连接一个作为从设备的智能手环,那么,此时这个作为主设备的智能手机连接过程中实际是一个客户端(Client),而作为从设备的智能手环在此过程中则是服务端(Server)。这里的主设备和从设备,客户端和服务端一定要区分清楚。

想要和一台BLE从设备建立连接,一般是某个智能设备,例如智能手环、智能灯泡之类的。如果使用智能手机作为测试平台,其硬件条件是,蓝牙得至少是低功耗蓝牙版本,然后安卓系统的话,至少得是Android 4.3以上系统才行,因为Google在Android 4.3以上才做了BLE主设备的支持,如果想将智能手机作为BLE从设备,则必须在Android 5.0以上才行。

具体建立GATT连接的顺序则是,首先通过BluetoothAdapter的getRemoteDevice(address)方法获取大相应BLE从设备的BluetoothDevice,其中的address为目标蓝牙设备MAC地址。然后通过此BluetoothDevice的connectGatt(this, false, mGattCallback)方法获取设备连接。

此时的连接,只能够进行监听,也就是获取到当前BLE从设备广播出来的数据。

4. 数据通信

经典蓝牙中,当建立连接后,就可以直接使用BluetoothSocket的getOutputStream()方法获取输出流写入需要发送的数据。读取发送回来的数据,则是调用BluetoothSocket的getInputStream()方法获取输入流读取。这点和Java中的Socket通信几乎是一模一样。

而在低功耗蓝牙中,想要实现主设备对从设备的数据发送,则需要直接读取获取到的从设备的Characteristic,而Characteristic又是Service下面的一层,所以操作顺序是:

(1)通过BLE从设备相应的Service_UUID获取对应的BluetoothGattService,获取方法是:使用BluetoothDevice的connectGatt(this, false, mGattCallback)方法返回的BluetoothGatt对象,调用BluetoothGatt的方法getService(Service_UUID)获取相应的BluetoothGattService;

(2)调用BluetoothGattService和对应的Characteristic的写入UUID获取相应的BluetoothGattCharacteristic,获取方法是:调用BluetoothGattService的getCharacteristic(Characteristic_UUID)方法获得;

(3)设置需要发送的命令值,调用BluetoothGattCharacteristic的方法setValue(value)进行设置,其中value一般为byte[];

(4)最后,使用BluetoothGatt的写入方法writeCharacteristic(TxChar)完成命令发送。

如果想要获取到BLE从设备的返回值,还需要设置Notification,然后调用BluetoothGatt的readCharacteristic(characteristic)方法进行数据的读取,这里不做详细说明了,放在以后详细说明BLE通信的时候再做解释。

可以看到,想要实现BLE的数据通信,还需要做分包处理,加密处理,协议规定,这里只是做一个简单的概念理解。

后续会更新经典蓝牙通信代码篇 和 BLE通信代码篇。

Android蓝牙开发实战总结相关推荐

  1. 《Android Studio开发实战 从零基础到App上线(第2版)》出版后记

    2015年11月23日,鄙人在csdn发表了第一篇技术文章,掐指一算距今已有三年.遥想当年开写博客,只是为了总结经验同时分享出来,后来机缘巧合受到出版社编辑邀请并出了书,完全是无心插柳的结果.当初写作 ...

  2. 《Android Studio开发实战 从零基础到App上线》源码运行问题解答

    本书提供了所有章节的完整源码下载,自上市以来陆续收到读者的意见反馈,现将与源码有关的问题汇总归类如下,方便更多的朋友解决源码运行过程中发现的问题: 一.打开本书源码时,出现"Plugin w ...

  3. 《Android Studio开发实战 从零基础到App上线》第一版的资源下载和内容勘误

    资源下载 下面是<Android Studio开发实战 从零基础到App上线>(第一版)一书用到的工具和代码资源: 1.本书使用的Android Studio版本为2.2.3,因为Andr ...

  4. 《Android NFC开发实战详解》——6.4节Android NFC P2P开发进阶

    本节书摘来自异步社区<Android NFC开发实战详解>一书中的第6章,第6.4节Android NFC P2P开发进阶,作者 赵波,更多章节内容可以访问云栖社区"异步社区&q ...

  5. 《Android Studio开发实战 从零基础到App上线(第3版)》出版后记

    2018年11月,经过熬夜写作的<Android Studio开发实战 从零基础到App上线(第2版)>正式出版面世.承蒙众多读者的厚爱,第2版的图书在此后的三年多时间,一直保持在移动开发 ...

  6. Android NFC开发实战详解

    Android NFC开发实战详解 Android开发实战详解NFC国内第一本AndroidNFC开发书籍带你开启AndroidNFC开发的神秘之旅大综合案例帮助读者快速进入实战角色:WiFi快速连接 ...

  7. Android 蓝牙开发,申请打开蓝牙

    申请打开蓝牙 <!-- 蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH" ...

  8. android蓝牙聊天设备,Android蓝牙开发——实现蓝牙聊天

    最近课上刚好需要做一个课程设计关于蓝牙的就挑选了个蓝牙聊天室,其实关键还是在于对蓝牙API的了解 一.蓝牙API 与蓝牙开发主要的相关类是以下四个 BluetoothAdapter 字面上则理解为蓝牙 ...

  9. Android蓝牙开发系列文章-蓝牙设备类型知多少?

    在写<Android蓝牙开发系列文章-蓝牙音箱连接>时,计划细化出一篇讲解蓝牙设备类型的文章,现在它来了~ 阅读其他内容,可以点击<Android蓝牙开发系列文章-策划篇>,或 ...

  10. Android蓝牙开发(一)之打开蓝牙和设备搜索

    Android蓝牙开发系列目录: https://blog.csdn.net/huangliniqng/article/details/82185635 一.判断是否系统是否支持蓝牙 在使用蓝牙之前, ...

最新文章

  1. 【OpenCV】图片操作小结:RAW图转image以及image连续保存
  2. java maven -DskipTests 和 -Dmaven.test.skip=true 区别
  3. 自动升级失败,缺少System.resources.dll?
  4. [设计模式] 8 组合模式 Composite
  5. solaris mysql_配置Solaris下自带的MYSQL
  6. uds帧格式_UDS诊断帧
  7. 职场上别人只做不说的潜规则
  8. expander菜单控件_《WPF》Expander控件简单美化
  9. n皇后问题(在棋盘上找方案)
  10. arm裸板驱动总结(makefile+lds链接脚本+裸板调试)
  11. 本程序是三菱FX3U PLC编写的铝材过秤包装平台
  12. 为什么边缘概率密度是联合概率密度的积分_5.27005柏林联合VS美因茨
  13. matlab对多维数组转置,C++向matlab engine传递二维数组,互为转置
  14. 网易云通信 java 登录,网易云IM(即时通讯) 集成指南(Android)
  15. 笔记本计算机管理没有键盘,如何禁用笔记本键盘输入?怎么关闭笔记本键盘
  16. 【EF】对象名 'dbo.EdmMetadata' 无效。
  17. 点对点传输现状,镭速高速点对点传输解决方案
  18. 面向毕业、职称的SCI论文高效写作方法
  19. 微软将推新AI聊天机器人Zo 可能是小冰的英文版
  20. 《实用VC编程之玩转控件》第7课:ListBox 列表控件

热门文章

  1. 怎么做QQ、微信等消息气泡
  2. jquery.event 研究学习之bind篇
  3. Rinetd.exe 通过 instsrv.exe/srvany.exe 注册服务实现稳定端口转发
  4. Harvest: A high-performance fundamental frequency estimator from speech signals
  5. 深度学习图像分类(一):LeNet
  6. videojs如何获取请求消息_WEB之基于HTTP协议的几种实时数据获取技术
  7. cfile read 最大读取限制_Read文件一个字节实际会发生多大的磁盘IO?
  8. vue-cli 2.6.9 安装卸载及创建一个工程
  9. ubuntu16.04 修改分辨路并永久保存
  10. Android gdb 调试