如果各位觉得有用,转载+个出处。

现如今安卓的低功耗蓝牙应用十分普遍了,智能手环、手表遍地都是,基本都是利用BLE通信来交互数据。BLE基本在安卓、IOS两大终端设备上都有很好支持,所以有很好发展前景。

现市面上各种手环、手表的智能设备中基本都充当"从设备"这样的角色,基本由智能设备完成蓝牙广播,由手机进行连接,然后交互数据。

根据上述方式的应用在安卓4.3、IOS 7.0的版本上就得到了支持,应用也比较广泛,园里应该有很多相关实现,大家可以自己找找,如果不愿意找,抽空再写一篇。

今天主要是为了说在安卓5.0时升级了广播相关API,园里也有一些说明,但之所以还写这篇是因为数据交换的提及很少。

既然将手机要做广播了,那么实质手机就变成手环、手表的角色,一个从设备了。

如果你愿意,可以拿另一台手机做个主设备,这样他们就可以交流了。

好了,我们进入代码正题吧...

首先应用权限设置。在AndroidManifest.xml中还是要加入BLE控制权限,不然异常一定与你为伍。

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

接着我们上套路了,判断手机是否支持BLE以及是否支持BLE从设备。

   if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
showToast("该设备不支持蓝牙低功耗通讯");
this.finish();
return;
} bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); if (bluetoothAdapter == null) {
showToast("该设备不支持蓝牙低功耗通讯");
this.finish();
return;
} bluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
if (bluetoothLeAdvertiser == null) {
showToast("该设备不支持蓝牙低功耗从设备通讯");
this.finish();
return;
}

我建议你先拿你调试设备试试,大多数同学走到这里都绝望了。你问我为啥?你试试就知道了。

如果你一脸what???的话,那恭喜你,你的调试设备是被选中的孩子,让我们继续乘风破浪吧。顺便在评论里告诉我下你用啥设备哦。

这时候我们开启广播的旋风吧。

  //广播设置
AdvertiseSettings.Builder settingBuilder = new AdvertiseSettings.Builder();
settingBuilder.setConnectable(true);
settingBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);
settingBuilder.setTimeout(0); //我填过别的,但是不能广播。后来我就坚定的0了
settingBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
AdvertiseSettings settings = settingBuilder.build(); //广播参数
AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
bluetoothAdapter.setName("H8-BlePpl"); //你想叫啥名字,你愿意就好
dataBuilder.setIncludeDeviceName(true);
dataBuilder.setIncludeTxPowerLevel(true); dataBuilder.addServiceUuid(ParcelUuid.fromString(Const.UUID_SERVICE)); //可自定义UUID,看看官方有没有定义哦
AdvertiseData data = dataBuilder.build(); bluetoothLeAdvertiser.startAdvertising(settings, data, advertiseCallback);

然后你的小手机就开始广播了,说大家来连我啊连我啊。别总搜地址,貌似地址动态会变的,还是用名儿吧毕竟你起了啊。

我之前傻傻的查了手机蓝牙MAC地址,后来发现不是广播的那个...

广播回调我干了点新增服务的活儿,不干你拿啥通信来。

  private AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
runOnUiThread(new Runnable() {
@Override
public void run() {
showInfo("1.1 AdvertiseCallback-onStartSuccess");
}
}); bluetoothGattServer = bluetoothManager.openGattServer(getApplicationContext(),
bluetoothGattServerCallback); BluetoothGattService service = new BluetoothGattService(UUID.fromString(Const.UUID_SERVICE),
BluetoothGattService.SERVICE_TYPE_PRIMARY); UUID UUID_CHARREAD = UUID.fromString(Const.UUID_CHARACTERISTIC); //特征值读写设置
BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(UUID_CHARREAD,
BluetoothGattCharacteristic.PROPERTY_WRITE |
BluetoothGattCharacteristic.PROPERTY_READ |
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_WRITE); UUID UUID_DESCRIPTOR = UUID.fromString(Const.UUID_CHARACTERISTIC_CONFIG); BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID_DESCRIPTOR, BluetoothGattCharacteristic.PERMISSION_WRITE);
characteristicWrite.addDescriptor(descriptor);
service.addCharacteristic(characteristicWrite); bluetoothGattServer.addService(service); runOnUiThread(new Runnable() {
@Override
public void run() {
showInfo("1.2. Service Builded ok");
}
}); }};

