看见标题小伙伴们大概能看出我今天要说的是什么了!由于近来公司项目中有关于Ble方面的需求,对于Bluetooth方面的相关知识,因为这种需求工作中不多(你如果从事于智能硬件相关的岗位那另说),所以之前我也只是写过一些小demo(还是2.0的),没有实战过。再加上这次用的是4.0,所以我也是急忙的涉猎了一波。。那么对于蓝牙的前世今生这里我就不多废话,大家有兴趣可以直接度娘,蓝牙在Android系统中总的来说分为两大阶段;一个是经典蓝牙时期(在1.x~3.0之间),后面到现在的话就是比较流行的Ble全称为Bluetooth low energy也就是低功耗蓝牙它的版本是从4.x开始,当然5.0的蓝牙模块目前Google虽已发布,但是市场上的手机还远未普及(ps: Android之父Andy Rubin推出的Essential Phone已经配备),但是从各方面看它也绝对是最强的蓝牙版本了!在真正coding之前,我们有必要清楚ble工作方式

一。Ble的区别与优势

首先低功耗蓝牙较传统蓝牙,传输速度更快,覆盖范围更广,安全性更高,延迟更短,耗电极低等等优点。这也是为什么近年来智能穿戴的东西越来越多,越来越火。还有传统蓝牙与低功耗蓝牙通信方式也有所不同,传统的一般通过socket方式,而低功耗蓝牙是通过Gatt协议来实现。现在我们所处在一个蓝牙4.x的时代。在此之前如我们经常使用的蓝牙耳机就已经跨越了好多的版本 蓝牙耳机有v1.1 v1.2 v2.0 v2.1…等诸多版本,究竟有什么样的优势呢?当然是版本越高信号越好,2.0以上支持蓝牙立体声。那么我们现在所处的4.x的设备大多是属于主从模式的。什么是主从模式?一个主设备比如手机,一个从设备(这里也称为子设备或从机)主动搜索从机 可以发送 也可以接收, 从机也可以发送和接收 但只能被搜索。

二。BLE设备有什么东西

一个BLE终端可以包含多个Service(服务)一个Service可以包含多个Characteristic(特征)一个Characteristic包含一个value和多个Descriptor(描述符),一个Descriptor包含一个Value。我们要注意的是,每一个Service、Characteristic都会有一个uuid,这是一个唯一值,我们接下来的传输数据,将用到这个。每一个Characteristic都有一个Value,我们就是通过改变这个值,来对设备进行交互的。举个生活中的小例子就是你去学校找一个学生,前提是得知道哪个班级,这里学校就相当于一个bluetoothdevice,班级则是BluetoothGattService而学生就是BluetoothGattCharacteristic,大家可能发现我这些名词基本都包含了BluetoothGatt,没错这就是ble通讯的关键,我们可以把它看成Android手机与BLE终端设备建立通信的一个管道,只有有了这个管道,我们才有了通信的前提。

三,FastBle的简单使用

前面铺垫了这么多,我想大家会对Ble有一个基本认知,好了,接下来我将介绍一下FastBle(Github ble开源框架排名首位)的基本使用(前人种树,后人乘凉,如果有好的框架我们当然要学会使用,毕竟在这个时间就是金钱的时代,效率非常重要,当然是在对基础了解的情况下),首先为了对作者的尊敬,在这里贴出项目地址:https://github.com/Jasonchenlijian/FastBle 欢迎大家给作者star,fork

限于文章篇幅,这里只会介绍一小部分常用的api,如果大家想详细了解,我这里给上作者的中文文档地址供大家学习https://github.com/Jasonchenlijian/FastBle/wiki

好了,接下来我将贴出我的代码一起学习:  首先在项目module的build.gradle文件里添加

implementation 'com.clj.fastble:FastBleLib:2.3.2'

这种写法是AS3.0之后Google 推荐的大家少部分人可能看着陌生 ,随后配置相关权限(注意这里有很多坑)

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

这第一和第二个权限呢是蓝牙必备的,而后面两种(位置权限)则在6.0以上的系统中需要加入,否则会搜索不到,随后你还需要在代码中动态申请该权限,和定位(这里我就不啰嗦了,Android6.0动态申请权限大家应该比较熟悉了)

BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder().setScanTimeOut(5000)              // 扫描超时时间,可选,默认10秒.build();
BleManager.getInstance().init(getApplication());
BleManager.getInstance().initScanRule(scanRuleConfig);
BleManager.getInstance().enableLog(true).setReConnectCount(1, 8000).setOperateTimeout(8000);

这段代码是FastBle的全局配置(是否运行日志,设置连接时重连次数和重连间隔(毫秒),默认为0次不重连,等等)

//初始化蓝牙适配器
final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {Toast.makeText(this, "您的设备不支持蓝牙BLE,将关闭", Toast.LENGTH_SHORT).show();finish();
}

这前面这些代码是为真正开始搜索蓝牙设备做个基调,好了现在我们就开始搜索了,

