Android在工业物联网或手持机终端上的应用开发中经常会遇到蓝牙相关功能需求,蓝牙4.0之后开始分为低功耗蓝牙(BLE)和经典蓝牙。这里简单介绍一下低功耗蓝牙的基本开发流程。

一、权限处理

应用中需要使用蓝牙功能,必须声明BLUETOOTH蓝牙权限。AndroidManifest文件中进行如下声明:

<!-- 使用蓝牙的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 扫描蓝牙设备或者操作蓝牙设置 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

蓝牙通信经常与位置相关联,还必须声明定位相关权限。(注意:需要做动态权限处理)

<!-- 模糊定位权限,仅作用于6.0+ -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 精准定位权限,仅作用于6.0+ -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

二、初始化蓝牙

获取本地蓝牙适配器,同时需要判断本地设备是否支持BLE。

//设置为全局变量,方便后续使用。
private BluetoothAdapter mBtAdapter;//1、获取本地蓝牙适配器。
mBtAdapter = BluetoothAdapter.getDefaultAdapter();//2、判断设备是否支持蓝牙。
if (mBtAdapter == null) {Log.i(TAG, "openBluetooth: 该设备不支持蓝牙");
} else {//3、启用蓝牙。if (!mBtAdapter.isEnabled()) {mBtAdapter.enable(); //打开蓝牙}
}

三、扫描蓝牙设备

使用startLeScan()方法查找,并在BluetoothAdapter.LeScanCallback回调中获得扫描结果。(注意:扫描这个过程非常耗电,找到所需设备,立即停止扫描)

