Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions android/src/main/java/com/rnmapbox/rnmbx/events/LocationEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ import java.util.*

import com.rnmapbox.rnmbx.v11compat.location.*

class LocationEvent(private val location: Location, private val mapView: RNMBXMapView?) : IEvent {
class LocationEvent(
private val location: Location,
private val mapView: RNMBXMapView?,
private val heading: Double? = null
) : IEvent {
val uUID: UUID

init {
uUID = UUID.randomUUID()
}

constructor(location: Location) : this(location, null) {}
constructor(location: Location, heading: Double? = null) : this(location, null, heading)

override val iD
get() = mapView?.id ?: -1
Expand Down Expand Up @@ -50,12 +54,12 @@ class LocationEvent(private val location: Location, private val mapView: RNMBXMa
coords.putDouble("altitude", it)
}
coords.putDouble("accuracy", location.accuracy.toDouble())
// A better solution will be to pull the heading from the compass engine,
// unfortunately the api is not publicly available in the mapbox sdk
location.bearing?.let {
coords.putDouble("heading", it.toDouble())
coords.putDouble("course", it.toDouble())
}
heading?.let {
coords.putDouble("heading", it)
}
location.speed?.let {
coords.putDouble("speed", it.toDouble())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package com.rnmapbox.rnmbx.modules

import android.animation.ValueAnimator
import com.facebook.react.bridge.*
import com.rnmapbox.rnmbx.location.LocationManager
import com.facebook.react.module.annotations.ReactModule
import com.rnmapbox.rnmbx.NativeRNMBXLocationModuleSpec
import com.rnmapbox.rnmbx.location.LocationManager.OnUserLocationChange
import com.rnmapbox.rnmbx.events.LocationEvent
import com.rnmapbox.rnmbx.location.LocationManager.Companion.getInstance
import com.mapbox.common.location.LocationError
import com.mapbox.geojson.Point
import com.mapbox.maps.plugin.locationcomponent.DefaultLocationProvider
import com.mapbox.maps.plugin.locationcomponent.LocationConsumer
import java.lang.Exception
import kotlin.math.abs

import com.rnmapbox.rnmbx.v11compat.location.*

Expand All @@ -22,16 +28,21 @@ class RNMBXLocationModule(reactContext: ReactApplicationContext) :
private val locationManager: LocationManager? = getInstance(reactContext)
private var mLastLocation: Location? = null
private var locationEventThrottle: LocationEventThrottle = LocationEventThrottle()
private var mLastHeading: Double? = null
private var mLastSentHeading: Double? = null
private var headingProvider: DefaultLocationProvider? = null

private val lifecycleEventListener: LifecycleEventListener = object : LifecycleEventListener {
override fun onHostResume() {
if (isEnabled) {
locationManager?.resume()
startHeadingUpdates()
}
}

override fun onHostPause() {
locationManager?.pause()
stopHeadingUpdates()
}

override fun onHostDestroy() {
Expand All @@ -56,12 +67,50 @@ class RNMBXLocationModule(reactContext: ReactApplicationContext) :
}
mLastLocation = location
if (changed && (location != null) && shouldSendLocationEvent()) {
val locationEvent = LocationEvent(location)
emitOnLocationUpdate(locationEvent.toJSON())
sendLocationEvent(location)
}
}
}

private val headingConsumer = object : LocationConsumer {
override fun onBearingUpdated(vararg bearing: Double, options: (ValueAnimator.() -> Unit)?) {
val heading = bearing.lastOrNull()?.let { (it % 360.0 + 360.0) % 360.0 } ?: return
mLastHeading = heading
val location = mLastLocation ?: return
// Like CLLocationManager's default headingFilter, ignore changes under 1 degree
val lastSent = mLastSentHeading
if (lastSent != null && abs((heading - lastSent + 540.0) % 360.0 - 180.0) < 1.0) return
if (shouldSendLocationEvent()) {
sendLocationEvent(location)
}
}

override fun onLocationUpdated(vararg location: Point, options: (ValueAnimator.() -> Unit)?) {}
override fun onPuckLocationAnimatorDefaultOptionsUpdated(options: ValueAnimator.() -> Unit) {}
override fun onPuckBearingAnimatorDefaultOptionsUpdated(options: ValueAnimator.() -> Unit) {}
override fun onHorizontalAccuracyRadiusUpdated(vararg radius: Double, options: (ValueAnimator.() -> Unit)?) {}
override fun onPuckAccuracyRadiusAnimatorDefaultOptionsUpdated(options: ValueAnimator.() -> Unit) {}
override fun onError(error: LocationError) {}
}

private fun sendLocationEvent(location: Location) {
mLastSentHeading = mLastHeading
emitOnLocationUpdate(LocationEvent(location, mLastHeading).toJSON())
}

private fun startHeadingUpdates() {
if (headingProvider != null) return
headingProvider = DefaultLocationProvider(reactApplicationContext).also {
it.updatePuckBearing(PuckBearing.HEADING)
it.registerLocationConsumer(headingConsumer)
}
}

private fun stopHeadingUpdates() {
headingProvider?.unRegisterLocationConsumer(headingConsumer)
headingProvider = null
}

init {
reactContext.addLifecycleEventListener(lifecycleEventListener)
}
Expand Down Expand Up @@ -107,7 +156,7 @@ class RNMBXLocationModule(reactContext: ReactApplicationContext) :
override fun onSuccess(result: LocationEngineResult) {
val location = result.lastLocation
if (location != null) {
val locationEvent = LocationEvent(location)
val locationEvent = LocationEvent(location, mLastHeading)
promise.resolve(locationEvent.payload)
} else {
promise.resolve(null)
Expand Down Expand Up @@ -140,6 +189,7 @@ class RNMBXLocationModule(reactContext: ReactApplicationContext) :
locationManager!!.addLocationListener(onUserLocationChangeCallback)
locationManager.setMinDisplacement(mMinDisplacement)
locationManager.startCounted()
startHeadingUpdates()
}

private fun stopLocationManager() {
Expand All @@ -148,8 +198,11 @@ class RNMBXLocationModule(reactContext: ReactApplicationContext) :
}
locationManager!!.removeLocationListener(onUserLocationChangeCallback)
locationManager.stopCounted()
stopHeadingUpdates()
isEnabled = false
mLastLocation = null
mLastHeading = null
mLastSentHeading = null
}

// region Location event throttle
Expand Down
2 changes: 0 additions & 2 deletions src/modules/location/locationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ interface Coordinates {
/**
* The heading (measured in degrees) relative to true north.
* Heading is used to describe the direction the device is pointing to (the value of the compass).
* Note that on Android this is incorrectly reporting the course value as mentioned in issue https://github.com/rnmapbox/maps/issues/1213
* and will be corrected in a future update.
*/
heading?: number;

Expand Down
Loading