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)
Related
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.
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
}
I have two Android devices communicating using BLE. One is adverting while the other is scanning and receiving. When I advertise using a Service UUID, the other device will pick it up just fine. However, when I filter by Service UUID, the scanning device won't pick up the advertisement at all. Both devices are using the exact same UUID to advertise/scan. The scanning device is running 5.0.1. This is the code I have set up for the scanfilter:
P_UUID = new ParcelUuid(UUID.fromString("6be5ab1b-328b-4709-a737-84db596e10d2"));
B_scanFilter = new ScanFilter.Builder().setServiceUuid(P_UUID).build();
list = new ArrayList<ScanFilter>();
list.add(B_scanFilter);
On the advertising device, this is the code I have for the AdvertiseData:
//The random UUID is just a placeholder. Using P_UUID for both the serviceUUID and serviceDataUUID doesn't change anything
B_advertiseData = new AdvertiseData.Builder().addServiceUuid(P_UUID).addServiceData(new ParcelUuid(UUID.randomUUID()), getByteArray(data)).build();
And finally, here is the scanCallback and startScan code:
B_scanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Toast.makeText(getApplicationContext(),"Received Data", Toast.LENGTH_SHORT).show();
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
Toast.makeText(getApplicationContext(),"Received Data(Batch)", Toast.LENGTH_SHORT).show();
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Toast.makeText(getApplicationContext(),"Scan failed", Toast.LENGTH_SHORT).show();
Log.e(TAG, "Scan Error: " + Integer.toString(errorCode));
}
};
B_scanner.startScan(list, B_scanSettings, B_scanCallback);
Toast.makeText(getApplicationContext(),"Scan Started", Toast.LENGTH_SHORT).show();
Note that with B_scanCallback, none of the methods are called during scanning(even onScanFailed()).
Any help with this issue would be greatly appreciated! If you want me to post more of the code, I can do that. I only posted the code that I think could be causing this problem.
I'm trying to implement a BLE scan app where i want to list all the devices nearby in a single scan rather than getting one BLE device at a time.
I read from the Android Documentation that i can use setReportDelay() in the Scan Setting Builder to delay the scan results and to use the BatchScanResults() to get a batch/list of devices found.
However when i try to use the setReportDelay() in the Scan Settings builder the scan does not start at all and i get the following error.
04-13 16:03:19.887 8454-8454/com.example.sasnee_lab2.sasbeacon D/BluetoothLeScanner﹕ could not find callback wrapper
Here is my StartScan function with Scan Settings
public void startScan(BluetoothLeScanner scanner)
{
ScanFilter filter = new ScanFilter.Builder().setDeviceName(null).build();
ArrayList<ScanFilter> filters = new ArrayList<ScanFilter>();
filters.add(filter);
ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER).setReportDelay(1l)
.build();
Log.i(TAG,"The setting are "+settings.getReportDelayMillis());
scanner.startScan(filters,settings,BLEScan);
}
And here is the Scan Callback.
private ScanCallback BLEScan = new ScanCallback() {
#Override
public void onBatchScanResults(List<ScanResult> results) {
Log.i(TAG,"The batch result is "+results.size());
}
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i(TAG,"******************************************");
Log.i(TAG,"The scan result "+result);
Log.i(TAG,"------------------------------------------");
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
}
}
};
Please let me know if i'm doing anything wrong in the implementation here.
And thank you.
You must check whether your hardware supports scan batching through BluetoothAdapter.isOffloadedScanBatchingSupported(). If this returns false then you should not attempt to set a report delay.
Use this:
Java
boolean f = adapter.isOffloadedScanBatchingSupported();
if (!f) builder.setReportDelay(0) else builder.setReportDelay(1)
Kotlin
val f: Boolean = adapter.isOffloadedScanBatchingSupported
if (!f) builder.setReportDelay(0) else builder.setReportDelay(1)