//扫描蓝牙。
mBtAdapter.startLeScan(mBtLeScanCallback); //扫描结果回调。
private final BluetoothAdapter.LeScanCallback mBtLeScanCallback = new BluetoothAdapter.LeScanCallback() {@SuppressLint("MissingPermission")@Overridepublic void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {//针对扫描结果的一些操作。device.getName(); //获取蓝牙名称device.getAddress(); //获取蓝牙MAC地址}
};//停止扫描。
mBtAdapter.stopLeScan(mBtLeScanCallback);

四、连接蓝牙

扫描结果回调中获取的蓝牙设备(device)调用connectGatt()连接方法连接蓝牙。 connectGatt(Context context, boolean autoConnect,BluetoothGattCallback callback)连接方法参数解释:context上下文对象,autoConnect布尔值,是否在可用时自动连接,BluetoothGattCallback蓝牙连接回调引用。

//将BluetoothGatt设置为全局变量,方便后续调用。
private BluetoothGatt mBtGatt;//连接蓝牙。
mBtGatt = device.connectGatt(context, false, mBtGattCallback);

五、建立通信

连接成功后建立设备间通信主要是依靠BluetoothGattCallback回调方法,其中UUID的配置最为重要。 UUID相关信息在开发时通常蓝牙设备厂商会提供,但是在未知的情况下就必须去自动配置服务、写入、监听等UUID信息。 (UUID相关概念可自行搜索,理解更深入)

//服务、写入、监听UUID配置相关全局变量。
private BluetoothGattService mBtGattService;
private BluetoothGattCharacteristic mWriteBtGattCharacteristic;
private BluetoothGattCharacteristic mNotifyBtGattCharacteristic;//UUID全局变量。
private UUID UUID_WRITE_SERVICES;
private UUID UUID_WRITE_CHARA;
private UUID UUID_NOTIFY_CHARA;//连接到GATT服务器,建立通信。
private final BluetoothGattCallback mBtGattCallback = new BluetoothGattCallback() {//成功连接到设备将回调此方法。@SuppressLint("MissingPermission")@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {//进行蓝牙连接状态判断。if (newState == BluetoothProfile.STATE_CONNECTED) {gatt.discoverServices(); //开始发现设备的服务Log.i(TAG, "onConnectionStateChange: 连接成功");} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {Log.i(TAG, "onConnectionStateChange: 连接失败");}}//发现服务,一般在设备连接成功后调用,扫描到设备服务后回调此方法。@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {//判断回调服务是否成功。if (status == BluetoothGatt.GATT_SUCCESS) {Log.i(TAG, "onServicesDiscovered: 回调服务连接成功");} else {Log.i(TAG, "onServicesDiscovered: 回调服务连接失败" + status);}//配置UUID。(整个BLE开发中最重要的地方,关系着通信是否成功)//创建集合,获取服务UUID。List<BluetoothGattService> gattServices = gatt.getServices();//遍历服务UUID集合。for (BluetoothGattService service : gattServices) {//创建集合,获取特征UUID。List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();//遍历特征UUID。for (BluetoothGattCharacteristic characteristic : characteristics) {//查找并识别出监听、写入等特征UUID和对应的服务UUID。int charaProp = characteristic.getProperties();if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {UUID_WRITE_CHARA = characteristic.getUuid(); //获取写入特征UUIDUUID_WRITE_SERVICES = service.getUuid(); //获取写入服务UUID}if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {UUID_NOTIFY_CHARA = characteristic.getUuid(); //获取监听特征UUID}}}//设置服务UUID。mBtGattService = mBtGatt.getService(UUID_WRITE_SERVICES);//设置写入特征UUID。mWriteBtGattCharacteristic = mBtGattService.getCharacteristic(UUID_WRITE_CHARA);//设置监听特征UUID。mNotifyBtGattCharacteristic = mBtGattService.getCharacteristic(UUID_NOTIFY_CHARA);//开启监听。gatt.setCharacteristicNotification(mNotifyBtGattCharacteristic, true);}//开启监听,即建立与设备的通信的首发数据通道,BLE开发中只有当上位机成功开启监听后才能与下位机收发数据.开启监听成功则会回调此方法。@Overridepublic void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {super.onDescriptorWrite(gatt, descriptor, status);//判断监听开启状态。if (status == BluetoothGatt.GATT_SUCCESS) {Log.i(TAG, "onDescriptorWrite: 开启监听成功,可以向设备写入命令了");}}//写入数据,若写入指令成功则回调此方法,说明将数据已经发送给下位机。@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicWrite(gatt, characteristic, status);//判断数据发送状态。if (status == BluetoothGatt.GATT_SUCCESS) {Log.i(TAG, "onCharacteristicWrite: 数据发送成功");}}//接收数据,若发送的数据符合通信协议,则下位机会向上位机回复相应的数据。发送的数据通过回调此方法获取。@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {//value为设备发送的数据,根据数据协议进行解析。byte[] value = characteristic.getValue();}
};

六、发送数据

通过BluetoothGattCharacteristic(GATT特征)配置发送的数据和写入UUID,再通过BluetoothGatt(GATT功能)去实现通信。 蓝牙间的通信通常采用16进制,所以写入写出的数据需要进行进制的转换。

//发送数据。
//设置写入,setValue(发送的数据)。
mWriteBtGattCharacteristic.setValue(data);
//设置写入特征UUID。
mWriteBtGattCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
//向设备写入指令。
mBtGatt.writeCharacteristic(mWriteBtGattCharacteristic); //进制转换工具方法。
//将字节数组byte[]转换为16进制字符串。
private String arrayToHex(byte[] arr) {if (arr != null) {StringBuilder sb = new StringBuilder();for (byte b : arr)sb.append(String.format("%02x ", b));return sb.toString().trim();}return "";
}//字符串转字节数组byte[]。
private static byte[] stringToBytes(String str) {if (str == null || str.trim().equals("")) {return new byte[0];}byte[] bytes = new byte[str.length() / 2];for (int i = 0; i < str.length() / 2; i++) {String subStr = str.substring(i * 2, i * 2 + 2);bytes[i] = (byte) Integer.parseInt(subStr, 16);}return bytes;
}

七、断开蓝牙连接

断开蓝牙连接时容易出现空引用异常, 最好是在建立通信判断回调服务成功处增加一个判断的标志位, 然后再通过判断回调服务是否成功来决定断开蓝牙连接。

//断开连接。
mBtGatt.disconnect(); 

总结

以上对BLE低功耗蓝牙的开发进行了简单的介绍,对于其使用仅是流于表面,此示例主要是为抛砖引玉。如有纰漏,请您给出建议,在此表示感谢!

基于BLE低功耗蓝牙实现与蓝牙设备的连接和数据通信相关推荐

  1. Android BLE低功耗蓝牙重启手机后自动连接失败问题

    最近在做安卓开发,用到蓝牙模块相关功能.主要功能是使用手机连上低功耗蓝牙设备,比如蓝牙手环.关于如何蓝牙连接在这里就不讲述了,网上搜索一大堆相关教程.想要来这里看蓝牙连接方式的朋友可能要大失所望了. ...

  2. 基于uni-app的BLE低功耗蓝牙测试工具

    基于uni-app的BLE低功耗蓝牙测试工具 前言 开发环境:HBuilder X2.8.11,运行环境:微信小程序 本项目是从网上收集他人的源代码,经过测试.修改后的版本,在微信小程序上表现比较稳定 ...

  3. 安卓基于BLE的蓝牙开发入门

    BLE蓝牙开发简单入门 BLE背景介绍 引言 BLE简介 Gatt协议以及必备知识 蓝牙开发涉及的API介绍 BLE实战准备 真机调试 权限准备 写两个简单的页面 扫描设备主界面 扫描设备信息界面 实 ...

  4. BT传统蓝牙和BLE低功耗蓝牙的区别

    蓝牙3.0及以下为传统蓝牙.   蓝牙4.0以上标准包含两个蓝牙标准,是一个双模的标准,它包含经典蓝牙部分(Classic Bluetooth)和低功耗蓝牙部分(Bluetooth Low Energ ...

  5. Android BLE低功耗蓝牙开发

    啦啦啦在上一个项目中有用到BLE低功耗蓝牙开发,当时baidu google了很多资料,但大多数都是千篇一律,英文文档我这种渣渣又看不懂...总之刚开始查的很痛苦.所以要把自己的踩坑之路写下来记录下, ...

  6. ble 低功耗蓝牙开发学习 嵌入式交流学习

    ble 低功耗蓝牙开发学习 嵌入式交流学习 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 这篇文章教你学会低功耗蓝牙开发,从0到深入,适合自学的学生.初级工程师 前言 随着疫情爆发 ...

  7. c# 低功耗蓝牙_Android ble低功耗蓝牙开发-客户端

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

  8. Android BLE(低功耗蓝牙)技术总结

    文章目录 前言 一.蓝牙介绍 1.什么是蓝牙? 2.蓝牙版本介绍 二.低功耗蓝牙(BLE) 1.BLE介绍 2.经典蓝牙(Classic Bluetooth)与低功耗蓝牙(BLE)的区别 3.低功耗蓝 ...

  9. android studio蓝牙低功耗,arduino ESP32 AndroidStudio BLE低功耗蓝牙 物联网

    arduino ESP32 AndroidStudio BLE低功耗蓝牙 物联网 nodered开发: esp32采用的蓝牙于普通的蓝牙不同,是低功耗蓝牙,手机用一般的蓝牙代码是连不上的.在本文中,不 ...

最新文章

  1. docker-compose up volumes 调用外部文件,权限问题 cannot open directory xxxxx .: Permission denied
  2. c语言存储结构体,c语言结构体的保存和导入
  3. VTK:高亮选择动画用法实战
  4. jzoj3518-进化序列(evolve)【位运算】
  5. Windows驱动—Windows应用程序和Windows驱动通信编程
  6. 基于layui的框架模版,采用模块化设计,接口分离,组件化思想
  7. 报表软件公司悬赏 BUG,100块钱1个的真实用意
  8. Git之路——配置SSH免密码登录
  9. 性能调优第一篇-SQL格式化
  10. 佳能MP145/140打印机 出现错误代码“E5”怎么处理
  11. MATLAB生成(对角线上元素相同的)三对角矩阵的实例
  12. opencv鱼眼相机模型详解
  13. flex: 1到底是什么意思?
  14. HTML实现banner图切换
  15. 使用计算机辐射最大,流言终结者:我们身边的辐射有多大?
  16. L415 Fat Is Not the Problem—Fat Stigma Is
  17. html5 iumpwzo cn,世界杯最神奇5分钟!踢默契球的队赢了杀人屠夫干
  18. MinIO高性能对象存储
  19. android 播放网络电视,HDP直播tv版 V2.0.5 for android (网络电视)
  20. CAS原理分析及ABA问题详解

热门文章

  1. 计算机网络原理 王志文,王志文-西安交通大学计算机科学与技术学院
  2. chrome断网小游戏实现
  3. 第五章 数据仓库实例
  4. 微信营销十三(抖音案例)
  5. (展讯 /RK3066)Android:ADB详解 (2013-01-05 13:36:15)
  6. 你的云桌面和阿里的云主机有什么区别?
  7. Java使用iText5.0生成PDF文件
  8. 一文彻底掌握用户态协议栈,一看就懂的
  9. 大数据-玩转数据-Hive应用小结
  10. 电工基础知识 接触器