if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Beacon beacon = new Beacon.Builder()
.setId1("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6") // UUID for beacon
.setId2("1") // Major for beacon
.setId3("5") // Minor for beacon
.setManufacturer(0x004C) // Radius Networks.0x0118 Change this for other beacon layouts//0x004C for iPhone
.setTxPower(-56) // Power in dB
.setDataFields(Arrays.asList(new Long[]{0l})) // Remove this for beacon layouts without d: fields
.build();
BeaconParser beaconParser = new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
BeaconTransmitter beaconTransmitter = new BeaconTransmitter(getApplicationContext(), beaconParser);
beaconTransmitter.startAdvertising(beacon, new AdvertiseCallback() {
#Override
public void onStartFailure(int errorCode) {
Log.e("tag", "Advertisement start failed with code: " + errorCode);
}
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.i("tag", "Advertisement start succeeded.");
}
});
}
catch(Exception o)
{
}
}
I am using AltBeacon Library to turn my phone to a beacon.I am getting in my adb logcat avdertisment start succeeded. However I want to detect other phones now that are acting as a beacon, how can I achieve that?
Detecting beacons with the Android Beacon Library is simple. See the Ranging Sample Code section on this page: http://altbeacon.github.io/android-beacon-library/samples.html
As the example code linked above show, you will get a callback approximately once per second with a list of all beacons visible over that time in a method that looks like this:
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
// The beacons collection contains all beacons detected in the past second
}
Related
I have implemented the following BLE scan callback,
private final ScanCallback mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.d(TAG,"onScanResult: " +result.toString());
runOnUiThread(() -> {
if (result.getDevice().getName() != null && getString(R.string.unknown_device_text).compareTo(result.getDevice().getName().toLowerCase()) != 0) {
mLeDeviceListAdapter.addDevice(result.getDevice());
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
super.onScanResult(callbackType, result);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
Log.d(TAG,"onBatchScanResults: " +results.toString());
super.onBatchScanResults(results);
}
#Override
public void onScanFailed(int errorCode) {
Log.d(TAG,"onScanFailed: errorCode: " +errorCode);
super.onScanFailed(errorCode);
}
};
However, in this callback I am not getting BLE devices that are advertising extended message. In contrast, in same place nRF app shows extended devices in their list.
Here is my scan method,
private void scanLeDevice() {
List<ScanFilter> filters = new ArrayList<>();
ScanFilter.Builder scanFilterBuilder = new ScanFilter.Builder();
filters.add(scanFilterBuilder.build());
ScanSettings.Builder settingsBuilder = new ScanSettings.Builder();
settingsBuilder.setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED);
final BluetoothLeScanner bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
bluetoothLeScanner.stopScan(mScanCallback);
Log.d(TAG, "scanLeDevice stopScan called");
}
}, SCAN_PERIOD);
bluetoothLeScanner.startScan(filters, settingsBuilder.build(), mScanCallback);
}
So, how can I filter and find the devices with extended advertising capabilities.
In order to show extended advertisements, you need to use the setLegacy(false) method. By default this is set to true, which is why you need to change it when setting up your scan settings.
Have a look at the links below for more information:-
ScanSettings.Builder setLegacy
How to scan Bluetooth 5 extended advertising with Pixel 3a
UPDATE
You can filter only BLE devices that are doing extended adverts by checking the advert type. You can access the advert type by reading the scanRecord (e.g. using the getBytes method). You can read further on how to read the advert type here and here. Legacy adverts will be one of the following 4 types:-
ADV_IND
ADV_DIRECT_IND
ADV_NONCONN_IND
ADV_SCAN_IND
While extended adverts will be one of the following 4 types:
ADV_EXT_IND
AUX_ADV_IND
AUX_SYNC_IND
AUX_CHAIN_IND
This can be see in more details in the table below:-
Below are some other useful links on understanding the meaning of advert packets:-
Bluetooth 5 adverts: Everything you need to know
How do iBeacons work
BLE advertising primer
I am using altbeacon library for detecting iBeacon. It shows all beacons on first scanning then some beacons are missing out.
This is my situation:
I have 7 beacons, on first scanning the app detecting all beacons.
If I again try to scan for beacons it shows only 4.
How can I fix this? I am adding my code below.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
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"));
backgroundPowerSaver = new BackgroundPowerSaver(this);
beaconManager.bind(this);
return START_STICKY;
}
#Override
public void onBeaconServiceConnect() {
RangeNotifier rangeNotifier = new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0)
{
Beacon firstBeacon = beacons.iterator().next();
String beaconID = String.valueOf(firstBeacon.getId3());
Log.v("beacons",""+beaconID);
}
}
};
try {
beaconManager.startRangingBeaconsInRegion(new Region("buuid", Identifier.parse(buuid), null, null));
beaconManager.addRangeNotifier(rangeNotifier);
}
catch (RemoteException e) { }
}
The code is currently printing out the third identifier of the first beacon seen:
if (beacons.size() > 0) {
Beacon firstBeacon = beacons.iterator().next();
String beaconID = String.valueOf(firstBeacon.getId3());
Log.v("beacons",""+beaconID);
}
It is NOT printing out a count of beacons seen. If you want it to print out the count of beacons seen, do this.
Log.v("beacon count", ""+beacons.count);
**EDIT: ** Also, understand that if you only look at the first beacon when there are multiple around, it may not behave consistently due to indeterminate ordering of the detections. You really need to see a list of all beacon ids detected, so use a loop like this:
Log.v("beacons", "Here are the beacons I see:");
for (Beacon beacon: beacons) {
String beaconID = String.valueOf(beacon.getId3());
Log.v("beacons","beacon id: "+beaconID);
}
The above will print a list like this:
Here are the beacons I see:
3
4
5
The order of identifiers may be different from one run to a next, but the list of the identifiers should generally be the same as long as all the beacons remain around.
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.
i want to transmit a beacon using android beacon library as an ibeacon.
i use the sample code from their site:
private void startIBeaconTransmit() {
Toast.makeText(context, "beacon transmission started", Toast.LENGTH_SHORT).show();
Beacon beacon = new Beacon.Builder()
.setId1("44918498-F5B3-4A21-AC3D-7CD9B4EA8BEB")
.setId2("1")
.setId3("2")
.setManufacturer(0x0000)
.setTxPower(-59)
.setDataFields(Arrays.asList(new Long[] {0l}))
.build();
BeaconParser beaconParser = new BeaconParser()
.setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
//.setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24");
beaconTransmitter = new BeaconTransmitter(getApplicationContext(), beaconParser);
beaconTransmitter.startAdvertising(beacon, new AdvertiseCallback() {
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.i("TAG", "onStartSuccess: ");
}
#Override
public void onStartFailure(int errorCode) {
Log.i("TAG", "onStartFailure: ");
}
});
}
i used different manufacturer codes and it didnt help
i scan with another phone with an app that i downloaded from the playstore, i see my beacon as altbeacon, how can i change it to an ibeacon?
thanks
You are very close!
Use the second beacon layout shown in the question (the one that is commented out) except change it to start with "m:2-3=0215
Then change the manufacturer code to use setManufacturer(0x004c)
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.