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

现如今安卓的低功耗蓝牙应用十分普遍了,智能手环、手表遍地都是,基本都是利用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. OAuth2.0 知多少

    1. 引言 周末逛简书,看了一篇写的极好的文章,点击大红心点赞,就直接给我跳转到登录界面了,原来点赞是需要登录的. 可是没有我并没有简书账号,一直使用的QQ的集成登录.下面有一排社交登录按钮,我们可以 ...

  2. php错误的处理

    错误的分类 通常分3种: 语法错误: 程序运行之前,都要先检查语法.如果语法有错误,就会立即报错,并且不会去执行程序. 运行时错误: 就是在程序语法检查通过后,,开始运行程序并在此过程中遇到的错误.常 ...

  3. 读书笔记 effective c++ Item 37 永远不要重新定义继承而来的函数默认参数值

    从一开始就让我们简化这次的讨论.你有两类你能够继承的函数:虚函数和非虚函数.然而,重新定义一个非虚函数总是错误的(Item 36),所以我们可以安全的把这个条款的讨论限定在继承带默认参数值的虚函数上. ...

  4. 查看apache,mysql,nginx,php的编译参数

    查看nginx编译参数:/usr/local/nginx/sbin/nginx -V 查看apache编译参数:cat /usr/local/apache2/build/config.nice 查看m ...

  5. centos6.5 源码安装 gtk 环境

    解决 No package 'gtk+-2.0′ found问题方法:yum install libgnomeui-devel 执行了上面的,下面的就可以放弃了,yum 大法好 首先 yum 安装下面 ...

  6. flume日志采集框架使用

    flume日志采集框架使用 本次学习使用的全部过程均不在集群上,均在本机环境,供学习参考 先决条件: flume-ng-1.6.0-cdh5.8.3.tar  去cloudrea下载flume框架,笔 ...

  7. Ubuntu离线安装VSCode(附带前期准备工作)

    跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux 在说正式步骤前先把准备工作做到位: 1.IP设置,这个因为是GUI的,手动设置 ...

  8. 转接口IC GM7122:BT656转CVBS芯片 视频编码电路

    1 概述    视频编码电路主要实现接收8位CCIR656格式的YUV数据,(例如MPEG解码数据),并编码成CVBS信号,经过D/A转换后输出.基本的编码功能包括副载波产生,色差信号调制,同步信号内 ...

  9. ORA-00918: 未明确定义列

    ORA-00918: 未明确定义列 出现问题原因及解决办法. --正常写,结果带上表名的字段在处理后表头名称相同,在进行下一次嵌套时就会出现问题  select au.userxm,au01.user ...

  10. (iOS)私有API的使用(原创)

    最近在做企业级程序,需要搞设备的udid等信息,但是ios7把udid私有化了,不公开使用.所以研究了一下ios的私有api. 调查了一下文章,发现这方面的文章不多,国内更是不全,高手们都懒得写基础教 ...