Fix send of the first location after start

This commit is contained in:
Maxime NATUREL 2022-05-04 16:02:23 +02:00
parent 0a21bd4b78
commit 6622651a90
2 changed files with 51 additions and 29 deletions

View File

@ -55,7 +55,10 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
private val binder = LocalBinder() private val binder = LocalBinder()
private var roomArgsList = mutableListOf<RoomArgs>() /**
* Keep track of a map between beacon event Id starting the live and RoomArgs.
*/
private var roomArgsMap = mutableMapOf<String, RoomArgs>()
private var timers = mutableListOf<Timer>() private var timers = mutableListOf<Timer>()
override fun onCreate() { override fun onCreate() {
@ -73,8 +76,6 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
Timber.i("### LocationSharingService.onStartCommand. sessionId - roomId ${roomArgs?.sessionId} - ${roomArgs?.roomId}") Timber.i("### LocationSharingService.onStartCommand. sessionId - roomId ${roomArgs?.sessionId} - ${roomArgs?.roomId}")
if (roomArgs != null) { if (roomArgs != null) {
roomArgsList.add(roomArgs)
// Show a sticky notification // Show a sticky notification
val notification = notificationUtils.buildLiveLocationSharingNotification() val notification = notificationUtils.buildLiveLocationSharingNotification()
startForeground(roomArgs.roomId.hashCode(), notification) startForeground(roomArgs.roomId.hashCode(), notification)
@ -87,7 +88,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
.getSafeActiveSession() .getSafeActiveSession()
?.let { session -> ?.let { session ->
session.coroutineScope.launch(session.coroutineDispatchers.io) { session.coroutineScope.launch(session.coroutineDispatchers.io) {
sendLiveBeaconInfo(session, roomArgs) sendStartingLiveBeaconInfo(session, roomArgs)
} }
} }
} }
@ -95,7 +96,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
return START_STICKY return START_STICKY
} }
private suspend fun sendLiveBeaconInfo(session: Session, roomArgs: RoomArgs) { private suspend fun sendStartingLiveBeaconInfo(session: Session, roomArgs: RoomArgs) {
val beaconContent = MessageBeaconInfoContent( val beaconContent = MessageBeaconInfoContent(
timeout = roomArgs.durationMillis, timeout = roomArgs.durationMillis,
isLive = true, isLive = true,
@ -103,7 +104,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
).toContent() ).toContent()
val stateKey = session.myUserId val stateKey = session.myUserId
session val beaconEventId = session
.getRoom(roomArgs.roomId) .getRoom(roomArgs.roomId)
?.stateService() ?.stateService()
?.sendStateEvent( ?.sendStateEvent(
@ -111,6 +112,16 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
stateKey = stateKey, stateKey = stateKey,
body = beaconContent body = beaconContent
) )
beaconEventId
?.takeUnless { it.isEmpty() }
?.let {
roomArgsMap[it] = roomArgs
locationTracker.requestLastKnownLocation()
}
?: run {
Timber.w("### LocationSharingService.sendStartingLiveBeaconInfo error, no received beacon info id")
}
} }
private fun scheduleTimer(roomId: String, durationMillis: Long) { private fun scheduleTimer(roomId: String, durationMillis: Long) {
@ -134,9 +145,13 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
// Send a new beacon info state by setting live field as false // Send a new beacon info state by setting live field as false
sendStoppedBeaconInfo(roomId) sendStoppedBeaconInfo(roomId)
synchronized(roomArgsList) { synchronized(roomArgsMap) {
roomArgsList.removeAll { it.roomId == roomId } val beaconIds = roomArgsMap
if (roomArgsList.isEmpty()) { .filter { it.value.roomId == roomId }
.map { it.key }
beaconIds.forEach { roomArgsMap.remove(it) }
if (roomArgsMap.isEmpty()) {
Timber.i("### LocationSharingService. Destroying self, time is up for all rooms") Timber.i("### LocationSharingService. Destroying self, time is up for all rooms")
destroyMe() destroyMe()
} }
@ -156,16 +171,17 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
override fun onLocationUpdate(locationData: LocationData) { override fun onLocationUpdate(locationData: LocationData) {
Timber.i("### LocationSharingService.onLocationUpdate. Uncertainty: ${locationData.uncertainty}") Timber.i("### LocationSharingService.onLocationUpdate. Uncertainty: ${locationData.uncertainty}")
val session = activeSessionHolder.getSafeActiveSession()
// Emit location update to all rooms in which live location sharing is active // Emit location update to all rooms in which live location sharing is active
session?.coroutineScope?.launch(session.coroutineDispatchers.io) { roomArgsMap.toMap().forEach { item ->
roomArgsList.toList().forEach { roomArg -> sendLiveLocation(item.value.roomId, item.key, locationData)
sendLiveLocation(roomArg.roomId, locationData)
}
} }
} }
private suspend fun sendLiveLocation(roomId: String, locationData: LocationData) { private fun sendLiveLocation(
roomId: String,
beaconInfoEventId: String,
locationData: LocationData
) {
val session = activeSessionHolder.getSafeActiveSession() val session = activeSessionHolder.getSafeActiveSession()
val room = session?.getRoom(roomId) val room = session?.getRoom(roomId)
val userId = session?.myUserId val userId = session?.myUserId
@ -174,18 +190,12 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
return return
} }
room room.sendService().sendLiveLocation(
.stateService() beaconInfoEventId = beaconInfoEventId,
.getLiveLocationBeaconInfo(userId, true) latitude = locationData.latitude,
?.eventId longitude = locationData.longitude,
?.let { uncertainty = locationData.uncertainty
room.sendService().sendLiveLocation( )
beaconInfoEventId = it,
latitude = locationData.latitude,
longitude = locationData.longitude,
uncertainty = locationData.uncertainty
)
}
} }
override fun onLocationProviderIsNotAvailable() { override fun onLocationProviderIsNotAvailable() {

View File

@ -40,10 +40,12 @@ class LocationTracker @Inject constructor(
fun onLocationProviderIsNotAvailable() fun onLocationProviderIsNotAvailable()
} }
private var callbacks = mutableListOf<Callback>() private val callbacks = mutableListOf<Callback>()
private var hasGpsProviderLiveLocation = false private var hasGpsProviderLiveLocation = false
private var lastLocation: LocationData? = null
@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION]) @RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
fun start() { fun start() {
Timber.d("## LocationTracker. start()") Timber.d("## LocationTracker. start()")
@ -92,6 +94,14 @@ class LocationTracker @Inject constructor(
callbacks.clear() callbacks.clear()
} }
/**
* Request the last known location. It will be given async through Callback.
* Please ensure adding a callback to receive the value.
*/
fun requestLastKnownLocation() {
lastLocation?.let { location -> callbacks.forEach { it.onLocationUpdate(location) } }
}
fun addCallback(callback: Callback) { fun addCallback(callback: Callback) {
if (!callbacks.contains(callback)) { if (!callbacks.contains(callback)) {
callbacks.add(callback) callbacks.add(callback)
@ -127,7 +137,9 @@ class LocationTracker @Inject constructor(
} }
} }
} }
callbacks.forEach { it.onLocationUpdate(location.toLocationData()) } val locationData = location.toLocationData()
lastLocation = locationData
callbacks.forEach { it.onLocationUpdate(locationData) }
} }
override fun onProviderDisabled(provider: String) { override fun onProviderDisabled(provider: String) {