android BLE Peripheral 模拟 ibeacon 发出ble 广播
原文地址:
https://www.cnblogs.com/CharlesGrant/p/7155211.html
Android对外模模式(peripheral)的支持:
从Android 5.0+开始才支持。 api level >= 21
所以5.0 之前设备,是不能向外发送广播的。
Android中心设备(central)的支持:
从Android 4.3+ 。 api level >= 18
1、初始化蓝牙
2、检查ble是否可用
3、开启广播
4、扫描响应数据
5、创建iBeacon 广播数据
6、广播设置
7、开启广播后的回调
(1)初始化蓝牙:
添加权限:
1 <uses-permission android:name="android.permission.BLUETOOTH" />2 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />3 <!-- 6.0之后蓝牙还需要地理位置权限 -->4 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />5 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />6 7 <!-- 自行判断 -->8 <uses-feature9 android:name="android.hardware.bluetooth_le" 10 android:required="false" />
初始化:
1 //初始化BluetoothManager和BluetoothAdapter 2 if (mBluetoothManager == null) { 3 mBluetoothManager = (BluetoothManager) mContext.getSystemService(BLUETOOTH_SERVICE); 4 } 5 6 if (mBluetoothManager != null && mBluetoothAdapter == null) { 7 mBluetoothAdapter = mBluetoothManager.getAdapter(); 8 }
(2)检查是否可使用ble:
1 if (!activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {2 Toast.makeText(activity, "不支持ble", Toast.LENGTH_LONG).show(); 4 return;5 }6 7 final BluetoothManager mBluetoothManager = (BluetoothManager) activity.getSystemService(BLUETOOTH_SERVICE);8 mBluetoothAdapter = mBluetoothManager.getAdapter();9 10 if (mBluetoothAdapter == null) { 11 Toast.makeText(activity, "不支持ble", Toast.LENGTH_LONG).show();13 return; 14 } 15 // 获取蓝牙ble广播 16 mBluetoothAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); 17 if (mBluetoothAdvertiser == null) { 18 Toast.makeText(activity, "the device not support peripheral", Toast.LENGTH_SHORT).show(); 19 Log.e(TAG, "the device not support peripheral");21 return; 22 }
(3)开启广播:
public void startAdvertising(MockServerCallBack callBack) {//获取BluetoothLeAdvertiser,BLE发送BLE广播用的一个APIif (mBluetoothAdvertiser == null) {mBluetoothAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();}if (mBluetoothAdvertiser != null) {try {//创建BLE beacon Advertising并且广播mBluetoothAdvertiser.startAdvertising(createAdvSettings(true, 0), createIBeaconAdvertiseData(BluetoothUUID.bleServerUUID,mMajor, mMinor, mTxPower), createScanAdvertiseData(mMajor, mMinor, mTxPower, mAdvCallback);} catch (Exception e) {Log.v(TAG, "Fail to setup BleService");}}}
一个ble广播包:广播数据其实包含两部分:Advertising Data(广播数据) 和 Scan Response Data(扫描响应数据)。
通常情况下,广播的一方,按照一定的间隔,往空中广播 Advertising Data。
当某个监听设备监听到这个广播数据时候,会通过发送 Scan Response Request,请求广播方发送扫描响应数据数据。
这两部分数据的长度都是固定的 31 字节。
在 Android 中,系统会把这两个数据拼接在一起,返回一个 62 字节的数组。
(4)扫描响应数据:
可以自定义数据,比如增加湿度,温度等。
1 //设置scan广播数据2 public static AdvertiseData createScanAdvertiseData(short major, short minor, byte txPower) {3 AdvertiseData.Builder builder = new AdvertiseData.Builder();4 builder.setIncludeDeviceName(true);5 6 byte[] serverData = new byte[5];7 ByteBuffer bb = ByteBuffer.wrap(serverData);8 bb.order(ByteOrder.BIG_ENDIAN);9 bb.putShort(major); 10 bb.putShort(minor); 11 bb.put(txPower); 12 builder.addServiceData(ParcelUuid.fromString(BluetoothUUID.bleServerUUID.toString()) 13 , serverData); 14 15 AdvertiseData adv = builder.build(); 16 return adv; 17 }
5、创建ibeacon 广播数据。
iBeacon 的广播结构:iBeacon 只是协议.
- the 2 byte beacon identifier (0xBEAC)
- the 16 bytes UUID
- the 2 byte major
- the 2 byte minor
- the 1 byte tx power
Byte 0-2: Standard BLE Flags
Byte 0: Length : 0x02Byte 1: Type: 0x01 (Flags)Byte 2: Value: 0x06 (Typical Flags)
Byte 3-29: Apple Defined iBeacon Data
Byte 3: Length: 0x1aByte 4: Type: 0xff (Custom Manufacturer Packet)Byte 5-6: Manufacturer ID : 0x4c00 (Apple)Byte 7: SubType: 0x2 (iBeacon)Byte 8: SubType Length: 0x15Byte 9-24: Proximity UUIDByte 25-26: MajorByte 27-28: MinorByte 29: Signal Power
ManufactureData : 设备厂商的自定义数据
使用addManufactureData(int manufacturerId, byte[] manufacturerSpecificData);
第一个参数0x004c,是厂商id,id长度为2个字节,不足2个字节系统会补0.
(比如id传入0xac, 不足两个字节,输入广播时:ac, 00)
1 /**2 * create AdvertiseDate for iBeacon3 */4 public static AdvertiseData createIBeaconAdvertiseData(UUID proximityUuid, short major, short minor, byte txPower) {5 6 String[] uuidstr = proximityUuid.toString().replaceAll("-", "").toLowerCase().split("");7 byte[] uuidBytes = new byte[16];8 for (int i = 1, x = 0; i < uuidstr.length; x++) {9 uuidBytes[x] = (byte) ((Integer.parseInt(uuidstr[i++], 16) << 4) | Integer.parseInt(uuidstr[i++], 16)); 10 } 11 byte[] majorBytes = {(byte) (major >> 8), (byte) (major & 0xff)}; 12 byte[] minorBytes = {(byte) (minor >> 8), (byte) (minor & 0xff)}; 13 byte[] mPowerBytes = {txPower}; 14 byte[] manufacturerData = new byte[0x17]; 15 byte[] flagibeacon = {0x02, 0x15}; 16 17 System.arraycopy(flagibeacon, 0x0, manufacturerData, 0x0, 0x2); 18 System.arraycopy(uuidBytes, 0x0, manufacturerData, 0x2, 0x10); 19 System.arraycopy(majorBytes, 0x0, manufacturerData, 0x12, 0x2); 20 System.arraycopy(minorBytes, 0x0, manufacturerData, 0x14, 0x2); 21 System.arraycopy(mPowerBytes, 0x0, manufacturerData, 0x16, 0x1); 22 23 AdvertiseData.Builder builder = new AdvertiseData.Builder(); 24 builder.addManufacturerData(0x004c, manufacturerData); 25 26 AdvertiseData adv = builder.build(); 27 return adv; 28 }
6、创建广播设置:模式,是否可连接,功率
setAdvertiseMode(int advertiseMode)设置广播的模式,低功耗,平衡和低延迟三种模式;对应 AdvertiseSettings.ADVERTISE_MODE_LOW_POWER ,ADVERTISE_MODE_BALANCED ,ADVERTISE_MODE_LOW_LATENCY从左右到右,广播的间隔会越来越短
setConnectable(boolean connectable)设置是否可以连接。广播分为可连接广播和不可连接广播,一般不可连接广播应用在iBeacon设备上,这样APP无法连接上iBeacon设备
setTimeout(int timeoutMillis)设置广播的最长时间,最大值为常量AdvertiseSettings.LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000; 180秒设为0时,代表无时间限制会一直广播
setTxPowerLevel(int txPowerLevel)设置广播的信号强度常量有AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW, ADVERTISE_TX_POWER_LOW, ADVERTISE_TX_POWER_MEDIUM, ADVERTISE_TX_POWER_HIGH 从左到右分别表示强度越来越强. 举例:当设置为ADVERTISE_TX_POWER_ULTRA_LOW时,手机1和手机2放在一起,手机2扫描到的rssi信号强度为-56左右,当设置为ADVERTISE_TX_POWER_HIGH 时, 扫描到的信号强度为-33左右,信号强度越大,表示手机和设备靠的越近
* AdvertiseSettings.ADVERTISE_TX_POWER_HIGH -56 dBm @ 1 meter with Nexus 5
* AdvertiseSettings.ADVERTISE_TX_POWER_LOW -75 dBm @ 1 meter with Nexus 5
* AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM -66 dBm @ 1 meter with Nexus 5
*AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW not detected with Nexus 5
1 public AdvertiseSettings createAdvSettings(boolean connectable, int timeoutMillis) {2 AdvertiseSettings.Builder builder = new AdvertiseSettings.Builder();3 //设置广播的模式, 功耗相关4 builder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);5 builder.setConnectable(connectable);6 builder.setTimeout(timeoutMillis);7 builder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);8 AdvertiseSettings mAdvertiseSettings = builder.build();9 if (mAdvertiseSettings == null) { 10 Log.e(TAG, "mAdvertiseSettings == null"); 11 } 12 return mAdvertiseSettings; 13 }
7、开始广播后的回调。提示广播开启是否成功。
1 //发送广播的回调,onStartSuccess/onStartFailure很明显的两个Callback2 private AdvertiseCallback mAdvCallback = new AdvertiseCallback() {3 public void onStartSuccess(android.bluetooth.le.AdvertiseSettings settingsInEffect) {4 super.onStartSuccess(settingsInEffect);5 if (settingsInEffect != null) {6 Log.d(TAG, "onStartSuccess TxPowerLv=" + settingsInEffect.getTxPowerLevel() + " mode=" + settingsInEffect.getMode() + " timeout=" + settingsInEffect.getTimeout());7 } else {8 Log.d(TAG, "onStartSuccess, settingInEffect is null");9 } 10 } 11 12 public void onStartFailure(int errorCode) { 13 super.onStartFailure(errorCode); 14 Log.d(TAG, "onStartFailure errorCode=" + errorCode); 15 16 if (errorCode == ADVERTISE_FAILED_DATA_TOO_LARGE) { 17 Toast.makeText(mContext, "advertise_failed_data_too_large", Toast.LENGTH_LONG).show(); 18 Log.e(TAG, "Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes."); 19 } else if (errorCode == ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) { 20 Toast.makeText(mContext, "advertise_failed_too_many_advertises", Toast.LENGTH_LONG).show(); 21 Log.e(TAG, "Failed to start advertising because no advertising instance is available."); 22 23 } else if (errorCode == ADVERTISE_FAILED_ALREADY_STARTED) { 24 Toast.makeText(mContext, "advertise_failed_already_started", Toast.LENGTH_LONG).show(); 25 Log.e(TAG, "Failed to start advertising as the advertising is already started"); 26 27 } else if (errorCode == ADVERTISE_FAILED_INTERNAL_ERROR) { 28 Toast.makeText(mContext, "advertise_failed_internal_error", Toast.LENGTH_LONG).show(); 29 Log.e(TAG, "Operation failed due to an internal error"); 30 31 } else if (errorCode == ADVERTISE_FAILED_FEATURE_UNSUPPORTED) { 32 Toast.makeText(mContext, "advertise_failed_feature_unsupported", Toast.LENGTH_LONG).show(); 33 Log.e(TAG, "This feature is not supported on this platform"); 34 35 } 36 } 37 };
注意:对于ios 设备接受广播,外围设备还是要广播出来一个16位的serviceUUID,因为扫描的时候要用(如果不指定特定服务的UUID,没有办法进行后台持续扫描连接).
Android 上的低功耗蓝牙实践
源代码demo
android BLE Peripheral 模拟 ibeacon 发出ble 广播相关推荐
- android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser
android 从4.3系统开始可以连接BLE设备,这个大家都知道了.iOS是从7.0版本开始支持BLE.android 进入5.0时代时,开放了一个新功能,手机可以模拟设备发出BLE广播, 这个新功 ...
- android ble peripheral,android5.0(Lollipop) BLE Peripheral牛刀小试
转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46468743 知道Android L对蓝牙对了一些改进.包含加入A2dp s ...
- android蓝牙4.0(BLE)开发之ibeacon初步
一个april beacon里携带的信息如下 ? 1 <code class=" hljs ">0201061AFF4C0002159069BDB88C11416BAC ...
- android+5.0+ble,android5.0(Lollipop) BLE Peripheral牛刀小试(示例代码)
转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46468743 知道Android L对蓝牙对了一些改进.包含加入A2dp s ...
- android ble status,Android BLE peripheral disconnects with status code BLE_HCI_INSTANT_PASSED(0x28)
问题 My application is able to connect to the BLE peripheral(which is an OBDII/J1939 device) device su ...
- android5.0(Lollipop) BLE Peripheral牛刀小试
转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46468743 知道Android L对蓝牙对了一些改进,包括添加A2dp s ...
- AliOS-Things+ESP32 BLE篇 (1)BLE peripheral
由于STM32的板子没有自带蓝牙和wifi模组,所以外设方面的demo,我选择放到乐鑫的ESP32模组上.一方面是由于ESP32这块板子有丰富的BT/WIFI的实现例程,还因为乐鑫的这款SOC扩展性很 ...
- BLE 技术(八)--- BLE MESH 各层报文是如何设计的(上)?
文章目录 前言: 一.SIG MESH Bearer Layer 1.1 Advertising Bearer Layer 1.2 GATT Bearer Layer 二.SIG MESH Provi ...
- 详解BLE 空中包格式—兼BLE Link layer协议解析
BLE有几种空中包格式?常见的PDU命令有哪些?PDU和MTU的区别是什么?DLE又是什么?BLE怎么实现重传的?BLE ACK机制原理是什么?希望这篇文章能帮你回答以上问题. 虽然BLE空中包(pa ...
最新文章
- 数据中心建设“优劣”在于这几个关键问题
- java正则学习笔记三
- Linux系统主要目录及作用
- hihocoder 1931 最短管道距离
- JZOJ 5820. 【NOIP提高A组模拟2018.8.16】 非法输入
- CSS自定义文件上传按钮
- pc,移动端局域网文件共享
- 四种进程或线程同步互斥的控制方法
- MVVM开发模式MVVM Light Toolkit
- 少年,别再收藏文章了!
- Team Foundation 使用第三方比较工具
- 吴锦华/明鑫: 用户态文件系统(FUSE)框架分析和实战
- AIX系统常用命令总结
- 人工智能——状态空间的启发式搜索
- Ubuntu14.04显示隐藏文件
- 什么是非关系型数据库,Redis概述、安装及部署Redis群集
- 【Opencv综合应用】自制训练集的人脸识别2——制作csv文件
- 3.1、立项管理内容
- CAD文件翻译和本地化
- 论文翻译 Joint Discriminative and Generative Learning for Person Re-identification
热门文章
- Python的函数返回值和参数
- charles 抓包显示unknown
- day25-day26-动态内容和异步编程
- matlab画动图留下末端点轨迹,请问Matlab robotic Toolbox中怎么让机械手运动时末端走过的轨迹显示出来?...
- Tailwind Base
- 【LinuxCNC开发序列教程二】Ethercat主站终端调试
- Cuda: Handle Conflicting Installation Methods
- word 文档标题样式相同、行距效果不同的解决办法
- MATLAB导入EXCEL数据D=xlsread()的一种情况
- 用cobar搭建分布式数据库