当你收到广播成功回调后,来吧,特征值啊~~反正要通信呐~~

被你发现了我偷懒读写特征值用了一个,其实你愿意用两个就用两个吧。

我用的NOTIFICATION方式做主设备的读取,你也可用INDICATION方式做。

服务建立完成后,也会收到通知。BLE嘛~~都是异步回调~~我是习惯了!

   private BluetoothGattServerCallback bluetoothGattServerCallback = new BluetoothGattServerCallback() {
@Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service); final String info = service.getUuid().toString();
runOnUiThread(new Runnable() {
@Override
public void run() {
showInfo("1.3 BluetoothGattServerCallback-onServiceAdded " + info);
}
}); } @Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
final String info = device.getAddress() + "|" + status + "->" + newState; runOnUiThread(new Runnable() {
@Override
public void run() {
showInfo("1.4 onConnectionStateChange " + info);
}
});
} @Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic); final String deviceInfo = "Address:" + device.getAddress();
final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + characteristic.getUuid() + "|Value:" +
Util.bytes2HexString(characteristic.getValue()); runOnUiThread(new Runnable() {
@Override
public void run() { showInfo("=============================================");
showInfo("设备信息 " + deviceInfo);
showInfo("数据信息 " + info);
showInfo("=========onCharacteristicReadRequest========="); }
}); bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue()); } @Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic,
preparedWrite, responseNeeded, offset, value); final String deviceInfo = "Name:" + device.getAddress() + "|Address:" + device.getAddress();
final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + characteristic.getUuid() + "|Value:" + Util.bytes2HexString(value); bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
//TODO:你做数据处理 runOnUiThread(new Runnable() {
@Override
public void run() { showInfo("=============================================");
showInfo("设备信息 " + deviceInfo);
showInfo("数据信息 " + info);
showInfo("=========onCharacteristicWriteRequest========="); }
}); } @Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status); final String info = "Address:" + device.getAddress() + "|status:" + status; runOnUiThread(new Runnable() {
@Override
public void run() {
showInfo("onNotificationSent " + info);
}
});
} @Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
final String deviceInfo = "Name:" + device.getAddress() + "|Address:" + device.getAddress();
final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + descriptor.getUuid() + "|Value:" + Util.bytes2HexString(value); runOnUiThread(new Runnable() {
@Override
public void run() { showInfo("=============================================");
showInfo("设备信息 " + deviceInfo);
showInfo("数据信息 " + info);
showInfo("=========onDescriptorWriteRequest========="); }
}); // 告诉连接设备做好了
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
} @Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) { super.onDescriptorReadRequest(device, requestId, offset, descriptor); final String deviceInfo = "Name:" + device.getAddress() + "|Address:" + device.getAddress();
final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + descriptor.getUuid(); runOnUiThread(new Runnable() {
@Override
public void run() { showInfo("=============================================");
showInfo("设备信息 " + deviceInfo);
showInfo("数据信息 " + info);
showInfo("=========onDescriptorReadRequest========="); }
}); // 告诉连接设备做好了
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null); } };

基本上从设备就做完了。

调试的时候你用主设备查服务列表可能查不到你的UUID_SERVICE,但是别慌,你getServcie(UUID_SERVICE)试试,说不定就柳暗花明了。

还有就是我拿的华为Honor 8做的调试机子,其他还有啥型号请各位分享下。姑娘我跪谢啦~~

