I am working on Android beacon app with PiBeacon as a beacon device.
I have setup Respberry Pi As Beacon Device as given on adfruit website.
I can see that PiBeacon is transmitting by using other BLE Scanner application available on Play Store.
I have download the Altbeacon and configure my Android Studio Project according to given guide on Altbeacon Sample but the app is not showing the ble device. Can anyone help me what i am doing wrong ?
Following is the code that i am using for scanning PiBeacon.
public class MonitoringActivity extends Activity implements BeaconConsumer {
protected static final String TAG = "MonitoringActivity";
private BeaconManager beaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ranging);
beaconManager = BeaconManager.getInstanceForApplication(this);
// To detect proprietary beacons, you must add a line like below corresponding to your beacon
// type. Do a web search for "setBeaconLayout" to get the proper expression.
// beaconManager.getBeaconParsers().add(new BeaconParser().
// setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager.bind(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
#Override
public void onBeaconServiceConnect() {
beaconManager.setMonitorNotifier(new MonitorNotifier() {
#Override
public void didEnterRegion(Region region) {
Log.i(TAG, "I just saw an beacon for the first time!");
}
#Override
public void didExitRegion(Region region) {
Log.i(TAG, "I no longer see an beacon");
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
Log.i(TAG, "I have just switched from seeing/not seeing beacons: "+state);
}
});
try {
beaconManager.startMonitoringBeaconsInRegion(new Region("myMonitoringUniqueId", null, null, null));
} catch (RemoteException e) { }
}
}
The PiBeacon you reference sends and iBeacon transmission, but by default, the Android Beacon Library only detects open-source AltBeacon transmissions.
It's easy to detect other beacon types, but you need to add a new BeaconParser for the beacon type you are interested in. The instructions are right there in the comments of the code you posted:
To detect proprietary beacons, you must add a line like below corresponding to your beacon type. Do a web search for "setBeaconLayout" to get the proper expression.
Apologies, for the need to do this -- unfortunately intellectual property restrictions mean that we cannot include the expression in the library or post it on public forums like this. Fortunately, it is easy to find with a Google search.
Related
I'm working on a simple beacon proximity app using AltBeacon library from here https://altbeacon.github.io/android-beacon-library/samples.html.
I am experimenting with the sample code provided on the above website, however, each time I run the app it only goes to addRangingNotifier() method. If it detected the beacon it would go log the beacon size.
private Region defaultRegion = null;
defaultRegion = new Region("BeaconIdentifier", Identifier.fromUuid(java.util.UUID.fromString(UUID)), null, null);
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.bind(this);
#Override
public void onBeaconServiceConnect() {
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Log.d("MainInfo","Beacon List Size " + beacons.size());
}else{
Log.d("MainInfo","Beacon Empty");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(defaultRegion);
} catch (RemoteException e) {}
}
I can receive the beacon size around of me.
I test the two device(A : Samsung galaxy J510-Marshmellow/B: Samsung galaxy J7-Nougat), B scan the beacon and print Beacon List Size, but, A can't scan the beacon and print Beacon Empty.
So I test same Marshmellow device, but I can't find it.
Are there any codes that should be added depending on the operating system?
The most likely thing wrong is that the UUID specified does not match your beacon. Try replacing this code:
Identifier.fromUuid(java.util.UUID.fromString(UUID))
With
null
To match all beacons. If this fixes it, replace the UUID with the one you are out of the detected beacon.
Ì am trying to connect with beacons in my android app. But I can't seem to find my beacons. I am using Ibeacons. I am using the AltBeacon Library. The onBeaconServiceConnect starts and the didDetermineStateForRegion follows. But didEnterReion never gets called. This is my code:
public class ListScenarios extends AppCompatActivity implements BeaconConsumer, MonitorNotifier {
private static final String TAG = "ListScenarios";
private ListView listView;
public String persoonID;
public String adresID;
public Array beaconArray;
//private ArrayList<IBeacon> arrBeacons = new ArrayList<>();
private BeaconManager mBeaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_scenarios);
// Setup beaconmanager
mBeaconManager = BeaconManager.getInstanceForApplication(this.getApplicationContext());
// Detect iBeacon
mBeaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
mBeaconManager.bind(this);
//listview
listView = (ListView) findViewById(R.id.list_scenario);
//send request to load list
getScenarios();
getBeacons();
}
// MARK: - Bluetooth
#Override
public void onBeaconServiceConnect() {
System.out.println("We are in onBeaconServiceConnect");
// Set the two identifiers below to null to detect any beacon regardless of identifiers
Identifier myBeaconNamespaceId = null;
Identifier myBeaconInstanceId = null;
Region region = new Region("my-beacon-region", myBeaconNamespaceId, myBeaconInstanceId, null);
mBeaconManager.addMonitorNotifier(this);
try {
mBeaconManager.startMonitoringBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void didEnterRegion(Region region) {
System.out.println("We are in didEnterRegion");
Log.d(TAG, "I detected a beacon in the region with namespace id " + region.getId1() +
" and instance id: " + region.getId2());
}
public void didExitRegion(Region region) {
System.out.println("We are in didExitRegion");
}
public void didDetermineStateForRegion(int state, Region region) {
System.out.println("We are in didDetermineStateForRegion");
}
#Override
public void onPause() {
super.onPause();
mBeaconManager.unbind(this);
}
Two things to check:
Make sure you are using the correct BeaconParser expression. The expression shown in the question is for AltBeacon: "m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25. If you are trying to detect iBeacon, you'll need to use a different expression. This site has a handy reference: https://beaconlayout.wordpress.com/
If you are running your app on Android 6+ and are targeting SDK 23 or higher, you need to dynamically request location permission for your app. If you don't do this, you will get no detections, and you will see this in the logs: 04-22 22:35:20.152 5158 5254 E BluetoothUtils: Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results You can read how to do this here: http://altbeacon.github.io/android-beacon-library/requesting_permission.html
I'm working with the AltBeacon library (2.5.1) to detect beacons.
I setup ranging with an "universal" Region to be able to detect any beacon in range, then do my stuff with it.
The issue is that when I have several beacons in range, the didRangeBeaconsInRegion callback always provides me a Collection of only 1 beacon at a time and this beacon is a random one among all the present beacons... Why can't I get all the beacons in range in my Collection ?
All of this is made from within a Service, I did clean all the other stuff to keep only the relevant parts of the code below -> Hopefully I am doing something wrong here ?
public class MonitorService extends Service implements BeaconConsumer
{
private BeaconManager beaconManager;
#Override
public void onCreate()
{
super.onCreate();
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setForegroundScanPeriod(5000l);
beaconManager.setBackgroundScanPeriod(5000l);
beaconManager.setForegroundBetweenScanPeriod(1100l);
beaconManager.setBackgroundBetweenScanPeriod(1100l);
setupBeaconManager();
}
private void setupBeaconManager()
{
if (!beaconManager.isBound(this))
beaconManager.bind(this);
}
private void unsetBeaconManager()
{
if (beaconManager.isBound(this))
{
beaconManager.unbind(this);
try
{
beaconManager.stopRangingBeaconsInRegion(new Region("apr", null, null, null));
}
catch (RemoteException e)
{
Log.i(TAG, "RemoteException = "+e.toString());
}
}
}
#Override
public void onBeaconServiceConnect()
{
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region)
{
Log.i(TAG,"didRangeBeaconsInRegion, number of beacons detected = "+beacons.size());
// HERE IT IS : the size is Always 1, but the beacon (UUID etc. can be different)
}
});
try
{
beaconManager.startRangingBeaconsInRegion(new Region("apr", null, null, null));
}
catch (RemoteException e)
{
Log.i(TAG, "RemoteException = "+e.toString());
}
}
#Override
public void onDestroy()
{
unsetBeaconManager();
super.onDestroy();
}
}
I'm working on Android 5.1.1 with a Nexus 6 (but a Wiko cheap phone gives the same results). The beacons are setup to advertise every 600ms... But even with 100ms it also gives the exact same results...
The code looks OK. A couple of thoughts:
Try using an off the shelf beacon scanner app based on the same library like Locate. Does it detect all of your beacons simultaneously? If not, something may be wrong with the beacons or their configuration.
Do each of your beacons have unique identifiers? The library by default only detects multiple beacons if they have unique identifiers.
I´m using the Android IBeacon Library for a Project. I need to create a Service that starts ranging for beacons in the background and notify the user when it finds one (the nearest one). I have searched a lot and coded based on many examples I have found, but still it doesn´t work. Using logs I found that the IBeaconManager doesn't bind, so onIBeaconServiceConnect never gets called. I have already tried some solutions I found here but none of them has been useful. I would really appreciate if someone could help me solving this problem. I post some of my code here
public class RangingService extends Service implements IBeaconConsumer
{
private IBeaconManager beaconManager;
#Override
public void onCreate()
{
super.onCreate();
beaconManager = IBeaconManager.getInstanceForApplication(this);
Log.d("RangingService","Created beaconManager instance");
beaconManager.setBackgroundBetweenScanPeriod(120000);
beaconManager.setBackgroundScanPeriod(30000);
beaconManager.bind(this);
if(beaconManager.isBound(this))
{
Log.d("RangingService","Beacon manager bound");
}
else
{
Log.d("RangingService","Beacon manager not bound");
}
//Show the service has started
notify("RangingService created", "RangingService has started");
}
#Override
public void onDestroy()
{
super.onDestroy();
beaconManager.unBind(this);
}
#Override
public void onIBeaconServiceConnect()
{
Log.d("RangingService", "Entering onIBeaconServiceConnect");
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<IBeacon> beacons, Region region)
{
if(beacons.size() > 0)
{
IBeacon nearestBeacon = beacons.iterator().next();
for(IBeacon b : beacons)
{
if(nearestBeacon.getProximity() == IBeacon.PROXIMITY_UNKNOWN)
{
nearestBeacon = b;
}
else
{
if(b.getProximity() != IBeacon.PROXIMITY_UNKNOWN)
{
if(b.getAccuracy() < nearestBeacon.getAccuracy())
{
nearestBeacon = b;
}
}
}
}
Log.d("RangingService","Nearest Beacon Found "+nearestBeacon.getMajor()+";"+nearestBeacon.getMinor());
notify("Beacon read","Major: "+nearestBeacon.getMajor()+"; Minor: "+nearestBeacon.getMinor());
}
else
{
Log.d("RangingService","No beacons");
}
}
});
try
{
Log.d("RangingService", "Entering startRangingBeacons");
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
}
catch(RemoteException e)
{
notificar("Error", e.getMessage());
Log.e("RangingService", "Error while starting scanning: "+e.getMessage());
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d("RangingService", "Entering onBind");
return null;
}
The Service is already in my manifest also. Thanks for your help.
A couple of points:
The code indicates you are using a 0.x version of the Android iBeacon Library. If you are starting a new project, I would strongly recommend you use the Android Beacon Library 2.0, as the earlier library is no longer actively maintained, and it is now hard to find documentation for it.
Regardless of the library version you are using, you should be able to get a callback to the onBeaconServiceConnect() method after you bind to the BeaconManager. The fact that you don't get this callback probably indicates that the BeaconService is not starting up properly.
The most likely reason that the BeaconService is not starting up properly is because it is not properly declared in the manifest. If you are using Eclipse, you must edit your project.properties file and add the line: manifestmerger.enabled=true. If you are using AndroidStudio, this is not necessary. If you are using IntelliJ, you may have to declare the service manually.
You can verify if the manifest has the proper entries by looking at the generated manifest file in bin/AndroidManifest.xml, and verifying it has an entry for the BeaconService.
I had faced similar issues. Got resolved by doing following things
In eclipse project.properties added manifestmerger.enabled=true
restarted the eclipse
uninstalled other beacon apps in my android phone and restarted the phone
I'm trying to detect a Kontakt Beacon with the following BeaconLayout:
setBeaconLayout("m:8-9=0215,i:10-13,i:14-15,i:16-17,i:18-25"));
but I don't seem to be doing it correctly. The advertising packet structure is like this:
Thanks in advance.
Thanks to #davidgyoung comments, I finally could detect my Kontakt beacon with the following code:
public class MainActivity extends Activity implements BeaconConsumer {
protected static final String TAG = "RangingActivity";
BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager.bind(this);
}
#Override
public void onBeaconServiceConnect() {
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Log.d(TAG, "The first beacon I see is about "+beacons.iterator().next().getDistance()+" meters away.");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
} catch (RemoteException e) { }
}
Please note that I'm using a 2.2 version Kontakt beacon, which is a different version from the layout posted above.
A few issues with your beaconLayout:
The byte offsets in the beaconLayout string start with the manufacturer data (byte 6 in the table you show) so you need to subtract 6 from all of your offsets.
The table shows there are only three identifiers in the beacon, but your beaconLayout string has four. Note the first identifier is 16 bytes long.
If you get it working, please post the correct beaconLayout you used.