原文地址:

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 广播相关推荐

  1. android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser

    android 从4.3系统开始可以连接BLE设备,这个大家都知道了.iOS是从7.0版本开始支持BLE.android 进入5.0时代时,开放了一个新功能,手机可以模拟设备发出BLE广播, 这个新功 ...

  2. android ble peripheral,android5.0(Lollipop) BLE Peripheral牛刀小试

    转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46468743 知道Android L对蓝牙对了一些改进.包含加入A2dp s ...

  3. android蓝牙4.0(BLE)开发之ibeacon初步

    一个april beacon里携带的信息如下 ? 1 <code class=" hljs ">0201061AFF4C0002159069BDB88C11416BAC ...

  4. android+5.0+ble,android5.0(Lollipop) BLE Peripheral牛刀小试(示例代码)

    转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46468743 知道Android L对蓝牙对了一些改进.包含加入A2dp s ...

  5. 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 ...

  6. android5.0(Lollipop) BLE Peripheral牛刀小试

    转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46468743 知道Android L对蓝牙对了一些改进,包括添加A2dp s ...

  7. AliOS-Things+ESP32 BLE篇 (1)BLE peripheral

    由于STM32的板子没有自带蓝牙和wifi模组,所以外设方面的demo,我选择放到乐鑫的ESP32模组上.一方面是由于ESP32这块板子有丰富的BT/WIFI的实现例程,还因为乐鑫的这款SOC扩展性很 ...

  8. BLE 技术(八)--- BLE MESH 各层报文是如何设计的(上)?

    文章目录 前言: 一.SIG MESH Bearer Layer 1.1 Advertising Bearer Layer 1.2 GATT Bearer Layer 二.SIG MESH Provi ...

  9. 详解BLE 空中包格式—兼BLE Link layer协议解析

    BLE有几种空中包格式?常见的PDU命令有哪些?PDU和MTU的区别是什么?DLE又是什么?BLE怎么实现重传的?BLE ACK机制原理是什么?希望这篇文章能帮你回答以上问题. 虽然BLE空中包(pa ...

最新文章

  1. 数据中心建设“优劣”在于这几个关键问题
  2. java正则学习笔记三
  3. Linux系统主要目录及作用
  4. hihocoder 1931 最短管道距离
  5. JZOJ 5820. 【NOIP提高A组模拟2018.8.16】 非法输入
  6. CSS自定义文件上传按钮
  7. pc,移动端局域网文件共享
  8. 四种进程或线程同步互斥的控制方法
  9. MVVM开发模式MVVM Light Toolkit
  10. 少年,别再收藏文章了!
  11. Team Foundation 使用第三方比较工具
  12. 吴锦华/明鑫: 用户态文件系统(FUSE)框架分析和实战
  13. AIX系统常用命令总结
  14. 人工智能——状态空间的启发式搜索
  15. Ubuntu14.04显示隐藏文件
  16. 什么是非关系型数据库,Redis概述、安装及部署Redis群集
  17. 【Opencv综合应用】自制训练集的人脸识别2——制作csv文件
  18. 3.1、立项管理内容
  19. CAD文件翻译和本地化
  20. 论文翻译 Joint Discriminative and Generative Learning for Person Re-identification

热门文章

  1. Python的函数返回值和参数
  2. charles 抓包显示unknown
  3. day25-day26-动态内容和异步编程
  4. matlab画动图留下末端点轨迹,请问Matlab robotic Toolbox中怎么让机械手运动时末端走过的轨迹显示出来?...
  5. Tailwind Base
  6. 【LinuxCNC开发序列教程二】Ethercat主站终端调试
  7. Cuda: Handle Conflicting Installation Methods
  8. word 文档标题样式相同、行距效果不同的解决办法
  9. MATLAB导入EXCEL数据D=xlsread()的一种情况
  10. 用cobar搭建分布式数据库