private void startScan() {BleManager.getInstance().scan(new BleScanCallback() {// 开始扫描(主线程)@Overridepublic void onScanStarted(boolean success) {}@Overridepublic void onLeScan(BleDevice bleDevice) {super.onLeScan(bleDevice);}@Overridepublic void onScanning(BleDevice bleDevice) {}@Overridepublic void onScanFinished(List<BleDevice> scanResultList) {// 扫描结束,列出所有扫描到的符合扫描规则的BLE设备(主线程)});
}

扫描完成后把设备数据填充列表即可(有木有感受到框架的强大之处,简化了很多操作),之后我们在列表点击的时候将其connect

BleManager.getInstance().connect(bleDevice, mCallback);

只需将该设备实体传入方法即可,其实核心就是这个callback回调,我们看看这里的流程

private BleGattCallback mCallback = new BleGattCallback() {@Overridepublic void onStartConnect() {}@Overridepublic void onConnectFail(BleDevice bleDevice, BleException exception) {}@Overridepublic void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {}@Overridepublic void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {}
};

四个方法回调大家看这单词意思也能大概明白(第一个是onStartConnect开始连接,onConnectFail连接失败,onConnectSuccess连接成功,最后还有个断开连接onDisConnected),回调方法的生命周期与你的初始化有关系,也就是说如果你是在application里单例的话,那么回调将在你整个APP运行期间持续,前提是你不手动断开,好了,接下来才真正来到通信的环节,毫无疑问你得在连接成功时做这个,

service = gatt.getService(UUID.fromString("0000fee9-0000-1000-8000-00805f9b34fb"));
List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
for (int i = 0; i < characteristics.size(); i++) {if ((characteristics.get(i).getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {//接受数据} else if ((characteristics.get(i).getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {//写数据}
}

前面我提到了Ble的通信首先是gatt ,根据它你得找到你需要的service,和需要的特征来读 写,收听操作,我记得刚开始自己做的时候,就一直纠结一个问题 ,一个蓝牙设备 有那么多service和特征我怎么知道到底找哪个呢,这里我告诉你,不要想太多,当然是找硬件要了,要啥,,,?  uuid.就是上面那一串字符,关于UUID,想了解清楚的话,大家自行解决。。这里可用看到每个特征都有自己的用途,一般来说就是这几种(write,read,notify)

我们来看看写操作:

BleManager.getInstance().write(bleDevice,bluetoothGattCharacteristic.getService().getUuid().toString(),bluetoothGattCharacteristic.getUuid().toString(),数据,writeCallback);

这个方法需要你传入蓝牙设备实体类,service的uuid,特征的uuid,和你需要写的字符,最后去实现一个callback回调,我们来看看

private BleWriteCallback writeCallback = new BleWriteCallback() {@Overridepublic void onWriteSuccess(final int current, final int total, final byte[] justWrite) {runOnUiThread(new Runnable() {@Overridepublic void run() {//Toast.makeText(BleDeviceDetailActivity.this, "写入成功", Toast.LENGTH_SHORT).show();}});}@Overridepublic void onWriteFailure(final BleException exception) {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(BleDeviceDetailActivity.this, "写入失败", Toast.LENGTH_SHORT).show();}});}
};

两个方法分别为写入成功和失败,非常人性化有木有。如果写入成功后,蓝牙设备如果有回复的话,会在notify特征中接收

BleManager.getInstance().notify(bleDevice,bluetoothGattCharacteristic.getService().getUuid().toString(),bluetoothGattCharacteristic.getUuid().toString(),notifyCallback);
 

前提你的开启notify,传入的参数和上面一致,我们同样来看看callback

private BleNotifyCallback mnotifyCallback = new BleNotifyCallback() {@Overridepublic void onNotifySuccess() {//接收成功runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(BleDeviceDetailActivity.this, "接收成功", Toast.LENGTH_SHORT).show();}});}@Overridepublic void onNotifyFailure(BleException exception) {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(BleDeviceDetailActivity.this, "接收失败", Toast.LENGTH_SHORT).show();}});}@Overridepublic void onCharacteristicChanged(final byte[] data) {runOnUiThread(new Runnable() {@Overridepublic void run() {HexUtil.formatHexString(data);//拿到数据进行操作}});}
};

里面已经写的很直白了,重点关注onCharacteristicChanged方法,这里是我们拿数据的地方,这样我们就实现和ble设备的通信了,值得注意的是这三个回调都不是在主线程完成的,这点大家记住了,由于安卓当中不允许在UiThread中进行耗时的操作而且还是异步的!大家清楚性能优化的都知道,在Android中activity响应的时间不能超过5秒,广播是10秒,否则就会引起程序无响应进而崩溃,也就是ANR(Application Not Responding)错误,所以蓝牙操作都是异步的,也就是在小线程里发生的,而我们更新UI的话又必须回到mainthread,所以就用到了runOnUiThread方法,当然也可以用Handler(runOnUiThread方法底层实现其实就是handler),值得注意的是接收的数据是以字节数组的形式,所以你得转成你想要的类型,

好了!以上就是ble通信的全过程,当然一些细节大家在coding的时候自己多加注意就行!

Android开发之Ble(Bluetooth low energy)初识相关推荐

  1. 基于蓝牙4.0的蓝牙打印机 低耗电蓝牙 BLE (Bluetooth Low Energy)

    作者:朱克锋 邮箱:zhukefeng@iboxpay.com 转载请注明出处:http://blog.csdn.net/linux_zkf 基于蓝牙4.0的蓝牙打印机 低耗电蓝牙 BLE (Blue ...

  2. Android ble连接过程,Android开发之ble蓝牙

    前言 由于自己工作中需要开发ble的项目,于是在折腾了一段时间后也有所了解,便想写下来分享给大家,同时对自己的知识也是一种巩固 1.BLE介绍 BLE是Bluetooth Low Energy的缩写, ...

  3. 安卓在4.3的系统中提供了低功耗蓝牙Bluetooth Low Energy

     1.简介 BLE(Bluetooth Low Energy,低功耗蓝牙)是对传统蓝牙BR/EDR技术的补充.尽管BLE和传统蓝牙都称之为蓝牙标准,且共享射频,但是,BLE是一个完全不一样的技术. ...

  4. Bluetooth Low Energy 介绍

    1.简介 BLE(Bluetooth Low Energy,低功耗蓝牙)是对传统蓝牙BR/EDR技术的补充.尽管BLE和传统蓝牙都称之为蓝牙标准,且共享射频,但是,BLE是一个完全不一样的技术.BLE ...

  5. Bluetooth Low Energy 介绍 低功耗蓝牙介绍

    1.简介 BLE(Bluetooth Low Energy,低功耗蓝牙)是对传统蓝牙BR/EDR技术的补充.尽管BLE和传统蓝牙都称之为蓝牙标准,且共享射频,但是,BLE是一个完全不一样的技术.BLE ...

  6. Android:BLE(Bluetooth Low Energy)开发

    Demo下载 demo下载 BLE介绍 最近穿戴设备发展得很火,其大多数所用的技术是BLE(Bluetooth Low Energy).BLE是蓝牙4.0的核心Profile,BLE前身是NOKIA开 ...

  7. Bluetooth Low Energy 嗅探

    路人甲 · 2015/10/16 10:52 0x00 前言 如果你打开这篇文章时期望看到一些新的东西,那么很抱歉这篇文章不是你在找的那篇文章.因为严格的来说这只是一篇整理文.里面没有任何我的发现,也 ...

  8. android开发之Intent.setFlags()_让Android点击通知栏信息后返回正在运行的程序

    android开发之Intent.setFlags()_让Android点击通知栏信息后返回正在运行的程序   在应用里使用了后台服务,并且在通知栏推送了消息,希望点击这个消息回到activity, ...

  9. Android开发之TextView高级应用

    Android开发之TextView高级应用 我们平时使用TextView往往让它作为一个显示文字的容器,但TextView的功能并不局限于此.以下就和大家分享一下TextView的一些使用技巧. A ...

最新文章

  1. 基于角色的权限管理数据库设计(RBAC)
  2. java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory 解决方案
  3. 用python前端html后端django_浅谈Django前端后端值传递问题
  4. 操作系统 第五章 IO管理
  5. python学来干什么-学 Python 都用来干嘛的?
  6. kali 创建php可执行文件_Kali安装wordpress
  7. Ubuntu下Postfix邮件服务器安装及基本的设置
  8. 地老天荒只是一个华丽的传说
  9. Atitit 函数式编程与命令行语言的区别与优缺点 目录 1. 常见的函数式语言 2 1.1. 命令行 bat 2 1.2. Sql h5 css 正则表达式 2 1.3. 工作流语言 anno注
  10. 【JXTA技术与应用发展】
  11. 设置cpolar远程访问本地网页
  12. Sqlmap免Python版启动器的小修改(根据学习进度逐步更新)
  13. filco蓝牙不好用_filco minila air的蓝牙连接稳定吗?
  14. 912计算机专业综合,西安交通大学2018年计算机考研814、912考试大纲
  15. 解决UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xca in position 0: invalid continuation byte
  16. git gitgitgitgitgit
  17. 什么是软件可靠性测试?
  18. 如何安装和使用vicuna
  19. 罚函数 c语言,神题求解............
  20. 相对定位中整周模糊度确定方法

热门文章

  1. zipline中扩展上交所交易日历SHStockCalendar
  2. 2019春招三七互娱Java面经(已拿到offer)
  3. 【※iPad到底有些什么用※lpxt】
  4. itertools库总结
  5. 电脑主板没有无线网卡怎么上网?怎么通过usb共享网络?
  6. POI——动态修改Excel模板下拉框
  7. 《C++ Primer Plus》(第6版)第14章编程练习
  8. 数据库索引相关(主键索引和非主键索引区别)
  9. 阿里云ACE高级认证考试试卷内容范围(云计算架构师)
  10. 关于QProcess的使用问题解释