I have 2 phones with Android 5.0.2, they both installed the latest Radius Beacon\'s App: Locate Beacon, meanwhile, I turned on 2 IBeacon sender, and can see
David - Are you sure that scan callback gets called for every non-connectable advertisement. I have a Xiaomi Redmi 3 and another Nexus 5 phone running Android 6.0. I have a BLE sensor that at every 1 minute interval sends the data. These phones appearing as central BLE device should receive and process the data from the sensor. I can see from an Over the Air (OTA) BLE capture device that it the sensor is sending data every 1 minute. However both phones seems to process data for few minutes at 1 minute interval but after that stop processing for 4 - 6 minutes and then start processing agenter code here
ain.
Time interval of phone processing on looks like this
1 min, 2 min, 3 min, 8min, 9min, 10min, 11 min
So after processing 3 packets at 1 minute interval, either phone will stop processing for 4 -6 minutes.
Here is code that does the processing.
public class BluetoothDataReader {
private final Context context;
public BluetoothDataReader(Context context) {
this.context = context;
}
public void startReading() {
BluetoothAdapter btAdapter = getBluetoothAdapter();
if (btAdapter == null) return;
BluetoothLeScanner scanner = btAdapter.getBluetoothLeScanner();
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
scanner.startScan(Collections.emptyList(), settings, new ScanRecordReader());
}
public void uploadScanBytes(SensorDataUploader sensorDataUploader, int count) {
BluetoothAdapter btAdapter = getBluetoothAdapter();
if (btAdapter == null) return;
BluetoothLeScanner scanner = btAdapter.getBluetoothLeScanner();
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.build();
// scanner.startScan(Arrays.asList(new ScanFilter.Builder().setDeviceAddress("26:50:26:50:26:50").build()), settings, new LimitedScanRecordReader(sensorDataUploader, count, scanner));
scanner.startScan(Collections.emptyList(), settings, new LimitedScanRecordReader(sensorDataUploader, count, scanner));
}
@Nullable
private BluetoothAdapter getBluetoothAdapter() {
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
if(btAdapter == null){
Log.i(BluetoothDataReader.class.getName(), "No bluetooth adapter available");
return null;
}
if(!btAdapter.isEnabled()){
Log.i(BluetoothDataReader.class.getName(), "Enable bluetooth adapter");
Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(enableBluetooth);
}
return btAdapter;
}
private class LimitedScanRecordReader extends ScanCallback {
private final int limit;
private final BluetoothLeScanner scanner;
private int scanRecordRead = 0;
private final SensorDataUploader sensorDataUploader;
private LimitedScanRecordReader( SensorDataUploader sensorDataUploader, int limit, BluetoothLeScanner scanner) {
this.limit = limit;
this.scanner = scanner;
this.sensorDataUploader = sensorDataUploader;
}
@Override
public void onScanResult(int callbackType, ScanResult result) {
// if(scanRecordRead++ < limit) {
// if(result.getDevice().getAddress().equals("A0:E6:F8:01:02:03")) {
// if(result.getDevice().getAddress().equals("C0:97:27:2B:74:D5")) {
if(result.getDevice().getAddress().equals("A0:E6:F8:01:02:03")) {
long timestamp = System.currentTimeMillis() -
SystemClock.elapsedRealtime() +
result.getTimestampNanos() / 1000000;
byte[] rawBytes = result.getScanRecord().getBytes();
Log.i(DataTransferService.class.getName(), "Raw bytes: " + byteArrayToHex(rawBytes));
sensorDataUploader.upload(timestamp, rawBytes);
}
// }else {
// scanner.stopScan(this);
// }
}
public String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b & 0xff));
return sb.toString();
}
public void onScanFailed(int errorCode) {
Log.i(DataTransferService.class.getName(), "Error code is:" + errorCode);
}
public void onBatchScanResults(java.util.List results) {
Log.i(DataTransferService.class.getName(), "Batch scan results");
}
}
private class ScanRecordReader extends ScanCallback {
@Override
public void onScanResult(int callbackType, ScanResult result) {
byte []rawBytes = result.getScanRecord().getBytes();
Log.i(DataTransferService.class.getName(), "Raw bytes: " + byteArrayToHex(rawBytes ));
// Map serviceData = result.getScanRecord().getServiceData();
// for(ParcelUuid uuid : serviceData.keySet()) {
// Log.i(DataTransferService.class.getName(), uuid.toString() + ":" + byteArrayToHex(serviceData.get(uuid)));
// }
// Log.i(DataTransferService.class.getName(),result.toString());
}
public String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b & 0xff));
return sb.toString();
}
public void onScanFailed(int errorCode) {
Log.i(DataTransferService.class.getName(), "Error code is:" + errorCode);
}
public void onBatchScanResults(java.util.List results) {
Log.i(DataTransferService.class.getName(), "Batch scan results");
}
}
}