【原创】Android 5.0 BLE低功耗蓝牙从设备应用的更多相关文章

  1. Android使用BLE(低功耗蓝牙,Bluetooth Low Energy)

    背景 在学习BLE的过程中,积累了一些心得的DEMO,放到Github,形成本文.感兴趣的同学可以下载到源代码. github: https://github.com/vir56k/bluetooth ...

  2. BLE——低功耗蓝牙(Bluetooth Low Energy)

    1.简介 以下蓝牙协议特指低功耗蓝牙协议. 蓝牙协议是由SIG制定并维护的通信协议,蓝牙协议栈是蓝牙协议的具体实现. 各厂商都根据蓝牙协议实现了自己的一套函数库——蓝牙协议栈,所以不同厂商的蓝牙协议栈 ...

  3. BLE低功耗蓝牙关键技术解析与应用

    BLE基础知识 1.传统蓝牙的传输距离几十米到几百米不等,BLE 则规定为 100 米(实际上没有那么远,50米以内比较稳定,和设备发射功率有关) 2.为了实现极低的功耗,BLE 协议设计为:在不必要 ...

  4. 低功耗蓝牙BLE之连接事件、连接参数和更新方法

    转自:http://blog.csdn.net/zzfenglin/article/details/51304084 连接事件 在一个连接当中,主设备会在每个连接事件里向从设备发送数据包.一个连接事件 ...

  5. TI低功耗蓝牙(BLE)介绍

    TI低功耗蓝牙(BLE)介绍 本文档翻译和修改自参考资料:CC2540Bluetooth Low Energy Software Developer’s Guide (Rev. B),部分图片直接引用 ...

  6. TI低功耗蓝牙(BLE)介绍【转】

    转自:http://blog.csdn.net/ooakk/article/details/7302425 TI低功耗蓝牙(BLE)介绍 本文档翻译和修改自参考资料:CC2540Bluetooth L ...

  7. 深入浅出讲解低功耗蓝牙(BLE)协议栈

    详解BLE连接建立过程https://www.cnblogs.com/iini/p/8972635.html 详解BLE 空中包格式—兼BLE Link layer协议解析https://www.cn ...

  8. Android 6.0 新功能及主要 API 变更

    运行时权限 这个版本中引入了新的权限模型,现在用户可以在运行时直接管理应用程序的权限.这个模型基于用户对权限控制的更多可见性,同时为应用程序的开发者提供更流畅的应用安装和自动升级.用户可以为已安装的每 ...

  9. Android 6.0 Changes

    原文链接:http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html 伴随着新特性和功能,Andr ...

随机推荐

  1. 【iOS】7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager(位置管理器)

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  2. HTTP请求错误400、401、402、403、404、405、406、407、412、414、500、501、502解析

    HTTP 错误 400 400 请求出错 由于语法格式有误,服务器无法理解此请求.不作修改,客户程序就无法重复此请求. HTTP 错误 401 401.1 未授权:登录失败 此错误表明传输给服务器的证 ...

  3. Docker 使用指南 (四)—— 数据卷的使用

    一.数据卷的使用 有时候需要使用数据库,但是又希望它的数据能保存在本地,Docker中提供了数据卷可以供你方便的操作数据.数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用 ...

  4. 富文本,NSAttributedString,当需要改变的内容有相同的时候的解决方法

    在开发的过程中可能会遇到富文本展示,例如:一行文本,前面是题后面是答案,题和答案用不同的颜色字体,但是答案的内容在题总也有,这时候用平常的方法就会展示错误,因为把题中的内容改变了颜色二实际答案却没有改 ...

  5. [译]Selenium Python文档:目录

    作者:Baiju Muthukadan 协议:本文档采用知识共享署名 - 共享4.0国际许可. 原英文网址:http://selenium-python.readthedocs.io/index.ht ...

  6. TreeSet集合如何保证元素唯一

    TreeSet: 1.特点 TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列 2.使用方式 a.自然顺序(Comparable) TreeSet类的add()方法中会 ...

  7. (转)crontab安装(command not found)

    1. 确认crontab是否安装:执行 crontab -l 命令如果报 command not found,就表明没有安装 2. 安装 crontab执行 yum install -y vixie- ...

  8. webpack独立打包与缓存处理

    关于 微信公众号:前端呼啦圈(Love-FED) 我的博客:劳卜的博客 知乎专栏:前端呼啦圈 前言 先前写了一篇webpack入门的文章<webpack入门必知必会>,简单介绍了webpa ...

  9. 数据库DDL操作

    DDL1. 数据库* 查看所有数据库:SHOW DATABASES* 切换(选择要操作的)数据库:USE 数据库名* 创建数据库:CREATE DATABASE [IF NOT EXISTS] myd ...

  10. 学习Redux之分析Redux核心代码分析

    1. React,Flux简单介绍 学习React我们知道,React自带View和Controller库,因此,实现过程中不需要其他任何库,也可以独立开发应用.但是,随着应用程序规模的增大,其需要控 ...