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

现如今安卓的低功耗蓝牙应用十分普遍了,智能手环、手表遍地都是,基本都是利用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. 【react-router】从Link组件和a标签的区别说起,react-router如何实现导航并优化DOM性能?

    (注:参考自官方英文文档V3.X版本) react-router是伴随着react框架出现的路由系统,它也是公认的一种优秀的路由解决方案.在使用react-router时候,我们常常会使用其自带的路径 ...

  2. selenium自动化--(JAVA方法写的)第一章 源代码工程的导入

    1.首先打开eclipse,找到eclipse的工程窗口界面,依次找到"import-->import"功能 2.在弹出来的导入对话框中,选择导入已存在的工程"Ex ...

  3. CSV工具类

    分享自己昨天写的CSV工具类, 主要实现解析CSV格式, 直接上代码 #region private /// <summary> /// 从sr当前位置解析一个栏位 /// </su ...

  4. 2017年要学习的JavaScript的顶级框架和主题

    JavaScript的流行促进了一个非常活跃的由相关技术,框架和库组成的生态圈的发展.整个生态圈的多样性和活跃性越来越强,这让许多人变得越来越困惑. 你应该了解些什么技术呢?   我们应该将时间花费在 ...

  5. Jenkins集成Docker

    大概过程如下图: 由于需要用到docker打包镜像,jenkins宿主机上需要安装docker,原先的jenkins server安装在centos6上无法运行docker,所以这里单独用一台cent ...

  6. Python之路-Linux命令基础(3)

    作业一: 1)将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) 2)将用户信息数据库文件和用户密码数据库文件纵向合并为一个文件/2.txt(追加) 3)将/1.txt./2 ...

  7. ABP框架实战 1.基础信息维护

    在之前的一个开发项目中,因为公司战略发展,引用了这个ABP开源框架作为新项目的基础版本,由于客户的要求需要迁移旧系统数据,以及其他的一些原因,数据库采用了Oracle数据库管理.所以引用了Dapper ...

  8. 以正确的姿势实现一棵JavaScript菜单树

    菜单树是常见的前端特效, 一般长下面这样 还有各种形态的变种, 有长这样的 也有长这样的 尽管这些菜单的相貌都不尽相同, 在功能实现的本质上却都是相同的.实现程序的大致流程如下 读取服务器端的菜单数据 ...

  9. 《Python基础教程》第1章读书笔记

    # -*- coding:utf-8 -*- x = "hello " y = "world" print x+y print "hello &quo ...

  10. ajax 第四步

    Ajax和XMLHttpRequest详述 (2011-12-10 16:40:23) 转载▼ 标签: ajax xmlhttprequest 分类: Web Ajax:Asynchronous Ja ...