1

I'm using the AltBeacon library for detecting iBeacons in my Android app. The code I have works on the following devices:

  • Xiaomi MI9 (Android 10.0)
  • Motorola Moto G4 (Android 6.0.1)
  • Huawei P Smart (Android 8.0)
  • Samsung Galaxy S8 (Android 9.0)

However, the same code doesn't work for a OnePlus 6 (Android 10, OxygenOS 10.3.2). It doesn't detect any beacons in my app. I tried to detect the beacons using an other app (Locate), that works. The creator of the AltBeacon library told me that Locate uses the AltBeacon library, so the beacons are detectable. This means my code setup is wrong. Can you help me by finding out what is wrong with my setup?

I checked (e.g.) this answer, although it didn't fix my problem. I turned debugging on for the BeaconManager but nothing interesting came out of that (an example at the bottom of this question).

In the ViewModel I call the MyStateManager. It contains a List regionsInRange, which contains beacons that are in range. I left out some code because I think it is irrelevant. If you feel like I left out too much, I will add it.

public class MyStateManager implements BootstrapNotifier {

  private static final MyStateManager instance = new MyStateManager();

  private final MyBeaconHelper myBeaconHelper;

  // ViewModel accessess this List to retrieve the beacons that are found.
  public final List<Region> regionsInRange = new ArrayList<>();

  private PresenceRegistrationStateManager() {
      presenceRegistrationBeaconHelper = new PresenceRegistrationBeaconHelper(this);
      updateScanningRegions();
  }

  @Override
  public Context getApplicationContext() {
      return MyApplication.getAppContext();
  }

  @Override
  public void didEnterRegion(Region region) {
      //Empty method
  }

  @Override
  public void didExitRegion(Region region) {
      //Empty method
  }

  @Override
  public void didDetermineStateForRegion(int status, Region region) {
      if (status == OUTSIDE) {
          regionsInRange.remove(region);
      } else {
          if (!regionsInRange.contains(region)) {
              regionsInRange.add(region);
          }
      }
      updateState();
  }

  public static MyStateManager getInstance() {
      return instance;
  }

  public void updateState() {
    // Own implementation here
  } 

  private void updateScanningRegions() {
    // add all the regions here
  }
}

In addition, this is the MyBeaconHelper:

public class MyBeaconHelper implements BeaconConsumer, Serializable {

  private transient final RegionBootstrap regionBootstrap;

  private List<Region> scanRegions = new ArrayList<>();

  public MyBeaconHelper(BootstrapNotifier bootstrapNotifier) {
      BeaconManager beaconManager = BeaconManager.getInstanceForApplication(getApplicationContext());
    
      beaconManager.getBeaconParsers().clear();
      beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
      LogManager.setVerboseLoggingEnabled(true);
      beaconManager.bind(this);

      regionBootstrap = new RegionBootstrap(bootstrapNotifier, new ArrayList<>());
  }

  @Override
  public void onBeaconServiceConnect() {
      //Empty method
  }

  @Override
  public Context getApplicationContext() {
      return MyApplication.getAppContext();
  }

  @Override
  public void unbindService(ServiceConnection serviceConnection) {
      getApplicationContext().unbindService(serviceConnection);
  }

  @Override
  public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) {
      return getApplicationContext().bindService(intent, serviceConnection, i);
  }

  public void updateScanRegions(List<Region> newRegions) {
      for (Region oldRegion : this.scanRegions) {
          if (!newRegions.contains(oldRegion)) {
              regionBootstrap.removeRegion(oldRegion);
          }
      }
      for (Region newRegion : newRegions) {
          if (!this.scanRegions.contains(newRegion)) {
              regionBootstrap.addRegion(newRegion);
          }
      }
      this.scanRegions = newRegions;
  }
}

When I turned debugging on for the BeaconManager, it showed me this a lot of times:

2020-03-31 11:57:30.181 25259-25259/com.my.app D/CycledLeScanner: starting a new scan cycle

2020-03-31 11:57:30.181 25259-25259/com.my.app D/CycledLeScanner: We are already scanning and have been for 1134 millis

2020-03-31 11:57:30.181 25259-25259/com.my.app D/CycledLeScanner: Waiting to stop scan cycle for another 1100 milliseconds

2020-03-31 11:57:30.181 25259-25259/com.my.app D/CycledLeScanner: Scan started

2020-03-31 11:57:31.213 25259-25259/com.my.app D/CycledLeScanner: Waiting to stop scan cycle for another 69 milliseconds

2020-03-31 11:57:31.323 25259-25259/com.my.app D/CycledLeScanner: Done with scan cycle

It keeps printing these lines over and over again...

Community
  • 1
  • 1
476rick
  • 2,764
  • 4
  • 29
  • 49

1 Answers1

1

The log messages shown (these are for OnePlus, yes?) indicate that BLE scanning is started. Do you see any log lines showing hex bytes of the packets detected? If BLE scanning is actually functioning you should. You may want to compare the logs output by the other devices.

Are you certain proper location permission has been granted to your app on the OnePlus? You can check in Settings -> Apps - > You App -> Permissions. Also confirm Bluetooth is on and location is on for the global phone settings (but if Locate works on the same device, this should not be a problem .)

It is not clear if this is related, but the use of beaconManager.bind() at the same time as RegionBootstrap is unnecessary and may cause conflicts. The code appears to not use the BeaconConsumer interface that is called back by the bind method. I suggest you remove the bind call, the use of BeaconConsumer and remove all that interface's callback methods just to be sure.

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • the log messages are from the OnePlus indeed. I was going to try your suggestions but wanted to check with the Locate app one more time. To see if I could still find the beacons with the Locate app. I don't know why, but out of the blue it doesn't find the beacons anymore. However, I did not change anything to the beacons... So maybe it is more an issue of my OP. I tried restarting the device and app multiple times. Do you have any idea? – 476rick Apr 10 '20 at 15:00
  • A few things to check: (1) Go to settings bluetooth and try to use the built-in bluetooth settings to pair with a speaker. If that doesn't work, you have a hardware problem. (2) Verify global device settings to ensure Location is on and Bluetooth is on. (3) Verify app-specific permissions (see my answer above on how to find this) to verify location permission is granted to each app. – davidgyoung Apr 10 '20 at 17:57
  • I found the problem, I watched for BLE as you tole me to. I noticed the line that the Bluetooth scanner did not have the ACCESS_FINE_LOCATION permission, but I was sure I asked for it. So I checked and asked for the ACCESS_COARSE_LOCATION and in the onRequestPermissionsResult I checked the ACCESS_FINE_LOCATION... After fixing that, the code worked... Thank you for your help, I really appreciate it! – 476rick Apr 11 '20 at 09:33