在安卓上进行BLE开发时,就不必像理解BLE协议栈那样复杂了。因为安卓的BLE包为我们提供了十分丰富的API、各类常量、各类连接通信情况下的回调API等。

具体流程

一、声明权限

二、获取Adapter适配器

三、开启蓝牙

四、BLE扫描与停止

五、连接设备

六、枚举特征值及其属性

七、利用特征值通讯

八、关闭蓝牙


一、声明权限

在AndroidManifest.xml文件中声明应用需要的特性及权限。

<!-- 声明App使用条件为支持BLE -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<!-- 声明蓝牙权限 -->
<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"/>

二、获取Adapter适配器

final BluetoothManager mBluetoothManager =(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();

三、开启蓝牙

if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(intent, BLE_ENABLE);
}

四、BLE扫描与停止

private boolean mScanning;//是否正在搜索
private Handler mHandler = new Handler();
// 预设15秒扫描时间
private static final int SCAN_PERIOD = 15000;private void scanLeDevice(final boolean enable) {if (enable) {// 控制BLE扫描时间mHandler.postDelayed(new Runnable() {@Overridepublic void run() {mBluetoothAdapter.stopLeScan(mLeScanCallback);}}, SCAN_PERIOD);mScanning = true;// 开始扫描mBluetoothAdapter.startLeScan(mLeScanCallback);} else {mScanning = false;// 停止扫描mBluetoothAdapter.stopLeScan(mLeScanCallback);}
}

在BLE扫描回调函数中保存设备对应的BlueToothDevice对象,rssi信号强度等。

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {// 保存device及相关信息,也可以通知UI线程显示信息}};

五、连接设备

使用扫描结果中保存的BluetoothDevice对象调用connectGatt进行通讯。

BluetoothGatt mBluetoothGatt;
// 参数一:context上下文
// 参数二:是否自动重连
// 参数三: 连接回调
mBluetoothGatt = mBluetoothDevice.connectGatt(context, false, mGattCallback);

连接回调函数实现如下,开发时在此处处理各类可能遇到的情况。

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {// 连接状态改变的回调@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {// 具体处理见后文第八项};// 发现服务回调@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {// 具体处理见后文第六项};@Overridepublic void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {// 由mBluetoothGatt.readRemoteRssi()调用得到,可不停刷新rssi信号强度Log.e(TAG, "信号强度RSSI:" + rssi);}// 写描述信息回调@Overridepublic void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptordescriptor, int status) {};// 写操作回调@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {Log.e(TAG, "写入成功:" + characteristic.getValue());}};// 读操作回调@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {Log.e(TAG, "读取成功:" + characteristic.getValue());}}// 数据改变回调(接收BLE设备发送的数据)@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {};};
}

六、枚举特征值及其属性

@Override
// 发现服务回调,即调用了mBluetoothGatt.discoverServices()执行的回调
public void onServicesDiscovered(BluetoothGatt gatt, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {// 获取ServiceList<BluetoothGattService> mGattServices = gatt.getServices();// 获取Service的Characteristicsfor (BluetoothGattService gattService : mGattServices) {List<BluetoothGattCharacteristic> mGattCharacteristics =     gattService.getCharacteristics();for (BluetoothGattCharacteristic gattCharacteristic :mGattCharacteristics) {int charaProp = gattCharacteristic.getProperties();// 所有Characteristics按属性分类if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {Log.e(TAG, "gattCharacteristic的UUID为:" +             gattCharacteristic.getUuid());Log.e(TAG, "gattCharacteristic的属性为:可读");readUuids.add(gattCharacteristic.getUuid());}if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {Log.e(TAG, "gattCharacteristic的UUID为:" + gattCharacteristic.getUuid());Log.e(TAG, "gattCharacteristic的属性为:可写");writeUuids.add(gattCharacteristic.getUuid());}if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {Log.e(TAG, "gattCharacteristic的UUID为:" + gattCharacteristic.getUuid() + gattCharacteristic);Log.e(TAG, "gattCharacteristic的属性为:具备通知属性");notifyUuids.add(gattCharacteristic.getUuid());}}}} else {Log.e(TAG, "onServicesDiscovered 失败,status:" + status);}
}

七、利用特征值通讯

1、写数据

public void writeChara(byte) {BluetoothGattCharacteristic mGattCharacteristic =             mBluetoothGatt.getCharacteristic(writeUuid);mGattCharacteristic.setValue(sendValue);mBluetoothGatt.writeCharacteristic(mGattCharacteristic);
}

2、读数据

public void readChara() {// 读取数据BluetoothGattCharacteristic mGattCharacteristic =         mBluetoothGatt.getCharacteristic(readUuid);mBluetoothGatt.readCharacteristic(mGattCharacteristic);
}

3、监听通知属性的数据

mBluetoothGatt.setCharacteristicNotification(mGattCharacteristic, enabled);
BluetoothGattDescriptor mGattDescriptor = mGattCharacteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
mGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(mGattDescriptor);

八、关闭蓝牙

合理的关闭步骤为,先调用BluetoothGatt#disconnect进行断开连接,此时会在BluetoothGattCallback#onConnectionStateChange接收到断开成功的回调,然后在回调中调用BluetoothGatt#close释放相关资源。

// 首先执行该disconnect操作,然后等待回调通知
mBluetoothGatt.disconnect();
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {if (newState != BluetoothGatt.GATT_SUCCESS) {// 连接失败直接在此处理即可,因此时调用disconnect无法进入下面条件Log.e(TAG, "连接失败, status:" + status);gatt.close();return;}if (newState == BluetoothGatt.STATE_DISCONNECTED) {// 连接断开Log.e(TAG, "连接断开");mBluetoothGatt.close();} else if (newState == BluetoothProfile.STATE_CONNECTED) {// 连接成功后启动服务发现Log.e(TAG, "连接成功");mBluetoothGatt.discoverServices();}
};

安卓BLE开发教程(二) BLE开发流程相关推荐

  1. ODOO13 开发教程二 Windows开发环境搭建

    这篇文章写给刚接触odoo开发的朋友,在这篇文章中,主要介绍Windows下,odoo开发环境的搭建方法. 本文的推荐开发环境搭建使用 PyCharm.Python3.7.odoo13社区版 Wind ...

  2. MIP开发教程(二) 使用MIP-CLI工具调试MIP网页

    初始化 MIP 配置 新建一个 MIP 网页 编写 MIP 网页代码 校验 MIP 网页 调试 MIP 网页 1. 初始化 MIP 配置 首先在html目录下进行初始化 MIP 配置: $ mip i ...

  3. pythoncad二次开发视频_revit二次开发|bim软件二次开发|revit二次开发教程|Revit二次开发技术文档...

    二次开发 revit二次开发|bim软件二次开发|revit二次开发教程|Revit二次开发技术文档2019-07-08赞( 0 ) 记录一下CAD二次开发的一些简单实例. 1.helloworld ...

  4. 来自damon的zencart二次开发教程-3.1开发自己的zencart模板

    转载自:http://www.yunxiu.org/blog/ 今天在网上FQ看到一篇老外写的,关于制作zencart模板的文章.<Creating a new Zen Cart Templat ...

  5. 乐鑫Esp32学习之旅 安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,拍照图片通过有线串口传到上位机PC端。(附带设备端+PC端源码)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 系列一:ESP32系列模组基础学习系列笔记 1. 爬坑学习新旅程,虚 ...

  6. 乐鑫Esp32学习之旅28 安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,实现MQTT远程拍照传输到私有服务器。(附带源码)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...

  7. 乐鑫Esp32学习之旅29 安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,实现本地视频流监控。(附带源码)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...

  8. 视频教程-红孩儿网狐Cocos经典棋牌开发教程-手游开发

    红孩儿网狐Cocos经典棋牌开发教程 中国早期游戏程序员,2003年起从事游戏程序开发,负责开发过多款游戏项目,曾担任大型端游<无限世界>自研引擎技术负责人,2012年起关注Cocos引擎 ...

  9. mapgis java二次开发_MapGIS开发平台二次开发.docx

    MapGIS开发平台二次开发解决方案 2012年8月武汉 前言 MapGIS IGSS地理空间信息共享服务平台解决方案产品,在超大规模.虚拟化的硬件架构基础上,提供以微内核群(MicroCore)为支 ...

  10. 微信开发sdk_二次开发微信API更新日志

    微信开发sdk_二次开发微信API更新日志 微信开发sdk_二次开发微信API更新日志 2.6.35 清粉优化 小于1k的图片发送失败的问题 联系人资料新增电话号码和描述 发布2.6.31->2 ...

最新文章

  1. C语言获取当前工作路径
  2. spring boot中@ResponseBody等注解的作用与区别
  3. 通用客户端表单验证函数修正版
  4. springbatch的writer、processor、reader复杂太难用?使用tasklet更方便!
  5. 解决layui数据表格table固定列行高不一致的情况
  6. 2018-06-25-Python全栈开发day21-part2-time模块介绍
  7. python_day7 绑定方法与非绑定方法
  8. Java 包装类 自动装箱和拆箱
  9. 【缅怀妈妈系列诗歌】之八:妈妈,我不会忘记
  10. cf B. Internet Address
  11. 总结-eclipse
  12. 【译】BMP格式与JPG格式之间的区别
  13. JAVA项目之图书管理系统
  14. 天堂2私服架设技术教程
  15. PyTorch-1.10(十三)--torch.optim基本用法
  16. maven 打jar包:mvn clean package
  17. 修正半透明头发的渲染异常
  18. 小程序 input自动聚焦唤起键盘
  19. 龙芯2h芯片不能进入pmon_2HSOCReleaseNotes - 龙芯开源社区
  20. 关于RHCE考试一些事情

热门文章

  1. IBM副总裁自述的数据中心简化经验
  2. php表格tr,jQuery+ajax实现动态添加表格tr td功能示例
  3. java语言静态分析工具_PMD 6.16.0 发布,跨语言静态代码自动分析工具
  4. 白裤子变粉裤子怎么办_使用裤子构建构建数据科学的monorepo
  5. 49. 字母异位词分组
  6. leetcode 474. 一和零(dp)
  7. Linux 网络相关命令
  8. javascript编程题_如何开始使用JavaScript进行竞争性编程
  9. web开发入门_Web开发人员和设计师的自由职业入门
  10. 业精于勤荒于嬉---Go的GORM查询