How to detect multiple beacons using Altbeacon android library? - android

I am using the AltBeacon sample app on my android device - the sample app provided by altbeacon.org is here: https://github.com/AltBeacon/android-beacon-library-reference
However, the app when launched is detecting and displaying only one beacon. I have about 5 beacons near my Android device. How do I detect all the beacons?
In RangingActivity.java, I noticed this method that is being called when a beacon comes in sight:
public void onBeaconServiceConnect() {
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
EditText editText = (EditText) RangingActivity.this.findViewById(R.id.rangingText);
Beacon firstBeacon = beacons.iterator().next();
logToDisplay("The first beacon " + firstBeacon.toString() + " is about " + firstBeacon.getDistance() + " meters away.");
}
}
}
I modified the iterator to read from the collection in a while loop as follows:
Beacon firstBeacon;
while(beacons.iterator().hasNext()){
firstBeacon = beacons.iterator().next();
logToDisplay("The first beacon " + firstBeacon.toString() + " is about " + firstBeacon.getDistance() + " meters away.");
}
However, the app crashes with this modification.
My questions:
(1) How can I display all beacons that are near my Android device?
(2) How can I detect beacons that go out of region?

For 1. I think you need to use a For loop. Like this.
for (Beacon beacon : beacons) {
logToDisplay("The beacon " + beacon.toString() + " is about " + beacon.getDistance() + " meters away.");
}
For 2. I was having trouble detecting that, but it might be a long timeout. So be very patient. I think the code in the Monitoring activity can be altered to display a message for that. Or you can review the logcat from a device.
A simple logToDisplay can be used inside the didExitRegion section of BeaconReferenceApplication.
public void didExitRegion(Region region) {
if (monitoringActivity != null) {
monitoringActivity.logToDisplay("I no longer see a beacon in the "+region.getUniqueId());
}
}

Related

AltBeacon Android Beacon Library region id is null

