I am using the Android beacon library with,
version -
compile 'org.altbeacon:android-beacon-library:2.15.1'
I am trying to develop one APK for transmitting multiple beacons from my mobile device.
I need to perform this to test or POC to test, how many beacons a reader can read at a time.
I am using the below code to transmit the BLE messages with Android Beacon Library.
btn_transmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (isBluetoothEnabled)
{
try
{
String customUuid = "";
for(int i=0;i<=50;i++)
{
if( i < 10){
customUuid = "99999999-b00"+i+"-4807-b747-9aee23508620";
} else if ( i < 999){
customUuid = "99999999-b0"+i+"-4807-b747-9aee23508620";
}
Thread.sleep(5000);
trasmitClick(customUuid);
beaconTransmitter = null;
}
}
catch(Exception e)
{
Toast.makeText(BeaconTransmitterActivity.this, "Something went wronggg", Toast.LENGTH_LONG).show();
}
}
else
Toast.makeText(BeaconTransmitterActivity.this, "Check your bluetooth connection", Toast.LENGTH_LONG).show();
}
});
Here above I am dynamically trying to create 50 new Id's to transmit the beacons.
Method to createBeacon and transmit its advertisements
public void trasmitClick(String customUuid) {
if (beaconTransmitter == null) {
String major, minor, uuid;
uuid = customUuid;
major = etMajorValue.getText().toString().trim();
minor = etMinorValue.getText().toString().trim();
if (TextUtils.isEmpty(uuid))
uuid = customUuid;
if (TextUtils.isEmpty(major))
major = "8";
if (TextUtils.isEmpty(minor))
minor = "2";
currentType=beaconLayout;
currentuuid=uuid;
currentmajorValue=major;
currentminorValue=minor;
beacon = new Beacon.Builder()
.setId1(uuid)
.setId2(major)
.setId3(minor)
//.setManufacturer(0x0118) // It is for AltBeacon. Change this for other beacon layouts
.setManufacturer(0x004C)
.setTxPower(-59)
//.setDataFields(Arrays.asList(new Long[]{6l, 7l})) // Remove this for beacon layouts without d: fields
.build();
// Change the layout below for other beacon types
beaconParser = new BeaconParser()
.setBeaconLayout(parserLayout[beaconLayout]);
beaconTransmitter = new BeaconTransmitter(getApplicationContext(), beaconParser);
beaconTransmitter.startAdvertising(beacon, new AdvertiseCallback() {
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
}
#Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
}
});
btn_transmit.setText("Stop Advertising");
btn_apply.setEnabled(false);
} else {
beaconTransmitter.startAdvertising();
beaconTransmitter = null;
btn_transmit.setText("Start Advertising");
btn_apply.setEnabled(false);
}
}
I am able to make this code work, but what is the result is I am able to transmit only 4 messages, the rest of the messages are not being visible in the simulator.
I am trying to find if the library has some limitations or I am wrong above.
Well I am novice in Android coding.
Below is the result that I can get in my simulator:
I would like to know how can I transmit 50 messages in one go.
This is most certainly a limitation of the Bluetooth chip on your mobile phone. Different device models have different advertising limits. The Huawei P9 Lite, for example can transmit only one advertisement at a time. The Nexus 5x can advertise 10 or more. It is unlikely that many phone models (if any) support 50 simultaneous advertisements.
There is no way to know the limit programmatically, as the OS provides no API to query this limit -- you just have to try. You can check when you get an error advertising by putting code in the onStartFailure callback.
You might also use the [BeaconScope]((https://play.google.com/store/apps/details?id=com.davidgyoungtech.beaconscanner) app to test this. But remember that transmission limits are device-wide. If one app is advertising a beacon, that takes one advertisement slot away from the next app. And no, there is no way to know if other apps are advertising.
Related
We are experimenting with a bunch of new tablets, and every one we tried is having issues with slow transfer rates with the RN4678 board. We currently use the Lenovo M10 FHD Plus. We tried a few such as the Teclast M40S, Nokia T20, and Samsung Galaxy Tab A8. The first two had horrible transfer rates, while the latter was okay but not ideal. We cannot use the Lenovo M10 Plus 3rd Gen because the buttons are too close to the corner to use with our tablet holders.
Here is my code:
public void SendMessage(BluetoothSocket socket, String msg) {
OutputStream outStream;
try {
outStream = BluetoothConnectionService.outputStream;
outStream.write("S".getBytes());
Thread.sleep(4000);
processThread = true;
mApp.running = true;
BluetoothSocketListener bsl = new BluetoothSocketListener(socket,
CollectingDetail.this);
Thread messageListener = new Thread(bsl);
messageListener.start();
timer = new CounterClass(remaingTime, 1000);
timer.start();
bt_stop.setText("Stop");
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(bluetoothReceiver, filter);
bluetoothReceiver.setRegistered(true);
} catch (IOException | InterruptedException e) {
Log.e("BLUETOOTH_COMMS", e.getMessage());
connectSocket();
}
}
public static class BluetoothSocketListener implements Runnable {
private final WeakReference<CollectingDetail> wrActivity;
private BluetoothSocket socket;
public BluetoothSocketListener(BluetoothSocket socket, CollectingDetail collectingDetail) {
this.socket = socket;
wrActivity = new WeakReference<CollectingDetail>(collectingDetail);
}
#Override
public void run() {
final CollectingDetail activity = wrActivity.get();
if (activity != null) {
activity.inStream = null;
if (!Thread.currentThread().isInterrupted()) {
int bufferSize = 512;
byte[] buffer = new byte[bufferSize];
Log.i("Bluetooth bytes", new String(buffer));
activity.inStream = BluetoothConnectionService.inputStream;
int availableBytes;
int bytesRead = -1;
String message = "";
while (activity.processThread) {
message = "";
try {
availableBytes = activity.inStream.available();
if (availableBytes > 0) {
bytesRead = activity.inStream.read(buffer);
if (bytesRead != -1 && bytesRead < bufferSize) {
message = new String(buffer, 0, bytesRead);
if (activity.mainHandler != null) {
activity.mainHandler.post(new MessagePoster(message, activity));
}
}
}
} catch (IOException e) {
Log.e("BLUETOOTH_COMMS", "Error reading bytes");
try {
socket.close();
} catch (IOException e1) {
Log.e("BLUETOOTH_COMMS", "Could not close socket");
}
activity.processThread = false;
}
}
}
}
}
}
public void seprateData(String message) {
try {
message = message.replaceAll("(\\r\\n|\\n|\\r)", ",");
String[] a = message.split(",");
boolean goodData = false;
for (int i = 0; i < a.length; i++) {
final String data = a[i];
if (data.length() > 0 && !data.equals(" ")) {
if (data.length() >= 10 && data.startsWith("5A")) {
al_sepratedMessageList.add(data);
goodData = true;
}
}
}
if (goodData) {
calculation();
if (ConnectThrough.equalsIgnoreCase("usb")) {
UsbConnectionSerivce.sendMessage("K");
} else {
BluetoothConnectionService.sendMessage(socket, "K");
}
}
} catch (Exception e) {
Log.e("BiSym", "Error Parsing BiSym Data");
}
}
Is there any way we can increase the transfer rate without changing the firmware? It appears others have faced similar problems, but none of the answers have a real solution. Could you please help me out. Thanks.
I fear this may not be software-solvable and may be an issue with BT hardware or firmware. How would I communicate with my boss about this?
I fear this may not be software-solvable and may be an issue with BT hardware or firmware. How would I communicate with my boss about this?
The difference is in the quality of the filtering of the signal, a better filter, narrower bandwidth, means lower Signal to Noise Ratio. Lower SNR means faster transfer.
Better analog filters, mean more components and slightly more cost and loss, however, due to the wide-band nature of Bluetooth, most analog filters can only filter out of band signals (nearby AM/FM/TV broadcasters).
In addition to the analog filters, digital filters are applied to the signal to narrow the bandwidth within the band, this technique incurs little loss, but requires more processing power to be included in the chip, more transistors, more costs.
The order of the filter and the type FIR or IIR determine the characteristics of the filer.
Most designers will minimize the cost to meet the minimum specifications, some will balance the cost versus performance and go further, you never know.
You tell your boss, the the better platforms perform digital filtering well beyond what the Bluetooth specification requires.
I just tested the Teclast M40 Plus which doesn't have this problem.
Something wants to make me believe it is an issue with the UNISOC Bluetooth stack. The Teclast M40 Plus has MediaTek which doesn't have this issue.
EDIT: Also tested on Lenovo M10 Plus 3rd Gen with MediaTek Helio G80, no issue. If we have to use it, we may need a new tablet holder.
Have you repeated the tests? Bluetooth uses the same frequencies as 2.4 GHz Wifi and microwave ovens. In a congested Wifi environment, and/or too many Bluetooth connections(mice, keyboards, headphones, speakers, watches ...), slowdowns are normal for high-speed transfers.
Wifi 6 MIMO utilizes all three distinct channels in the 2.4G band, (1,6,11) of the 12 overlapping. Higher bandwidth/speeds are available in 5.4G (and above), but wall penetration and signal propagation factors keep 2.4G as the primary band in the absence of other possibilities.
There is only so much space in the 2.4G band that Bluetooth operates.
Repeat your tests in an area without interference and see if you get the same results.
A cheap isolation method is to build a Faraday Cage out of .25 inch chicken wire fencing. Isolate the sender and receiver inside of the cage and measure the throughput.
In an uncontrolled environment, hundreds to thousands of tests for each device are required across different time spans to establish a true baseline measurement. You never know when you neighbor is going to start or stop a variable bit-rate video, or move a mouse.Every action contributes to the background noise in the band.
I am new to Android Bluetooth LE and wearables and trying to develop an app to get heart rate from wearables. I am using a Mi Band 3 and following Google’s docs to get heart rate from nearby BLE device(Mi Band 3). I am unable to discover the device. I am using the following code as a reference.
callback = new BleScanCallback() {
#Override
public void onDeviceFound(BleDevice device) {
// ClaimBleDeviceRequest request = new ClaimBleDeviceRequest(mClient,device);
PendingResult<Status> pendingResult =
Fitness.BleApi.claimBleDevice(mClient, device);
}
#Override
public void onScanStopped() {
// ..
}
};
StartBleScanRequest request = new StartBleScanRequest.Builder()
.setDataTypes(DataType.TYPE_HEART_RATE_BPM)
.setBleScanCallback(callback)
.build();
PendingResult<Status> pendingResult =
Fitness.BleApi.startBleScan(mClient, request);
Have you tried regular BLE api?
https://developer.android.com/guide/topics/connectivity/bluetooth-le
If the device is not discovered with the regular BLE api, but its discovered by the
companion device, then you might try regular Bluetooth API - the LE might not be supported by device.
[### Expected behavior
That the lib should only fire exit when beacon has actually exited the region.
Actual behavior
The lib fires exit and enter region methods where the beacon is still in range. And this happens 20 sec apart some time more frequent some times less frequent on all android versions from 5-7
Steps to reproduce this behavior
I am running the beacon app continuously in the background as soon as the bluetooth gets turned
ON to search the beacon ,the beacon is fixed inside a car and is broadcasting at 1000s interval i have to start a ride when ever a user gets in the range and stop the ride when ever it gets out of it but the issue is that itt reports beacon Entered and Exited continuously where the user never left the beacon zone.
My code snippet
public class BackgroundBeaconScan extends Service implements BootstrapNotifier, BeaconConsumer {
#Override
public void onCreate() {
super.onCreate();
AppUtils.isBGServiceActive = true;
//AppUtils.appTerminated = false;
Log.e("Beacon", "Service Start");
Log.e("Bfpk", " *** Beacon Service is started *** ");
LoggingOperations logger = new LoggingOperations();
Thread.setDefaultUncaughtExceptionHandler(logger);
mBeaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
try {
Log.e("BG", "iam in mBeaconManager to unbind it");
mBeaconManager.unbind(this);
mBeaconManager.removeAllRangeNotifiers();
mBeaconManager.removeAllMonitorNotifiers();
mBeaconManager.removeMonitoreNotifier(this);
} catch (OutOfMemoryError e) {
Log.e("BG", "iam in mBeaconManager to unbind it excep ");
}
mBeaconManager.getBeaconParsers().clear();
//set Beacon Layout for Eddystone-UID packet
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT));
// rideBDD = new RideBDD(getApplicationContext());
mBeaconManager.setForegroundScanPeriod(20001);
mBeaconManager.setForegroundBetweenScanPeriod(50001);
mBeaconManager.setBackgroundScanPeriod(20001);
mBeaconManager.setBackgroundBetweenScanPeriod(50001);
mBeaconManager.setBackgroundMode(true);
mBeaconManager.setDebug(true);
BeaconManager.setAndroidLScanningDisabled(true);
notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
namespace = DataHandler.getStringPreferences(AppConstants.UUID_NAME_SPACE);
instanceID = DataHandler.getStringPreferences(AppConstants.UUID_INSTANCE_ID);
Log.e("BG", "namespace :" + namespace);
Log.e("BG", "instanceID :" + instanceID);
Long currentTime = System.currentTimeMillis();
String time = formateLongToOnlyDateForServer(currentTime);
LoggingOperations.writeToFile(BackgroundBeaconScan.this,"UUID > " + time + " -- > " + namespace + " - " + instanceID);
try {
Log.e("BG", "iam in mBeaconManager.isBound");
mBeaconManager.bind(this);
Log.e("BG", "iam in mBeaconManager.bind");
} catch (OutOfMemoryError e) {
Log.e("BG", "iam in mBeaconManager.bindexce", e);
}
}
My service connect
#Override
public void onBeaconServiceConnect() {
// String preiBeaconUUID = DataHandler.getStringPreferences(AppConstants.UUID);
// postiBeaconUUID=AppUtils.addDashes(preiBeaconUUID);
Region region;
try {
Log.e("BG", "iam in onBeaconServiceConnect");
namespace = DataHandler.getStringPreferences(AppConstants.UUID_NAME_SPACE);
instanceID = DataHandler.getStringPreferences(AppConstants.UUID_INSTANCE_ID);
Identifier myBeaconNamespaceId = Identifier.parse(namespace);
Identifier myBeaconInstanceId = Identifier.parse(instanceID);
region = new Region("EdstUIDAdvertising", myBeaconNamespaceId, myBeaconInstanceId, null);
mBeaconManager.addMonitorNotifier(this);
Log.e("BG", "iam in startMonitoringBeaconsInRegion");
} catch (Exception e) {
Log.e("BG", "iam in startMonitoringBeaconsInRegionExce" + e);
e.printStackTrace();
namespace = DataHandler.getStringPreferences(AppConstants.UUID_NAME_SPACE);
instanceID = DataHandler.getStringPreferences(AppConstants.UUID_INSTANCE_ID);
Identifier myBeaconNamespaceId = Identifier.parse(namespace);
/* Identifier myBeaconInstanceId = Identifier.parse(instanceID);*/
region = new Region("EdstUIDAdvertising", myBeaconNamespaceId, null, null);
mBeaconManager.addMonitorNotifier(this);
Log.e("BG", "iam in startMonitoringBeaconsInRegion");
}
AppUtils.isBGServiceActive = true;
try {
mBeaconManager.startMonitoringBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
mBeaconManager.addMonitorNotifier(new MonitorNotifier() {
#Override
public void didEnterRegion(Region region) {
Log.e("Monitored", "entered"); this fires at the same time
enterCount++;
}
#Override
public void didExitRegion(Region region) {
Log.e("Monitored", "exited"); // this fires at the same time
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
});
}
The
Mobile device model and OS version
Samsung note 5 (7.0) s6 (6.0) s5 (5.0) every device
Android Beacon Library version
2.12.4 // please help i am facing this issue for quiet a long time now
This is a common problem caused by intermittent detection of beacons. Understand that the library only knows when a beacon disappears (exits the region) when it hasn't been detected in a long time. The library fires region exit event if a previously seen beacon is not seen for at least 10 seconds when the scan period ends.
Recommendations:
Increase your beacon transmission rate to 10 Hz or more.
If you cannot do (1), lengthen the scanPeriod to be longer until the problem goes away.
The problem you are experiencing is likely exacerbated by the custom scanning periods set in the example code, which shows a scanPeriod of 5 seconds followed by a betweenScanPeriod of 20 seconds. If a beacon in the vicinity fails to be detected during the 5 second scanPeriod.
It's unclear why your beacons are not being detected sometimes during a 5 seconds scan you have configured. It may be that they only transmit infrequently. Some beacons send out an advertising packet only every 5 seconds or so to save battery. If this is the case, it would certainly cause the problem you describe. Even if they were set up to transmit once per second, it is sometimes possible that 5 packets in a row could be missed due to radio noise.
If you use the library's default settings it is less likely to happen because scanning is performed constantly in the foreground (making it much more likely that the beacon will be detected before an exit fires) and for 10 seconds in the background. If you cannot or do not want to increase the advertising rate of your beacons, I recommend adjusting your scanPeriod / betweenScanPeriod settings to be longer than 5 seconds every 30 seconds.
For proper operation of the library, the scan period must be at least 5x the beacon transmission period. This is because not all bluetooth packets get received due to radio noise. Having an interval that is 5x the transmission period means that there are 5 chances to receive a packet on each background scan cycle, making it very unlikely the library will miss one
I'm trying to connect to an Arduino Uno via an android app using Bluetooth Low Energy (BLE).
I'm developing on Android Studio, testing with a Samsung Galaxy S4, and with an Android version 5.0.1
I followed this link: http://www.truiton.com/2015/04/android-bluetooth-low-energy-ble-example/
I'm scanning devices and when I found one, I would like to get it's UUID before connecting to it, to make sure that it's the right type of device:
mScanCallback = new ScanCallback() {
#Override
#TargetApi(21)
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice btDevice = result.getDevice();
ParcelUuid[] uuids = btDevice.getUuids(); //<-- this is always null!! :(
Log.d(TAG, ""+btDevice.fetchUuidsWithSdp()); //<-- prints true.
Log.d(TAG, "result : " + result.toString()); //<-- prints a bunch of relevant info that contains the UUID I want to check.
Log.d(TAG, "uuids : " + uuids); //<-- prints null.
/*
for (ParcelUuid u : uuids) {
//Compare with the UUID of my device, and connect if ok.
}
*/
}
However, btDevice.getUuids(); is always returning null with no error...
How can I get the UUID of the scanned device?
A brute force method would be to use regexp with the result.toString() to grab what I want but there must be a better way isn't it?
Thanks
BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
// scan for devices
scanner.startScan(new ScanCallback() {
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onScanResult(int callbackType, ScanResult result)
{
List<ParcelUuid> uuids = result.getScanRecord().getServiceUuids();
}
}
this is worked for me in Android 6.0.1
After hours of searching I find out that getUuid() is not the way to go if you want to retrieve the uuid of an iBeacon.
If that is the case, you need to get it directly from the Scan result result object.
I managed to work by using the answer provided by ADEBAYO OSIPITAN.
BLE obtain uuid encoded in advertising packet
Here is his code snipet:
//For APIs greater than 21, Returns Device UUID
public String getUUID(ScanResult result){
String UUIDx = UUID
.nameUUIDFromBytes(result.getScanRecord().getBytes()).toString();
return UUIDx;
}
From Java DOC:
public ParcelUuid[] getUuids ()
Added in API level 15
Returns the supported features (UUIDs) of the remote device.
This method does not start a service discovery procedure to retrieve the UUIDs from the remote device. Instead, the local cached copy of the service UUIDs are returned.
Use fetchUuidsWithSdp() if fresh UUIDs are desired.
Requires BLUETOOTH.
Returns
the supported features (UUIDs) of the remote device, or null on error
Your ScanResult probably is a error
I'm a french student in ingineering and I am learning Android language by myself. My friends and I have to create an Android app which is based on iBeacon technology. I discovered the AltBeacon library few days ago and I found it awesome but I have some questions to ask on it.
Firstly, you must understand I am a novice in programming, and my questions will be idiots for you. But please I really need help ;)
Android provides a Bluetooth.LE Api and I understood that I can use the method startLeScan() to get a BluetoothDevice.
But if I want to use the AltBeacon library which is the equivalent method who allow us to scan iBeacon devices and get an Beacon object?
Another question, If I use startLeScan() and get a BluetoothDevice, how can I transform it into Beacon in order to use AltBeacon methods ?
I am sorry for my english mistakes, I hope my questions will be understandable. Bye
This is what we use to detect iBeacons and get a beacon object in a Android service using the AltBeacon lib.
Setup the BeaconManager
BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.setForegroundScanPeriod(5100);
beaconManager.setForegroundBetweenScanPeriod(2000);
beaconManager.setBackgroundScanPeriod(5100);
beaconManager.setBackgroundBetweenScanPeriod(2000);
//Parse IBeacon structure
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);
Start Ranging the beacons
private void startBeaconRangeFinderService() {
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, org.altbeacon.beacon.Region region) {
try {
if (beacons.size() > 0) {
for (Beacon b : beacons) {
processYourBeaconInThisMethod(b);
}
}
} catch (Exception ex) {
Log.e(TAG_BEACON_ACTIVITY, "Error was thrown: " + ex.getMessage());
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
} catch (RemoteException e) {
Log.e(TAG_BEACON_ACTIVITY, "Error was thrown: " + e.getMessage());
}
}
You can easily use the Android Beacon Library to scan for beacons and return results using the "Ranging APIs" as described here:
http://altbeacon.github.io/android-beacon-library/samples.html
If you want to directly call startLeScan() and use library code to convert the results to beacon objects, you can call the following method in the scan callback:
Beacon beacon = beaconParser.fromScanData(scanData, rssi, bluetoothDevice)
However, if using a proprietary beacon format (like from from Apple), you will need to construct a BeaconParser with the proper layout. This is proprietary info, but you can do a Google search to find out the proper way to construct a
BeaconParser for proprietary layouts.
I think nv-bluetooth is the easiest way to extract iBeacon from advertising packets. Below is a sample implementation of onLeScan method.
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.