|
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