Skip to content

feat: add support for heading in addWatch#10

Open
ItsChaceD wants to merge 4 commits intomainfrom
feat/RMET-4897/heading-support
Open

feat: add support for heading in addWatch#10
ItsChaceD wants to merge 4 commits intomainfrom
feat/RMET-4897/heading-support

Conversation

@ItsChaceD
Copy link

@ItsChaceD ItsChaceD commented Feb 2, 2026

Description

This PR adds support for heading, magneticHeading, trueHeading, headingAccuracy, and course

Context

https://outsystemsrd.atlassian.net/browse/RMET-4897

Type of changes

  • Fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Refactor (cosmetic changes)
  • Breaking change (change that would cause existing functionality to not work as expected)

Tests

Tested on Pixel 8 Pro with Capacitor example app, ODC sample app, and O11 sample app

@ItsChaceD ItsChaceD marked this pull request as ready for review February 5, 2026 16:19
@ItsChaceD ItsChaceD requested a review from a team February 5, 2026 16:19
@OS-pedrogustavobilro OS-pedrogustavobilro self-assigned this Feb 5, 2026
it.altitude.toFloat(),
System.currentTimeMillis()
)
trueHeading = (magneticHeading!! + geoField.declination + 360) % 360
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would feel "safer" with

Suggested change
trueHeading = (magneticHeading!! + geoField.declination + 360) % 360
magneticHeading?.let { mh ->
trueHeading = (mh + geoField.declination + 360) % 360
}

trySend(Result.success(locationResultList))
}

sensorHandler.start()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if this gets called twice (e.g. from two calls to watchLocation)

}

awaitClose {
sensorHandler.stop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm how about if a user sets multiple watches?

Would think this call would make more sense inside clearWatch when watchLocationHandlers is empty. But I guess then there's the case of the app closing, we'll want to unregister the listener as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a method for heading @ FusedLocationProvider - https://developers.google.com/android/reference/com/google/android/gms/location/FusedOrientationProviderClient#requestOrientationUpdates(com.google.android.gms.location.DeviceOrientationRequest,%20java.util.concurrent.Executor,%20com.google.android.gms.location.DeviceOrientationListener)

This wouldn't work for the fallback, but just wondering if you evaluated this option (possibly using this handler for fallback without play services)

Comment on lines +224 to +228
it.toOSLocationResult(
magneticHeading = sensorHandler.magneticHeading,
trueHeading = sensorHandler.trueHeading,
headingAccuracy = sensorHandler.headingAccuracy
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how big of an issue this is, but it returns the same heading if there's multiple locations being sent at once, which for default requests to watchLocation shouldn't happen, but may happen depending on the value passed for interval, location results may be sent in batches.

Again, I don't know if this is that much of an issue because you're setting it to the latest location below, but you can probably get the headings for each location by doing some minor changes in IONGLOCSensorHandler

/**
* Handler for device sensors to calculate heading.
*/
internal class IONGLOCSensorHandler(context: Context) : SensorEventListener {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't want be too bothersome, but wouldn't mind some tests for this 😅 - particularly the computing of heading from sensor data + location.

Maybe AI could help drafting up some tests quickly? If you agree ofc.

altitude = this.altitude,
accuracy = this.accuracy,
altitudeAccuracy = if (IONGLOCBuildConfig.getAndroidSdkVersionCode() >= Build.VERSION_CODES.O) this.verticalAccuracyMeters else null,
heading = trueHeading ?: magneticHeading ?: course ?: -1f,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does #Location#bearing return if hasBearing is false? Just thinking if the value before this PR where there's no bearing would be -1, or something else?

}

override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
if (sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder the reasoning behind this accuracy mapping? Also I see this same block twice in code, could be extracted to its own method?

Comment on lines +125 to +127
every { sensorHandler.magneticHeading } returns null
every { sensorHandler.trueHeading } returns null
every { sensorHandler.headingAccuracy } returns null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add an extra test where sensorHandler returns data, to make sure that it is returned by the Controller.

@OS-pedrogustavobilro OS-pedrogustavobilro changed the title feat: add support for heading feat: add support for heading in addWatch Feb 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants