@TargetApi(18)
  private void finishScanCycle() {
    if (android.os.Build.VERSION.SDK_INT < 18) {
      Log.w(TAG, "Not supported prior to API 18.");
      return;
    }
    if (IBeaconManager.LOG_DEBUG) Log.d(TAG, "Done with scan cycle");
    processExpiredMonitors();
    if (scanning == true) {
      processRangeData();
      // If we want to use simulated scanning data, do it here.  This is used for testing in an
      // emulator
      if (simulatedScanData != null) {
        // if simulatedScanData is provided, it will be seen every scan cycle.  *in addition* to
        // anything actually seen in the air
        // it will not be used if we are not in debug mode
        if (0 != (getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE)) {
          for (IBeacon iBeacon : simulatedScanData) {
            processIBeaconFromScan(iBeacon);
          }
        } else {
          Log.w(
              TAG,
              "Simulated scan data provided, but ignored because we are not running in debug mode.  Please remove simulated scan data for production.");
        }
      }
      if (getBluetoothAdapter() != null) {
        if (getBluetoothAdapter().isEnabled()) {
          getBluetoothAdapter().stopLeScan((BluetoothAdapter.LeScanCallback) getLeScanCallback());
          lastScanEndTime = new Date().getTime();
        } else {
          Log.w(TAG, "Bluetooth is disabled.  Cannot scan for iBeacons.");
        }
      }

      if (!anyRangingOrMonitoringRegionsActive()) {
        if (IBeaconManager.LOG_DEBUG)
          Log.d(TAG, "Not starting scan because no monitoring or ranging regions are defined.");
        scanCyclerStarted = false;
      } else {
        if (IBeaconManager.LOG_DEBUG)
          Log.d(
              TAG,
              "Restarting scan.  Unique beacons seen last cycle: "
                  + trackedBeacons.size()
                  + " Total iBeacon advertisement packets seen: "
                  + trackedBeaconsPacketCount);

        scanningPaused = true;
        nextScanStartTime = (new Date().getTime() + betweenScanPeriod);
        if (scanningEnabled) {
          scanLeDevice(true);
        } else {
          if (IBeaconManager.LOG_DEBUG)
            Log.d(TAG, "Scanning disabled.  No ranging or monitoring regions are active.");
          scanCyclerStarted = false;
        }
      }
    }
  }
 public void stopMonitoringBeaconsInRegion(Region region) {
   Log.d(TAG, "stopMonitoring called");
   monitoredRegionState.remove(region);
   Log.d(TAG, "Currently monitoring " + monitoredRegionState.size() + " regions.");
   if (scanning && rangedRegionState.size() == 0 && monitoredRegionState.size() == 0) {
     scanLeDevice(false);
   }
 }
 @Override
 public void onDestroy() {
   Log.i(TAG, "onDestory called.  stopping scanning");
   scanLeDevice(false);
   if (bluetoothAdapter != null) {
     bluetoothAdapter.stopLeScan(leScanCallback);
   }
 }
 /** methods for clients */
 public void startRangingBeaconsInRegion(Region region, Callback callback) {
   if (rangedRegionState.containsKey(region)) {
     Log.d(TAG, "Already ranging that region -- will replace existing region.");
     rangedRegionState.remove(
         region); // need to remove it, otherwise the old object will be retained because they are
     // .equal
   }
   rangedRegionState.put(region, new RangeState(callback));
   if (!scanning) {
     scanLeDevice(true);
   }
 }
 public void startMonitoringBeaconsInRegion(Region region, Callback callback) {
   Log.d(TAG, "startMonitoring called");
   if (monitoredRegionState.containsKey(region)) {
     Log.d(TAG, "Already monitoring that region -- will replace existing region monitor.");
     monitoredRegionState.remove(
         region); // need to remove it, otherwise the old object will be retained because they are
     // .equal
   }
   monitoredRegionState.put(region, new MonitorState(callback));
   Log.d(TAG, "Currently monitoring " + monitoredRegionState.size() + " regions.");
   if (!scanning) {
     scanLeDevice(true);
   }
 }
 @Override
 @TargetApi(18)
 public void onDestroy() {
   if (android.os.Build.VERSION.SDK_INT < 18) {
     Log.w(TAG, "Not supported prior to API 18.");
     return;
   }
   bluetoothCrashResolver.stop();
   Log.i(TAG, "onDestroy called.  stopping scanning");
   handler.removeCallbacksAndMessages(null);
   scanLeDevice(false);
   if (bluetoothAdapter != null) {
     bluetoothAdapter.stopLeScan((BluetoothAdapter.LeScanCallback) getLeScanCallback());
     lastScanEndTime = new Date().getTime();
   }
 }
  private void finishScanCycle() {
    Log.d(TAG, "Done with scan cycle");
    processExpiredMonitors();
    if (scanning == true) {
      if (!anyRangingOrMonitoringRegionsActive()) {
        Log.d(TAG, "Not starting scan because no monitoring or ranging regions are defined.");
      } else {
        processRangeData();
        Log.d(TAG, "Restarting scan.  Unique beacons seen last cycle: " + trackedBeacons.size());
        if (getBluetoothAdapter() != null) {
          if (getBluetoothAdapter().isEnabled()) {
            getBluetoothAdapter().stopLeScan(leScanCallback);
            lastScanEndTime = new Date().getTime();
          } else {
            Log.w(TAG, "Bluetooth is disabled.  Cannot scan for iBeacons.");
          }
        }

        scanningPaused = true;
        // If we want to use simulated scanning data, do it here.  This is used for testing in an
        // emulator
        if (simulatedScanData != null) {
          // if simulatedScanData is provided, it will be seen every scan cycle.  *in addition* to
          // anything actually seen in the air
          // it will not be used if we are not in debug mode
          if (0 != (getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE)) {
            for (IBeacon iBeacon : simulatedScanData) {
              processIBeaconFromScan(iBeacon);
            }
          } else {
            Log.w(
                TAG,
                "Simulated scan data provided, but ignored because we are not running in debug mode.  Please remove simulated scan data for production.");
          }
        }
        nextScanStartTime = (new Date().getTime() + betweenScanPeriod);
        scanLeDevice(true);
      }
    }
  }
 public void stopRangingBeaconsInRegion(Region region) {
   rangedRegionState.remove(region);
   if (scanning && rangedRegionState.size() == 0 && monitoredRegionState.size() == 0) {
     scanLeDevice(false);
   }
 }
 public void enableScanning() {
   scanningEnabled = true;
   if (!scanCyclerStarted) {
     scanLeDevice(true);
   }
 }