Reputation: 169
I'm working on an Android application that requires accurate orientation heading updates using the FusedOrientationProviderClient and a custom DeviceOrientationListener. However, I'm experiencing issues with orientation accuracy and incorrect heading values, especially when the device is flat on a surface.
When the device is not flat it's showing almost every time the right heading.
If the first value is not accurate,its not fixing itself to the right heading,its just keep updating the wrong heading.
Here's the class I am using for orientation updates:
class LocationOrientationRepo(context: Context) {
private var deviceOrientationListener: DeviceOrientationListenerImpl? = null
private val fusedOrientationProviderClient: FusedOrientationProviderClient =
LocationServices.getFusedOrientationProviderClient(context)
private val handler = Handler(Looper.getMainLooper())
private val refreshRunnable = object : Runnable {
override fun run() {
checkOrientationListener()
handler.postDelayed(this, REFRESH_INTERVAL_MS)
}
}
private var lastAzimuth: Float? = null
private val threshold = 0.0f // Set your threshold value (in degrees)
fun startListening(onOrientationChanged: (Float) -> Unit) {
if (deviceOrientationListener == null) {
deviceOrientationListener = DeviceOrientationListenerImpl { azimuth ->
if (shouldNotify(azimuth)) {
lastAzimuth = azimuth
onOrientationChanged(azimuth)
}
}
val request = DeviceOrientationRequest.Builder(DeviceOrientationRequest.OUTPUT_PERIOD_DEFAULT).build()
val executor: ExecutorService = Executors.newSingleThreadExecutor()
fusedOrientationProviderClient.requestOrientationUpdates(request, executor, deviceOrientationListener!!)
.addOnSuccessListener {
Log.i(TAG, "Successfully added new orientation listener")
handler.post(refreshRunnable)
}
.addOnFailureListener { e ->
Log.e(TAG, "Failed to add new orientation listener", e)
}
}
}
fun stopListening() {
if (deviceOrientationListener != null) {
Log.i(TAG, "Removing active orientation listener")
fusedOrientationProviderClient.removeOrientationUpdates(deviceOrientationListener!!)
deviceOrientationListener = null
handler.removeCallbacks(refreshRunnable)
}
}
private fun checkOrientationListener() {
if (deviceOrientationListener == null) {
Log.i(TAG, "Orientation listener not active. Restarting.")
startListening { azimuth ->
Log.d(TAG, "Orientation callback with azimuth: $azimuth")
}
}
}
private fun shouldNotify(newAzimuth: Float): Boolean {
// If lastAzimuth is null, initialize it
if (lastAzimuth == null) {
lastAzimuth = newAzimuth
return true
}
// Calculate the difference
val diff = Math.abs(newAzimuth - (lastAzimuth ?: newAzimuth))
return diff >= threshold
}
private inner class DeviceOrientationListenerImpl(private val onOrientationChanged: (Float) -> Unit) :
DeviceOrientationListener {
override fun onDeviceOrientationChanged(deviceOrientation: DeviceOrientation) {
val azimuth = deviceOrientation.headingDegrees
Log.d(TAG, "Device Orientation Changed - Heading: $azimuth") // Debug log for azimuth
onOrientationChanged(azimuth)
}
}
companion object {
private const val TAG = "LocationOrientationRepo"
private const val REFRESH_INTERVAL_MS = 10000L // 10 seconds
}
}
Issue:
The heading direction provided by DeviceOrientationListener is not always accurate. When the device is flat, the heading direction seems incorrect and does not update properly.
Using sensor events directly also yields inaccurate and erratic results, especially when rotating the device.
What I've Tried: I’ve tried using sensors events but they produce unstable and incorrect values when the device is rotated. Questions:
Any guidance or suggestions on how to fix these issues would be greatly appreciated. Thank you !
Upvotes: 0
Views: 39