I'm using AltBeacon android library to detect Eddystone beacons on my app.
I'm setting the region like this:
Region region = new Region("backgroundRegion", null, null, null);
Whenever my app detects a beacon in range, I'm logging it like this:
#Override public void didEnterRegion(Region region) {
Log.v(TAG, "didEnterRegion() called with: region = [" + region.toString() + "]");
}
id1, id2 and id3 return null.
Instead, if I do this:
Region region = new Region("backgroundRegion", Identifier.parse("0x0b85497366bad1356d69"), null, null);
id1 returns `b85497366bad1356d69``
I want to detect all Eddystone devices. Can I get the device identifier if I do not set the region for that identifier?
The Ranging object in the callback for didEnterRegion is simply a copy of the one you used to start monitoring, so the identifiers will be all null if the initial Region has identifiers all null.
The solution? Use startRangingBeaconsInRegion() and the didRangeBeaconsInRegion callback. That callback will give you a list of detected beacons matching the region, so you can read all the actual identifiers.

How to increase the delay in the data of the region notifier?

I have using Android Beacon Library for one of my beacon solution .Is there a way put a delay in data produced by the range notifier because it is giving data very frequently .
Below is the code which I am referring to. To see complete code you can go to this thread "Android iBeacon App not working in the background"
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if(beacons.size() > 0) {
for (Beacon beacon : beacons) {
if (beacon.getDistance() < 1.0) {
Log.d(TAG, "I see a beacon transmitting a : " +
" approximately " + beacon.getDistance() + " meters away.");
Log.d(TAG, "BEACON DATA : " +beacon.getBluetoothAddress()+":"+beacon.getBluetoothName()+":"+beacon.getId1());
showNotification("Treewalker","You are near beacon range");
Intent intent = new Intent(this,MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
}
}
}
There are two methods which can help you
mBeaconManager.setBackgroundBetweenScanPeriod(10000);
mBeaconManager.setForegroundBetweenScanPeriod(10000);
Check official javadocs for details

Qt BLE For Android: Characteristic update does not trigger characteristicChanged signal

Here is the thing a device that we have transmits regular updates of a custom characteristic of a custom service. The service and characteristic in this device is defined via a XML file. This, of course, is referring to the Bluetooth BLE protocol.
What I'm trying to do is create a simple Qt Android App that connects to the device and monitors the update. I've gotten as far as discovering the service and connecting it signal to it. I've done that using this code:
void BLETest::on_stateChanged(QLowEnergyService::ServiceState state){
Q_UNUSED(state);
// Only printing data if all services are in correct state.
for (qint32 i = 0; i < monitoredServices.size(); i++){
if (monitoredServices.at(i)->state() != QLowEnergyService::ServiceDiscovered){
logger->out("There are still services that have not been discoverd",Logger::LC_ORANGE);
return;
}
}
QString msg = "PRINTING SERVICE DATA<br>";
for (qint32 i = 0; i < monitoredServices.size(); i++){
QLowEnergyService *monitoredService = monitoredServices.at(i);
QList<QLowEnergyCharacteristic> clist = monitoredService->characteristics();
msg = msg + "SERVICE: " + monitoredService->serviceName() + ". UUID: " + monitoredService->serviceUuid().toString() + "<br>";
// Checking if this is the service that need connection.
if (monitoredService->serviceUuid() == QBluetoothUuid(QString("0a464eef-af72-43fd-8a8b-1f26f6319dab"))){
QString res;
if (connect(monitoredService,SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)),this,SLOT(on_charastericChanged(QLowEnergyCharacteristic,QByteArray)))) res = "true";
else res = "false";
logger->out("CONNECTED TO TARGET SERVICE: " + res,Logger::LC_ORANGE);
}
for (int i = 0; i < clist.size(); i++){
QString name = clist.at(i).name();
if (name.isEmpty()) name = "UNDEFINED NAME";
QByteArray buffer = clist.at(i).value();
//QString value = QString(clist.at(i).value());
QString value = QByteArray(buffer.toHex()) + " (BS = " + QString::number(buffer.size()) + ")";
QString properties = QString::number(clist.at(i).properties());
msg = msg + "CHARACTERISTIC: " + clist.at(i).uuid().toString() + " - " + name + ": " + value + ". PROPERTIES: " + properties + "<br>";
}
if (clist.isEmpty()){
msg = msg + "No characteristics found<br>";
}
}
logger->out(msg);
}
The above functions waits for all services to be discovered then prints the UUID, name and Value for all characteristics of all services. When the service I want to monitored is processed a connection is done to the changedCharacteristic signal.
When I do this the printed value of the characteristic of the service I want to monitor is the original value for that characteristic. However as that value updates I'm not notified (the signal never triggers) and so the value never changes in my app.
Do I need to write some code to actually trigger the signals?
PD: Using the Blue Gecko Demo App I can see the values changing.
EDIT: I decided to use a timer to Poll the value of the characteristic and it never changes. Which might indicate why the signal is never generated either.
You should connect a chracteristic changed handler to the service:
connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(on_characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
In the slot you can explore the data array.
However, the signal (characteristicChanged()) will only emitted by the service if the for this chracteristic notification is enabled. This works only, if the characteritic has a notify property, that should the case in your application.

AltBeacon getDistance() showing values as infinity

I am using AltBeacon library to detect nearby beacons. The app works and is able to detect my beacons. However, it is not able to calculate distance - I am getting distance measurement value as "Infinity".
This is my code :
beaconManager.setForegroundScanPeriod(5100l);
beaconManager.setForegroundBetweenScanPeriod(11000l);
if (beacons.size() > 0) {
Log.i("Ranging", "inside detected : " + beacons.iterator().next().getDistance());
for (Beacon beacon : beacons) {
Log.i("RangingActivity", "Got rssi as : " + beacon.getRssi() + " and distance " + beacon.getDistance());
}
}
I get the following output in the log:
Got rssi as -53 and distance Infinity
What is going wrong in the distance measurement?

How to detect Region Enter/Exit for multiple beacons using AltBeacon android-beacon-library?

I am working with iBeacons and using the AltBeacon library.
beaconManager.getBeaconParsers()
.add(new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
I would like my Android app to detect and generate an event when beacons enter and exit visibility.
This works just fine fine with a single beacon using the library using methods.
public void **didEnterRegion**(Region region)
and
public void **didExitRegion**(Region region)
My problem is when multiple beacons are visible at the same time.
I am trying to maintain an array with all beacons visible.
I want to generate an event each time a beacon enters and exits.
The event should identify the beacon that generated the event by it's unique Identifier.
My beacons are uniquely identifiable using the beacon.getIdentifiers() or (UUID, Major and Minor)
The problem is that the didExitRegion method does not get executed until all beacons exit the region.
Can anyone think of a simple way for me to achieve my goals using AltBeacon library?
Any suggestions would be greatly appreciated.
Two options:
Set up a different region to match only each individual beacon, specifying all their identifiers, and monitor for each. You will get a different entry and exit callback for each region.
Region region1 = new Region("myIdentifier1", Identifier.parse("2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6"), Identifier.parse("1"), Identifier.parse("1"));
Region region2 = new Region("myIdentifier2", Identifier.parse("2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6"), Identifier.parse("1"), Identifier.parse("2"));
beaconManager.startMonitoringBeaconsInRegion(region1);
beaconManager.startMonitoringBeaconsInRegion(region2);
Enable ranging, and put code in the didRangeBeaconsInRegion callback to track individual beacons. You can use a java.util.HashMap to keep track of all beacons that are visible (with a timestamp for the latest time each was seen), and then if you haven't seen a beacon in, say, five seconds, you can remove the beacon from the HashMap and execute your exit logic for that beacon.
Option 1 is great for a small number of beacons where you know their identifiers up front. Option 2 is more involved, but better for a large number of beacons or if you do not know their identifiers in advance.
/***************This Code for estimote Beacons *****************/
private final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("beaconall", null, null, null);
private BeaconManager beaconManager;
public onCreate()
{
beaconManager.connect(new BeaconManager.ServiceReadyCallback()
{
#Override
public void onServiceReady()
{
Log.d("Lalit", "Beacon service Ready");
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
beaconManager.startMonitoring(ALL_ESTIMOTE_BEACONS_REGION);
}
});
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
int index = beacons.size();
// UUID uuid = UUID.fromString("");
if (beacons.size() > 0) {
Beacon SelectedBeacon = beacons.get(index-1);
Log.d("Lalit", "Beacon Id :- " + SelectedBeacon.getProximityUUID());
Log.d("Lalit", "Beacon major :- " + SelectedBeacon.getMajor());
Log.d("Lalit", "Beacon miner :- " + SelectedBeacon.getMinor());
Log.d("Lalit", "Beacon total :- " + beacons.size());
Log.d("Lalit","Distance :- "+ getDistance(SelectedBeacon.getRssi(),SelectedBeacon.getMeasuredPower()));
}
}
});
beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
#Override
public void onEnteredRegion(Region region, List<Beacon> list) {
Calendar calendar = Calendar.getInstance();
Date entertime = calendar.getTime();
Log.d("Lalit", "Region Enter :- " + entertime);
Log.d("List", "Region UUID id :- " + region.getProximityUUID());
}
#Override
public void onExitedRegion(Region region) {
Calendar calendar = Calendar.getInstance();
Date entertime = calendar.getTime();
Log.d("Lalit", "Region exit :- " + entertime);
Log.d("List", "Region UUID id :- " + region.getProximityUUID());
}
});
}

Categories

Resources