Skip to content

Commit 201e4a6

Browse files
committed
Started making the library less bound to ibeacons
1 parent 4e17365 commit 201e4a6

13 files changed

Lines changed: 144 additions & 75 deletions

File tree

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ In the `onLeScan()` method of your `BluetoothAdapter.LeScanCallback()` create a
3333

3434
For example:
3535

36-
<pre>
36+
```
3737
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
3838
3939
@Override
@@ -51,7 +51,7 @@ For example:
5151
});
5252
}
5353
};
54-
</pre>
54+
```
5555

5656
### Device Properties
5757

@@ -83,7 +83,17 @@ Once you've created a BluetoothLe device, you can access the AdRecord store via
8383
They are also declared as constants in `AdRecord.java`.
8484

8585
### Fun with iBeacons
86-
You can check if a device is an iBeacon by using `IBeaconUtils.isThisAnIBeacon(BluetootLeDevice device)`. Once you have confirmed that it is, you can create a new IBeaconDevice via the IBeaconDevice constructor.
86+
You can check if a device is an iBeacon by using `BeaconUtils.getBeaconType(BluetootLeDevice device)`. Once you have confirmed that it is, you can create a new IBeaconDevice via the IBeaconDevice constructor.
87+
88+
Example Flow:
89+
```
90+
final BluetoothLeDevice device = ... // A generic BLE device
91+
92+
if (BeaconUtils.getBeaconType(device) == BeaconType.IBEACON) {
93+
final IBeaconDevice iBeacon = new IBeaconDevice(device);
94+
// DO STUFF
95+
}
96+
```
8797

8898
An IBeaconDevice extends BluetoothLeDevice, so you still have access to the same methods as before. In addition you can do the following:
8999

