I am sorry if this question is not an "SO approved" type of question.
I would like to develop an app that act as a beacon (among of other functionality). This app will be installed on an Android device.
I am very new at all these Bluetooth programming and I would like to get some answers on these questions:
Can anyone point me on the right part as where to start?
How client app get notification from the beacon? Can anyone explain how it works?
Thank you and sorry for these questions.
A few points:
Yes, you can make a beacon app that sends both an iBeacon and/or an Eddystone beacon transmission from an Android device. You need a device with Android 5.0+ that supports transmission (not all do). You can see a list of such devices here. The Android Beacon Library shows how to code transmission here. There is also an off-the-shelf Locate app that supports transmission here.
It is also possible to make a transmitter beacon app on iOS, but iOS only supports transmission of iBeacon packets (you cannot transmit Eddystone on iOS), and iOS cannot transmit when the app is in the background. Android can.
If you want your client app to detect quickly in the background on iOS, you are better off with iBeacon than Eddystone. Detection of iBeacon signals is optimized in the background on iOS and is built-in. Detection of Eddystone requires extra software and is not as fast.
To send a notification on beacon discovery you simply write code in the client app that detects the unique beacon identifier then creates a local notification message keyed off the beacon identifier and sends it to the user. The important part to understand us that the client code does all of the message sending locally. All the beacon app does is transmit a unique identifier that the client app receives.
To illustrate the point about how you send local notifications based on beacon identifiers, here is some sample code for iOS. This code runs on the client app. The Beacon simply sends out a transmission with specific beacon identifiers, and the client app reads them and acts appropriately.
var lastNotificationTime = NSDate(timeIntervalSince1970: 0) // Initialize last Notification time to a long time ago
func locationManager(manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], inRegion region: CLBeaconRegion) {
// Only send notification if we have not done so in the last hour (3600 seconds)
if (lastNotificationTime.timeIntervalSinceNow < -3600.0) {
for beacon in beacons {
// Send a 20% off notification for beacon with identifiers major 1, minor 2
if beacon.major.intValue == 1 && beacon.minor.intValue == 2 {
let localNotification = UILocalNotification()
localNotification.alertTitle = "Discount 20% on all items"
dispatch_async(dispatch_get_main_queue()) {
UIApplication.sharedApplication().presentLocalNotificationNow(localNotification)
}
}
}
}
}
Full Disclosure: I am the lead developer on the Android Beacon Library open source project and the author of the Locate app.
Related
I'm writing an BLE application, where need to track if peripherals device is advertising or has stop.
I followed getting peripherals without duplications this and BLE Filtering behaviour of startLeScan() and I completely agree over here.
To make it feasible I kept timer which re-scan for peripherals after certain time (3 sec). But with new device available on market(with 5.0 update), some time re-scan take bit time to find peripherals.
Any suggestion or if anyone have achieved this?
Sounds like you're interested in scanning advertisements rather than connecting to devices. This is the "observer" role in Bluetooth Low Evergy, and corresponds to the "broadcaster" role more commonly known as a Beacon. (Bluetooth Core 4.1 Vol 1 Part A Section 6.2)
Typically you enable passive scanning, looking for ADV_IND packets broadcast by beacons. These may or may not contain a UUID. Alternatively, you can active scan by transmitting SCAN_REQ to which you may receive a SCAN_RSP. Many devices use different advertising content in ADV_IND and SCAN_RSP to increase the amount of information that can be broadcast - you could, for instance, fit a UUID128 into the ADV_IND followed by the Device Name in the SCAN_RSP. (Bluetooth Core 4.1 Vol 2 Part E Section 7.8.10)
Now you need to define "go away" - are you expecting the advertisements to stop or to fade away? You will get a Receive Signal Strength Indication "RSSI" with each advertisement (Bluetooth Core 4.1 Vol 2 Part E Section 7.7.65.2) - this is how iBeacon positioning works and there's plenty of support for beacon receivers in Android.
Alternatively you wait for N seconds for an advertisement that should be transmitted every T seconds where N>2T. The downside of the timed approach is that probably not receiving a beacon isn't the same as definitely receiving a weak beacon; to be sure you need N to be large and that impacts the latency between the broadcaster being switched off or moving out of range and your app detecting it.
One more thing - watch out that Advertising stops if something connects to a Peripheral (if you really are scanning for peripherals) another good reason to monitor RSSI.
First scenario: Bonded Devices
We know that if a bond is made, then most of the commercially available devices send directed advertisements in during re-connection. In situations such as this, according to BLE 4.0 specification, you cannot scan these devices on any BLE sniffer.
Second scenario: Connectable Devices
Peripheral devices are usually in this mode when they are initially in the reset phase. The central sends a connect initiator in response to an advertisement packet. This scenario offers you a lot of flexibility since you can play around with two predominant configuration options to alter connection time. These are: slavelatency on the peripheral and conninterval on the central. Now, I don't know how much effort it's going to take get it working on the Android platform, but if you use the Bluez BLE stack and a configurable peripheral such as a TI Sensor tag, then you can play around with these values.
Third scenario: Beacon devices
Since this is what your question revolves around, according to the BLE architecture, there are no parameters to play with. In this scenario, the central is just a dumb device left at the mercy of when a peripheral chooses to send it's beaconing signal.
Reference:
http://www.amazon.com/Inside-Bluetooth-Communications-Sensing-Library/dp/1608075796/ref=pd_bxgy_14_img_z
http://www.amazon.com/Bluetooth-Low-Energy-Developers-Handbook/dp/013288836X/ref=pd_bxgy_14_img_y
Edit: I forgot, have you tried setting the advertiser to non-connectable? That way you should be able to get duplicate scan results
I am dealing with a similar issue, that is, reliably track the RSSI values of multiple advertising devices over time.
It is sad, the most reliable way i found is not nice, rather dirty and battery consuming. It seems due to the number of android devices that handle BLE differently the most reliable.
I start LE scan, as soon as i get a callback i set a flag to stop and start scan again. That way you work around that DUPLICATE_PACKET filter issue since it resets whenever you start a fresh scan.
The ScanResults i dump into a sqlite db wich i shrink and evaluate once every x seconds.
It should be easy to adapt the shrinking to your use case, i.e. removing entries that are older than X, and then query for existance of a device to find out if you received a ScanResult in the last X seconds. However dont put that X value too low, as you must take into account that you still lose alot of advertisement packets on android LE scan, compared to a BLE scan on i.e. bluez..
Edit:
I can add some information i already found for speeding up the performance on Advertisement discovery. It involves modifying and compiling the bluedroid sources and root access to the device. Easiest would be building a full android yourself, i.e. Cyanogenmod.
When a LE scan is running, the bluetooth module sends the scan sesponse via HCI to the bluedroid stack. There various checks are done until it finally gets handed to the Java onScanResult(...) which is accessed via JNI.
By comparing the log of the hci data sent from the bluetooth module (can be enabled in /etc/bluetooth/bt_stack.conf) with debug output in the bluedroid stack aswell as the Java side i noticed that alot of advertisement packets are discarded, especially in some check. i dont really understand, beside that it has something to do with the bluedroid inquiry database
From the documentation of ScanResult we see that the ScanRecord includes the advertisement data plus the scan response data. So it might be that android blocks the report until it got the scan response data/ until it is clear there is no scan response data. This i could not verify, however a possibility.
As i am only interested in rapid updates on the RSSI of those packets, i simply commented that check out. It seems that way every single packet i get from the bluetooth moduly by hci is handed through to the Java side.
In file btm_ble_gap.c in function BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p)
comment out to_report = FALSE; in the following check starting on line 2265.
/* active scan, always wait until get scan_rsp to report the result */
if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
(evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))
{
BTM_TRACE_DEBUG("btm_ble_update_inq_result scan_rsp=false, to_report=false,\
scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);
p_i->scan_rsp = FALSE;
// to_report = FALSE; // to_report is initialized as TRUE, so we basically leave it to report it anyways.
}
else
p_i->scan_rsp = TRUE;
I was wondering :
When we enter a shop, using the app shop, we receive for example a notification.
But what if the beacon is down, and it's replaced with another beacon, with a different UUID etc .. ? Are the UUID/Major/Minor value of a beacon not harcoded but in a database on the server ? How it's fetched ?
Thanks you
The UUID of an iBeacon is not related in any way to its MAC address. It is a value that is assigned to the beacon by the beacon owner. Some beacon vendors have a specific UUID or range of UUIDs while others allow any UUID to be used.
If a particular beacon failed then the replacement would likely be configured with the same UUID.
When the app detects a particular beacon it needs to refer to some database, either in the app or on a server, that gives "meaning" to the particular UUID/major/minor combination so it is possible that the database could be updated to reflect the new hardware but this is less likely than simply configuring the replacement hardware with the same values
It is a good practice to not hard code your beacon identifiers in your app. You can build your app so on launch, it contacts a web service to download a list of identifiers to search for. You can build your own or use an off the shelf service like my company's ProximityKit that does exactly this.
Of course, if you are relying on beacon detections to launch your app, your app won't get auto launched to download the new beacon identifiers if the beacon ids change in advance. The user will have to manually do the launch to get the new list.
There are a few ways around this:
Set the identifiers on replaced beacons so they are the same as the old ones.
If you know you cannot set the identifiers, broaden the beacon region filter for auto launch so it matches a wide variety of beacon identifiers. On iOS you can search for all beacons with a shared UUID. On Android, you can search for all beacons regardless of identifiers.
When you initialise Beacon Region then you need to identify at least UUID and it is either hardcoded with in the app or can be placed on the server and should be retrieved from server before calling initialising Beacon Region.
NOTE:You should have a copy of all beacons UUIDs,majors and minors for future purposes
But suppose your Beacon goes out of order then there's a backup plan.
Follow below said steps:
1.Install Estimote-iOS or android app
2.Place the new beacon near to your device and start ranging beacons in estimote app.
3.Then you need to login with your cloud account in your app and configure new beacon(i.e edit your beacon's UUID.)You can even edit major,minor etc
4.Save those settings and your new beacon is configured and ready to use.
Happy Coding :)
Recently I got a iBeacon device with the intention of creating Android Apps than can recognize it and use it. I'm new using bluetooth in Android Apps and there many things than I still don't know. Looking in the Internet and in this forum I found recommendations to use the Radius Networks' Android IBeacon Library but, alas, now it's no longer available:
https://github.com/RadiusNetworks/android-ibeacon-service
So I started by using the code shown in Android Developers' guide about Bluetooth Low Energy:
https://developer.android.com/guide/topics/connectivity/bluetooth-le.html
Using this code I can detect the device, even connect to it, but I don't know how to get the Proximity Uuid and the Major and Minor values: the app shows a lot of Uuids from services and characteristics of the device, but none is the Proximity Uuid of the device.
Anyone could tell me how to get that data using the Android Bluetooth LE API, or help me to get the Radius Networks' Android iBeacon library for Eclipse and a guide to use it or sample showing how to use it?
Thank you.
EDIT/UPDATE:
It gets better.. AltBeacon !
Check the AltBeacon specifications
AltBeacon brings greater transparency to what a beacon transmits and
how that data can be used by Android, Windows and other devices.
Why the Android iBeacon Library by RadiusNetworks is no longer available:
Vendors have started complying with guidelines set by Apple and have,
as a result, been forced to ‘scrub’ their products of any references
or connection between Android devices and their detection of iBeacon
protocols.
Read more:
Apple cracks down on iBeacon for Android
I think the best bet seems to be from somebody who has been using it, already has it, can share it with you, as from previous commits, you may not get every component - library, sample, service
Also: A note from the CEO for Android iBeacon Lib, RadiusNetworks
Now, coming to Proximity UUID and major, minors:
I have not found a direct way to get it, in terms of a parameter, though you can have a look at read major, minor, uuid of beacons in android and SensorTag using iBeacon Technology. In the latter, there is an indication of major, minor, uuid after iBeacon Service, however TI instruments might be the restriction.
In android, as an identifier.. you can recover the device addressby device.getAddress() of the beacon/for each BluetoothDevice device;.
The following two are totally different things, although both are called UUID.
UUIDs of GATT services which are hosted on a BLE peripheral device.
Proximity UUID of iBeacon.
What you should know about "UUIDs of GATT services":
BLE peripheral devices may implement a GATT server.
A GATT server hosts GATT services.
What the API "android.bluetooth.BluetoothGatt.getServices()" returns is a list of GATT services (List<BluetoothGattService>).
BluetoothGattService.getUuid() returns the ID of the service.
What you should know about "Proximity UUID of iBeacon":
BLE peripheral devices broadcast advertising packets.
The payload part of an advertising packet contains a list of AD structures.
An AD structure consists of (1) Length (1 byte), (2) AD Type (1 byte) and (3) AD Data. The AD structure format is described in "11 ADVERTISING AND SCAN RESPONSE DATA FORMAT" of "Bluetooth Core Specification 4.2".
iBeacon is a kind of AD structures.
AD Type of iBeacon is 0xFF (which means Manufacturer Specific Data).
The first 4 bytes of AD Data of iBeacon are 0x4C, 0x00, 0x02 and 0x15. The first 2 bytes (0x4C, 0x00) mean "Apple, Inc." and the next 2 bytes (0x02, 0x15) mean "iBeacon format".
Proximity UUID (16 bytes), major number (2 bytes in big endian), minor number (2 bytes in big endian), and power (1 byte) follow the first 4 bytes.
So, what you have to do to get iBeacon information (Proximity UUID, major, minor, power) are as follows.
Parse a payload of an advertising packets as a list of AD structures.
For each AD structure, check if AD Type is 0xFF and the first 4 bytes of AD Data are 0x4C, 0x00, 0x02 and 0x15.
When the conditions of 2. are satisfied, parse the remaining bytes as Proximity UUID, major number, minor number, and power.
If you use nv-bluetooth, you can extract iBeacon from an advertising packet like the following:
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
{
// Parse the payload of the advertising packet.
List<ADStructure> structures =
ADPayloadParser.getInstance().parse(scanRecord);
// For each AD structure contained in the advertising packet.
for (ADStructure structure : structures)
{
if (structure instanceof IBeacon)
{
// iBeacon was found.
IBeacon iBeacon = (IBeacon)structure;
// Proximity UUID, major number, minor number and power.
UUID uuid = iBeacon.getUUID();
int major = iBeacon.getMajor();
int minor = iBeacon.getMinor();
int power = iBeacon.getPower();
........
See "iBeacon as a kind of AD structures" for details.
RadiusNetworks has "re-released" the libraries and examples in conjunction with a new cross platform beacon proximity spec.
New AltBeacon Standard Allows Cross-Platform Proximity Apps
Check out altbeacon.org.
I'm currently working on an app on Android which detects iBeacons using the API provided by Kontakt, to execute actions configured online in the Kontakt CMS.
However, to detect beacons, I am using the Radius Networks BLE libraries. I was unable to extract the UUID from the beacons, is this feature only available in the Pro Library? If it is available for the Open Source Library, how do I detect beacons with their UUID?
Region region = new Region("myRangingUniqueId", uUID, null, null);
Should be able to range for that to get a list of beacons matching that uuid from didRangeBeaconsInRegion callback.
Unless you just want to range for all beacons, then you can leave the proxUuid field null (wildcard) and then iterate through and get the proxIds with
iBeacons.iterator().next().getProximity()
Yes, you can do this with the open source Android iBeacon Library.
First, make sure your beacons are transmitting properly by verifying you can detect therm with the free iBeacon Locate app.
If this works, take a look at the "Ranging Example Code" here, which shows how to read the beacon ids.
EDIT: This library has been replaced by one with a the Android Beacon Library 2.0. The Ranging example is now available here.
I have been trying to write an application to detect iBeacons. (I set up my iPhone 5 as iBeacon)
I slightly changed the fromScanData method to return only proximity UUID String. I have no idea how the pattern detection works. It always Logs "This is not an iBeacon advertisement".
I am not using the whole IBeacon class. I am using the method alone. I am calling it from my
onLeScan and passing the byte array scanRecord, rssi value and the BluetoothDevice object.
Once I have my proximity UUID for each ble device, I can filter the ones I want.
Please help. Thanks in advance.
The Log
04-17 14:44:29.828: D/BLEScan(28549): This is not an iBeacon advertisment (no 0215 seen in bytes 4-7).The bytes I see are :02011a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The debug line says it all. Those bytes do not indicate a valid iBeacon advertisement. Are you sure your iPhone transmitter is really working properly? Can you detect the iBeacon using a different tool like the Android iBeacon Locate app?
I don't know how you set up the transmitter but you might also try Locate for iBeacon iOS app or EZ Beacon iOS app, which are known to transmit properly formed iBeacon advertisements that work with this code. The same Android code is inside the iBeacon Locate app.
Finally, make sure your iPhone transmitter is in the foreground. iOS devices cannot transmit as iBeacons in the background.