I'm using Alt beacon in my project to detect beacons, it is working perfectly on my Samsung s7 (Android 7) but on a Samsung s10, Oneplus 6 and Google Pixel 3 XL (Android 9/10) it doesn't work at all.
The code just doesn't seem to find any beacons.
My code starts with a permission check:
if (ContextCompat.checkSelfPermission(view, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Requesting Permission.")
openPermissionDialog()
} else {
startBeacon()
}
Then inside of my start beacon code bluetooth gets turned on and I create my beacon manager
val mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
if(mBluetoothAdapter != null){
if (!mBluetoothAdapter.isEnabled) {
mBluetoothAdapter.enable()
}
Log.d(TAG, "Permissions accepted, bluetooth is on.")
model.beaconManager = BeaconManager.getInstanceForApplication(view)
BeaconController.startBeacon(model.beaconManager, view)
}
Lastly inside of BeaconController I have a singleton companion object that will bind the beacon every 20 minutes. This is because when I find a beacon it will unbind.
class BeaconController {
companion object {
private val TAG = "HomePresenter"
private var hasTimerStarted = false
fun startBeacon(beaconManager: BeaconManager?, view: HomeActivityView) {
if (!hasTimerStarted) {
Log.d(TAG, "Timer starting")
hasTimerStarted = true
val handler = Handler()
Thread(object : Runnable {
override fun run() {
if (beaconManager?.isBound(view) != null) {
Log.d(TAG, "Beacon binding")
beaconManager.bind(view)
beaconManager.beaconParsers.clear()
beaconManager.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT))
} else {
Log.d(TAG, "Beacon is bound")
}
handler.postDelayed(this, 1200000) // 20 Minutes
}
}).start()
} else {
Log.d(TAG, "Timer already started.")
}
}
}
}
Once the beacon is bound I run some logic in my onBeaconServiceConnect to send an analytic when I find a beacon
override fun onBeaconServiceConnect() {
model.beaconManager?.addRangeNotifier { beacons, _ ->
if (beacons.isNotEmpty()) {
val firstBeacon = beacons.iterator().next()
val firstBeaconNameSpace = "${firstBeacon.id1}".replace("0x", "")
val firstBeaconIdentifier = "${firstBeacon.id2}".replace("0x", "")
Log.d(TAG, "Beacon $firstBeaconNameSpace - $firstBeaconIdentifier is " + firstBeacon.distance + " meters away.")
}
}
/**
* Attach
*/
try {
model.beaconManager?.startRangingBeaconsInRegion(Region("com.MYAPP.MYAPP", null, null, null))
Log.d(TAG, "Added Range Notifier")
} catch (e: RemoteException) {
Log.d(TAG, "Error adding Range Notifier")
e.printStackTrace()
}
}
The reason this wasn't working is because I was binding the beacon before actually adding the Beacon layout...
Before:
beaconManager?.bind(view)
beaconManager?.beaconParsers?.clear()
beaconManager?.beaconParsers?.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT))
After:
beaconManager?.beaconParsers?.clear()
beaconManager?.beaconParsers?.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT))
beaconManager?.bind(view)