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      2      3      4      5      6  7      8     

复制代码

 初始化:

复制代码

1 //初始化BluetoothManager和BluetoothAdapter2  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广播用的一个API        if (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 :  0x02 Byte 1: Type: 0x01 (Flags) Byte 2: Value: 0x06 (Typical Flags)

Byte 3-29: Apple Defined iBeacon Data

复制代码

 Byte 3: Length: 0x1a Byte 4: Type: 0xff (Custom Manufacturer Packet) Byte 5-6: Manufacturer ID : 0x4c00 (Apple) Byte 7: SubType: 0x2 (iBeacon) Byte 8: SubType Length: 0x15 Byte 9-24: Proximity UUID Byte 25-26: Major Byte 27-28: Minor Byte 29: Signal Power

复制代码

ManufactureData : 设备厂商的自定义数据

使用addManufactureData(int manufacturerId, byte[] manufacturerSpecificData);

第一个参数0x004c,是厂商id,id长度为2个字节,不足2个字节系统会补0.

(比如id传入0xac, 不足两个字节,输入广播时:ac, 00)

复制代码

 1 /** 2      * create AdvertiseDate for iBeacon 3      */ 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很明显的两个Callback 2     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,没有办法进行后台持续扫描连接).

更多相关文章

  1. 第十二章:Android数据存储(下)
  2. 基于 android 数据备份恢复的一种实现
  3. Android开发实践 数据存储 学习、应用、总结
  4. 编写高效的Android代码
  5. Android 测试代码编写小技巧 - UI 和 单元测试间共享代码
  6. Android studio 通过以servlet搭建的服务器访问 PC端 mysql数据
  7. 初涉Android蓝牙开发(转) 收藏以备后用

随机推荐

  1. android ContentResolver
  2. Android(安卓)TV,机顶盒Gridview 焦点
  3. 『Android』activity的生命周期
  4. Android(安卓)C++ 多线程
  5. android 画线
  6. [置顶] Android 代码混淆 选项说明
  7. Android TextView 复制功能
  8. Android签名文件转化为pk8和pem的实现
  9. Android使用Shape实现布局圆角边框
  10. 【Android】关于android:divider 的用法