|
20 | 20 | import org.altbeacon.beacon.logging.LogManager;
|
21 | 21 | import org.altbeacon.beacon.startup.StartupBroadcastReceiver;
|
22 | 22 | import org.altbeacon.bluetooth.BluetoothCrashResolver;
|
23 |
| - |
24 | 23 | import java.util.Date;
|
25 | 24 |
|
26 | 25 | @TargetApi(18)
|
@@ -52,6 +51,7 @@ public abstract class CycledLeScanner {
|
52 | 51 | protected boolean mBackgroundFlag = false;
|
53 | 52 | protected boolean mRestartNeeded = false;
|
54 | 53 |
|
| 54 | + private boolean mDistinctPacketsDetectedPerScan = false; |
55 | 55 | private static final long ANDROID_N_MIN_SCAN_CYCLE_MILLIS = 6000l;
|
56 | 56 |
|
57 | 57 | protected CycledLeScanner(Context context, long scanPeriod, long betweenScanPeriod, boolean backgroundFlag, CycledLeScanCallback cycledLeScanCallback, BluetoothCrashResolver crashResolver) {
|
@@ -162,6 +162,14 @@ public void stop() {
|
162 | 162 | }
|
163 | 163 | }
|
164 | 164 |
|
| 165 | + public boolean getDistinctPacketsDetectedPerScan() { |
| 166 | + return mDistinctPacketsDetectedPerScan; |
| 167 | + } |
| 168 | + |
| 169 | + public void setDistinctPacketsDetectedPerScan(boolean detected) { |
| 170 | + mDistinctPacketsDetectedPerScan = detected; |
| 171 | + } |
| 172 | + |
165 | 173 | public void destroy() {
|
166 | 174 | mScanThread.quit();
|
167 | 175 | }
|
@@ -268,25 +276,39 @@ private void finishScanCycle() {
|
268 | 276 | if (mScanning) {
|
269 | 277 | if (getBluetoothAdapter() != null) {
|
270 | 278 | if (getBluetoothAdapter().isEnabled()) {
|
271 |
| - long now = SystemClock.elapsedRealtime(); |
272 |
| - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && |
273 |
| - mBetweenScanPeriod+mScanPeriod < ANDROID_N_MIN_SCAN_CYCLE_MILLIS && |
274 |
| - now-mLastScanCycleStartTime < ANDROID_N_MIN_SCAN_CYCLE_MILLIS) { |
275 |
| - // As of Android N, only 5 scans may be started in a 30 second period (6 |
276 |
| - // seconds per cycle) otherwise they are blocked. So we check here to see |
277 |
| - // if the scan period is 6 seconds or less, and if we last stopped scanning |
278 |
| - // fewer than 6 seconds ag and if so, we simply do not stop scanning |
279 |
| - LogManager.d(TAG, "Not stopping scan because this is Android N and we" + |
280 |
| - " keep scanning for a minimum of 6 seconds at a time. "+ |
281 |
| - "We will stop in "+(ANDROID_N_MIN_SCAN_CYCLE_MILLIS-(now-mLastScanCycleStartTime))+" millisconds."); |
| 279 | + // Determine if we need to restart scanning. Restarting scanning is only |
| 280 | + // needed on devices incapable of detecting multiple distinct BLE advertising |
| 281 | + // packets in a single cycle, typically older Android devices (e.g. Nexus 4) |
| 282 | + // On such devices, it is necessary to stop scanning and restart to detect |
| 283 | + // multiple beacon packets in the same scan, allowing collection of multiple |
| 284 | + // rssi measurements. Restarting however, causes brief detection dropouts |
| 285 | + // so it is best avoided. If we know the device has detected to distinct |
| 286 | + // packets in the same cycle, we will not restart scanning and just keep it |
| 287 | + // going. |
| 288 | + if (!getDistinctPacketsDetectedPerScan()) { |
| 289 | + long now = SystemClock.elapsedRealtime(); |
| 290 | + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && |
| 291 | + mBetweenScanPeriod+mScanPeriod < ANDROID_N_MIN_SCAN_CYCLE_MILLIS && |
| 292 | + now-mLastScanCycleStartTime < ANDROID_N_MIN_SCAN_CYCLE_MILLIS) { |
| 293 | + // As of Android N, only 5 scans may be started in a 30 second period (6 |
| 294 | + // seconds per cycle) otherwise they are blocked. So we check here to see |
| 295 | + // if the scan period is 6 seconds or less, and if we last stopped scanning |
| 296 | + // fewer than 6 seconds ag and if so, we simply do not stop scanning |
| 297 | + LogManager.d(TAG, "Not stopping scan because this is Android N and we" + |
| 298 | + " keep scanning for a minimum of 6 seconds at a time. "+ |
| 299 | + "We will stop in "+(ANDROID_N_MIN_SCAN_CYCLE_MILLIS-(now-mLastScanCycleStartTime))+" millisconds."); |
| 300 | + } |
| 301 | + else { |
| 302 | + try { |
| 303 | + LogManager.d(TAG, "stopping bluetooth le scan"); |
| 304 | + finishScan(); |
| 305 | + } catch (Exception e) { |
| 306 | + LogManager.w(e, TAG, "Internal Android exception scanning for beacons"); |
| 307 | + } |
| 308 | + } |
282 | 309 | }
|
283 | 310 | else {
|
284 |
| - try { |
285 |
| - LogManager.d(TAG, "stopping bluetooth le scan"); |
286 |
| - finishScan(); |
287 |
| - } catch (Exception e) { |
288 |
| - LogManager.w(e, TAG, "Internal Android exception scanning for beacons"); |
289 |
| - } |
| 311 | + LogManager.d(TAG, "Not stopping scanning. Device capable of multiple indistinct detections per scan."); |
290 | 312 | }
|
291 | 313 |
|
292 | 314 | mLastScanCycleEndTime = SystemClock.elapsedRealtime();
|
|
0 commit comments