@@ -114,6 +124,7 @@ You can also lookup values and convert them to human friendly strings:
114124
* Added some Estimote UUIDs
115125
* v1.0.0:
116126
* Migrated project to Android Studio/ gradle
127+
* We now use the more generic `BeaconUtils.getBeaconType()` method instead of `IBeaconUtils.isThisAnIBeacon()`
117128
* Fix for [issue 5](https://github.com/alt236/Bluetooth-LE-Library---Android/issues/5)
118129
* Fix for [issue 9](https://github.com/alt236/Bluetooth-LE-Library---Android/issues/9)
119130

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package uk.co.alt236.bluetoothlelib.device.beacon;
2+
3+
/**
4+
*
5+
*/
6+
public enum BeaconType {
7+
NOT_A_BEACON,
8+
IBEACON
9+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package uk.co.alt236.bluetoothlelib.device.beacon;
2+
3+
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
4+
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
5+
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconConstants;
6+
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
7+
8+
/**
9+
*
10+
*/
11+
public final class BeaconUtils {
12+
13+
private BeaconUtils(){
14+
// TO AVOID INSTANTIATION
15+
}
16+
17+
/**
18+
* Ascertains whether a Manufacturer Data byte array belongs to a known Beacon type;
19+
*
20+
* @param manufacturerData a Bluetooth LE device's raw manufacturerData.
21+
* @return the {@link BeaconType}
22+
*/
23+
public static BeaconType getBeaconType(final byte[] manufacturerData) {
24+
if (manufacturerData == null) {
25+
return BeaconType.NOT_A_BEACON;
26+
}
27+
28+
if(isIBeacon(manufacturerData)){
29+
return BeaconType.IBEACON;
30+
} else {
31+
return BeaconType.NOT_A_BEACON;
32+
}
33+
}
34+
35+
/**
36+
* Ascertains whether a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} is an iBeacon;
37+
*
38+
* @param device a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} device.
39+
* @return the {@link BeaconType}
40+
*/
41+
public static BeaconType getBeaconType(final BluetoothLeDevice device) {
42+
final int key = AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA;
43+
return getBeaconType(device.getAdRecordStore().getRecordDataAsString(key).getBytes());
44+
}
45+
46+
private static boolean isIBeacon(final byte[] manufacturerData){
47+
// An iBeacon record must be at least 25 chars long
48+
if (!(manufacturerData.length >= 25)) {
49+
return false;
50+
}
51+
52+
if (ByteUtils.doesArrayBeginWith(manufacturerData, IBeaconConstants.MANUFACTURER_DATA_IBEACON_PREFIX)) {
53+
return true;
54+
}
55+
56+
return false;
57+
}
58+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
2+
3+
/**
4+
*
5+
*/
6+
public class IBeaconConstants {
7+
public static final byte[] MANUFACTURER_DATA_IBEACON_PREFIX = {0x4C, 0x00, 0x02, 0x15};
8+
9+
}

library/src/main/java/uk/co/alt236/bluetoothlelib/device/IBeaconDevice.java renamed to library/src/main/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconDevice.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package uk.co.alt236.bluetoothlelib.device;
1+
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
22

33
import android.bluetooth.BluetoothDevice;
44
import android.os.Parcel;
55

6-
import uk.co.alt236.bluetoothlelib.device.mfdata.IBeaconManufacturerData;
7-
import uk.co.alt236.bluetoothlelib.util.IBeaconDistanceDescriptor;
8-
import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
6+
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
7+
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
8+
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
99

1010
public class IBeaconDevice extends BluetoothLeDevice {
1111

@@ -139,7 +139,7 @@ public String getUUID() {
139139
}
140140

141141
private void validate() {
142-
if (!IBeaconUtils.isThisAnIBeacon(this)) {
142+
if (BeaconUtils.getBeaconType(this) != BeaconType.IBEACON) {
143143
throw new IllegalArgumentException("Device " + getDevice() + " is not an iBeacon.");
144144
}
145145
}

library/src/main/java/uk/co/alt236/bluetoothlelib/util/IBeaconDistanceDescriptor.java renamed to library/src/main/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconDistanceDescriptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package uk.co.alt236.bluetoothlelib.util;
1+
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
22

33
public enum IBeaconDistanceDescriptor {
44
IMMEDIATE,

library/src/main/java/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java renamed to library/src/main/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconManufacturerData.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
package uk.co.alt236.bluetoothlelib.device.mfdata;
1+
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
22

33
import java.util.Arrays;
44

55
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
66
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
7+
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
8+
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
79
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
8-
import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
910

1011
/**
1112
* Parses the Manufactured Data field of an iBeacon
@@ -72,7 +73,7 @@ public IBeaconManufacturerData(final BluetoothLeDevice device) {
7273
public IBeaconManufacturerData(final byte[] manufacturerData) {
7374
mData = manufacturerData;
7475

75-
if (!IBeaconUtils.isThisAnIBeacon(manufacturerData)) {
76+
if (BeaconUtils.getBeaconType(mData) != BeaconType.IBEACON) {
7677
throw new IllegalArgumentException(
7778
"Manufacturer record '"
7879
+ Arrays.toString(manufacturerData)

library/src/main/java/uk/co/alt236/bluetoothlelib/util/IBeaconUtils.java renamed to library/src/main/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconUtils.java

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
package uk.co.alt236.bluetoothlelib.util;
1+
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
22

3-
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
4-
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
3+
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
54

6-
public class IBeaconUtils {
5+
final class IBeaconUtils {
76
private static final double DISTANCE_THRESHOLD_WTF = 0.0;
87
private static final double DISTANCE_THRESHOLD_IMMEDIATE = 0.5;
98
private static final double DISTANCE_THRESHOLD_NEAR = 3.0;
109

11-
private static final byte[] MANUFACTURER_DATA_IBEACON_PREFIX = {0x4C, 0x00, 0x02, 0x15};
10+
private IBeaconUtils(){
11+
// TO AVOID INSTANTIATION
12+
}
1213

1314
/**
1415
* Calculates the accuracy of an RSSI reading.
@@ -75,38 +76,4 @@ public static IBeaconDistanceDescriptor getDistanceDescriptor(final double accur
7576

7677
return IBeaconDistanceDescriptor.FAR;
7778
}
78-
79-
/**
80-
* Ascertains whether a Manufacturer Data byte array belongs to an iBeacon;
81-
*
82-
* @param manufacturerData a Bluetooth LE device's raw manufacturerData.
83-
* @return true if the manufacturer data belong to an iBeacon
84-
*/
85-
public static boolean isThisAnIBeacon(final byte[] manufacturerData) {
86-
if (manufacturerData == null) {
87-
return false;
88-
}
89-
90-
// An iBeacon record must be at least 25 chars long
91-
if (!(manufacturerData.length >= 25)) {
92-
return false;
93-
}
94-
95-
if (ByteUtils.doesArrayBeginWith(manufacturerData, MANUFACTURER_DATA_IBEACON_PREFIX)) {
96-
return true;
97-
}
98-
99-
return false;
100-
}
101-
102-
/**
103-
* Ascertains whether a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} is an iBeacon;
104-
*
105-
* @param device a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} device.
106-
* @return true if the device is an iBeacon, false otherwise
107-
*/
108-
public static boolean isThisAnIBeacon(final BluetoothLeDevice device) {
109-
final int key = AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA;
110-
return isThisAnIBeacon(device.getAdRecordStore().getRecordDataAsString(key).getBytes());
111-
}
11279
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package uk.co.alt236.bluetoothlelib.device.beacon;
2+
3+
import junit.framework.TestCase;
4+
5+
/**
6+
*
7+
*/
8+
public class BeaconUtilsTest extends TestCase {
9+
10+
public void testGetBeaconTypeInvalid() throws Exception {
11+
assertEquals(BeaconType.NOT_A_BEACON, BeaconUtils.getBeaconType((byte[]) null));
12+
assertEquals(BeaconType.NOT_A_BEACON, BeaconUtils.getBeaconType(new byte[0]));
13+
assertEquals(BeaconType.NOT_A_BEACON, BeaconUtils.getBeaconType(new byte[25]));
14+
}
15+
16+
public void testGetBeaconTypeIBeacon() throws Exception {
17+
assertEquals(BeaconType.IBEACON, BeaconUtils.getBeaconType(new byte[]{
18+
0x4C, 0x00, 0x02, 0x15, 0x00, // <- Magic iBeacon header
19+
0x00, 0x00, 0x00, 0x00, 0x00,
20+
0x00, 0x00, 0x00, 0x00, 0x00,
21+
0x00, 0x00, 0x00, 0x00, 0x00,
22+
0x00, 0x00, 0x00, 0x00, 0x00
23+
}));
24+
}
25+
}

library/src/test/java/uk/co/alt236/bluetoothlelib/util/IBeaconUtilsTest.java renamed to library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconUtilsTest.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package uk.co.alt236.bluetoothlelib.util;
1+
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
22

33
import junit.framework.TestCase;
44

@@ -7,20 +7,6 @@
77
*/
88
public class IBeaconUtilsTest extends TestCase {
99

10-
public void testIsThisAnIBeacon() throws Exception {
11-
assertFalse(IBeaconUtils.isThisAnIBeacon((byte[]) null));
12-
assertFalse(IBeaconUtils.isThisAnIBeacon(new byte[0]));
13-
assertFalse(IBeaconUtils.isThisAnIBeacon(new byte[25]));
14-
15-
assertTrue(IBeaconUtils.isThisAnIBeacon(new byte[]{
16-
0x4C, 0x00, 0x02, 0x15, 0x00, // <- Magic iBeacon header
17-
0x00, 0x00, 0x00, 0x00, 0x00,
18-
0x00, 0x00, 0x00, 0x00, 0x00,
19-
0x00, 0x00, 0x00, 0x00, 0x00,
20-
0x00, 0x00, 0x00, 0x00, 0x00
21-
}));
22-
}
23-
2410
public void testGetDistanceDescriptor() throws Exception {
2511
assertEquals(IBeaconDistanceDescriptor.UNKNOWN, IBeaconUtils.getDistanceDescriptor(-1));
2612

0 commit comments

Comments
 (0)