Android使用低功耗蓝牙BLE进行简单通信
一.蓝牙硬件操作
Android操作蓝牙需要申请蓝牙权限、定位权限,部分手机还必须要打开GPS才能使用。
蓝牙的打开、关闭、搜索,这部分内容只是简单的调用API就能实现,这里不做说明。
但是从连接开始就要了解一些低功耗蓝牙的知识,这些是在Android以外的知识,现在介绍最基础的使用。
1.连接
public void connect(Context context, BluetoothDevice device)mBluetoothGatt = device.connectGatt(context, false, mBluetoothGattCallback);}
这里着重说明BluetoothGatt和BluetoothGattCallback这两个东西,Gatt是一种协议一种规范,低功耗蓝牙就是建立在这个协议之上的通信方式。
二.在连接之后,要把蓝牙看作一个什么样的对象
调用完连接方法之后,就把蓝牙看作上面这棵树,最重要的就是characteristic节点,characteristic(特征值)是手机与蓝牙设备交互信息的关键。
现在要通过BluetoothGatt这个对象来操纵蓝牙,而通过BluetoothGattCallback这个回调来接收蓝牙的消息和状态变化。下面按照顺序说明,连接后应该做的操作
mBluetoothGattCallback = new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(final BluetoothGatt gatt, final int status,final int newState) {if (newState == BluetoothGatt.STATE_CONNECTED) {gatt.discoverServices();}else{...}}@Overridepublic void onServicesDiscovered(final BluetoothGatt gatt, final int status) {if (status == BluetoothGatt.GATT_SUCCESS){//todo 可以去找特征值了}}@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,final BluetoothGattCharacteristic characteristic, final int status) {}@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,final BluetoothGattCharacteristic characteristic, final int status) {}@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,final BluetoothGattCharacteristic characteristic) {//todo 按照协议解析数据,characteristic.getValue()}};
1.设备连接状态的变化
在onConnectionStateChange中等待接收连接状态的改变,这里能够接收,连接成功、连接失败、断开等状态。
2.在判断到连接成功之后,发现服务
gatt.discoverServices();
在调用发现服务之后会,这个回调会得到消息onServicesDiscovered,当服务发现之后,就代表我们可以去操作我们需要的service和characteristic了。
3.如何找到要用的characteristic
UUID(通用唯一识别码),蓝牙中用到了这个概念,每一个service,characteristic都有唯一的UUID。我们需要的UUID应该由蓝牙硬件一方提供说明文档,告知做app的开发人员,不同的characteristic可能对应不同的功能。
这是两个很常用的UUID
String UUID_service ="0000FFE0-0000-1000-8000-00805F9B34FB";String UUID_characteristic ="0000FFE1-0000-1000-8000-00805F9B34FB";UUID serviceUUID = UUID.fromString(UUID_service);UUID characteristicUUID = UUID.fromString(UUID_characteristic);service =bluetoothGatt.getService(serviceUUID);characteristic =service.getCharacteristic(characteristicUUID);
至此,我们终于拿到了最关键的这个对象,我们可以主动去读一下这个特征值瞧瞧
bluetoothGatt.readCharacteristic(characteristic)
结果会在onCharacteristicRead中得到
三.如何使用特征值与蓝牙设备互发消息
1.向蓝牙设备发送消息
蓝牙与手机的交流都是通过字节数组,当我们修改蓝牙设备特征值,蓝牙就收到了我们发送的这串数据,
characteristic.setValue(byte[] data);bluetoothGatt.writeCharacteristic(characteristic);
然后就会在回调onCharacteristicWrite中得到我们刚发送的消息的结果,
@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,final BluetoothGattCharacteristic characteristic, final int status) {if (status == BluetoothGatt.GATT_SUCCESS){}}
这就证明发送成功了。
2.接收蓝牙设备发送的消息
手机端通过监听特征值的变化,来接收消息,如果蓝牙设备改变了一个特征值的值,被我们监听到了,这就相当于,蓝牙设备向app发送了字节数组。
bluetoothGatt.setCharacteristicNotification(characteristic, true);@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,final BluetoothGattCharacteristic characteristic) {//todo 按照协议解析数据,characteristic.getValue(),注意:每次传输大小有限制,如果过长,这个回调就会执行多次,要自己把每次的到的数据拼接成一个完整的数据帧}
每当特征值被蓝牙修改,我们就会在onCharacteristicChanged接收到修改的信息,这就是蓝牙发送消息给app。
3.解析数据
数据的解析,要根据协议来执行,这个协议一般由app的开发和蓝牙硬件的开发人员一起制定。
举例说明:
假设这样制定一个协议,将接收到的字节数组转成十六进制,每个字节的范围就是00-FF
规定每一个完整的数据帧是以BB开头,以7E结尾,数组中第二个位置的数字代表有用数据体的长度。app可以根据这个规定拼接完整数据帧,以及排除一些多余的或者错误的字节
BB 02 A7 64 7E
这个数据帧中代表特别含义的数据体就是 A7 64
其中第一位代表功能标识,其中A7可能就代表这个消息是电池的电量,64表示剩余电量是100%
四.DEMO
private final String TAG = "BLE_TEST"; private String UUID_service = "0000FFE0-0000-1000-8000-00805F9B34FB"; private String UUID_characteristic ="0000FFE1-0000-1000-8000-00805F9B34FB"; private BluetoothGatt mBluetoothGatt; private BluetoothGattCharacteristic mCharacteristic; private BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() { @Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {if (newState == BluetoothGatt.STATE_CONNECTED) {gatt.discoverServices();//四.连接蓝牙成功之后,发现服务}super.onConnectionStateChange(gatt, status, newState);}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {if (status == BluetoothGatt.GATT_SUCCESS){ //五.发现服务成功之后,去找需要的特征值UUID serviceUUID = UUID.fromString(UUID_service);UUID characteristicUUID = UUID.fromString(UUID_characteristic);BluetoothGattService service = mBluetoothGatt.getService(serviceUUID);mCharacteristic = service.getCharacteristic(characteristicUUID); //找到特征值之后进行收发操作,设置接收特征值通知mBluetoothGatt.setCharacteristicNotification(mCharacteristic, true);send(); //发个消息给蓝牙}super.onServicesDiscovered(gatt, status);}@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicRead(gatt, characteristic, status);Log.i(TAG,"onCharacteristicRead" + ByteHelper.BytesToHexString(characteristic.getValue()));}@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicWrite(gatt, characteristic, status); Log.i(TAG,"onCharacteristicWrite:"+ByteHelper.BytesToHexString(characteristic.getValue()));}@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);Log.i(TAG,"onCharacteristicChanged"+ByteHelper.BytesToHexString(characteristic.getValue()));}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if (VERSION.SDK_INT >= VERSION_CODES.M) {int checkResult = ContextCompat.checkSelfPermission(this, permission.ACCESS_FINE_LOCATION);if (checkResult== PackageManager.PERMISSION_DENIED){ ActivityCompat.requestPermissions(this, new String[]{permission.ACCESS_FINE_LOCATION}, 1);}}initBluetooth();}private void initBluetooth() {BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();bluetoothAdapter.enable();//一.打开蓝牙final BluetoothLeScanner bluetoothLeScanner =bluetoothAdapter.getBluetoothLeScanner();bluetoothLeScanner.startScan(new ScanCallback() {//二.搜索蓝牙@Overridepublic void onScanResult(int callbackType, ScanResult result) {super.onScanResult(callbackType, result);if ("我的蓝牙".equals(result.getDevice().getName())){//三.连接蓝牙mBluetoothGatt = result.getDevice().connectGatt(getApplicationContext(), false, mBluetoothGattCallback);bluetoothLeScanner.stopScan(this);}}});}private void send() {byte[] mes = new byte[4];mes[0] = (byte) 0xAB;mes[1] = (byte) 0xA8;mes[2] = (byte) 0x58;mes[3] = (byte) 0xFE;mCharacteristic.setValue(mes);mBluetoothGatt.writeCharacteristic(mCharacteristic);}
五.总结
这些只是低功耗蓝牙操作的最基本使用,而且只是站在app开发者的角度进行描述。
蓝牙开发还有其他很多可扩展的细节,如:
解析广播包
将手机作为外围设备
单次传输突破20字节限制
通知与指示器的区别
等等等等。。。
Android使用低功耗蓝牙BLE进行简单通信相关推荐
- 泰凌微ble mesh蓝牙模组天猫精灵学习之旅④如何在Android开发低功耗蓝牙ble控制 TB-02 模块,代码工程全部开源!(附带Demo)
本<泰凌微ble mesh蓝牙模组天猫精灵学习之旅>系列博客学习由半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1.小白也痴迷,如 ...
- Android低功耗蓝牙(BLE)开发(二)
在上一篇文章Android低功耗蓝牙(BLE)开发(一)中我们了解了BLE的相关概念,这里我们来实际用代码演示安卓进行BLE连接和通讯的功能.本文代码基于Android5.0以上(API 21) 1. ...
- (Android)低功耗蓝牙(BLE)开发一文全(详)解
前言:如果你是刚开始接触android关于低功耗(ble)蓝牙的开发,还是应该花点是时间了解一下BLE协议,因为哪怕你把蓝牙ble协议梳理个一知半解,那么开发就只剩下调用API了... 为了快速编辑, ...
- Android低功耗蓝牙BLE
低功耗蓝牙BLE与传统的蓝牙相比最大的优势是功耗降低90%,同时传输距离增大(超过100米).安全和稳定性提高(支持AES加密和CRC验证),允许Android应用程序与具有更严格电源要求的BLE设备 ...
- PyQt5之QtBluetooth模块:低功耗蓝牙BLE通信
PyQt5之QtBluetooth模块:低功耗蓝牙BLE通信 最近使用PyQt5开发PC端工具,正巧手上有一个富芮坤的低功耗蓝牙,于是想在PC端试试与之通信,不过发现使用PyQt5开发低功耗蓝牙的教程 ...
- 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发详解
转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50909410 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发详解 ...
- java 协议栈_深入浅出讲解低功耗蓝牙(BLE)协议栈
详解BLE连接建立过程 https://www.cnblogs.com/iini/p/8972635.html 详解BLE 空中包格式-兼BLE Link layer协议解析 https://www. ...
- 蓝牙:深入浅出低功耗蓝牙(BLE)协议栈
深入浅出低功耗蓝牙(BLE)协议栈 BLE协议栈为什么要分层?怎么理解BLE"连接"?如果BLE协议只有ATT层没有GATT层会发生什么? 协议栈框架 一般而言,我们把某个协议的实 ...
- 低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端
低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端 Android对外模模式(peripheral)的支持 从Android5.0开始才支持 关键术语和概念 以下是关键BLE术语和 ...
最新文章
- sql左连接排序取第一个_详解kettle工具记录集连接功能及实验测试
- awk小技巧之执行shell命令
- 老鸟程序员才知道的40个小技巧
- 金蝶kis云触发器解决审核和反审核的问题
- 还是畅通工程 最小生成树
- python urlopen_Python爬虫教程-02-使用urlopen
- 测试线程池(Java)
- 分治法 —— 快速排序和归并排序(自底向上和自顶向下)
- 半监督学习入门基础(一)
- java基础27 单例集合Collection及其常用方法
- SurfaceView 之满屏的代码雨效果
- 三级网络技术无纸化模拟软件 (未来)教育
- esp8266教程:网络基础知识
- WIN7电脑语言栏不见了---解决方案
- 什么是自然语言处理(NLP)?
- 常用邮箱的 IMAP/POP3/SMTP 设置
- 微信公众号新变动!你都发现了吗?
- 无线笔记本怎么连接服务器打印机驱动,笔记本怎么连接无线打印机驱动程序
- 【并发编程的艺术】并发机制原理
- 根据PyTorch学习CONV1D