From 7b159c5b71ec879b25ee7435d3ec80194072037a Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 9 Jun 2022 17:40:14 +0200 Subject: [PATCH] Send live location API --- .../room/location/LocationSharingService.kt | 10 ++++ .../sdk/api/session/room/send/SendService.kt | 9 --- .../sdk/internal/session/room/RoomModule.kt | 5 ++ .../location/DefaultLocationSharingService.kt | 14 ++++- .../room/location/SendLiveLocationTask.kt | 52 +++++++++++++++++ .../session/room/send/DefaultSendService.kt | 6 -- .../location/LocationSharingService.kt | 57 +++++++++---------- 7 files changed, 108 insertions(+), 45 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/SendLiveLocationTask.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt index 3ff629ac7a..11b74ecd7f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt @@ -33,6 +33,16 @@ interface LocationSharingService { */ suspend fun sendStaticLocation(latitude: Double, longitude: Double, uncertainty: Double?, isUserLocation: Boolean): Cancelable + /** + * Send a live location event to the room. + * To get the beacon info event id, [startLiveLocationShare] must be called before sending live location updates. + * @param beaconInfoEventId event id of the initial beacon info state event + * @param latitude required latitude of the location + * @param longitude required longitude of the location + * @param uncertainty Accuracy of the location in meters + */ + suspend fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable + /** * Starts sharing live location in the room. * @param timeoutMillis timeout of the live in milliseconds diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt index 201e6c5c0c..9cf062356f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt @@ -142,15 +142,6 @@ interface SendService { */ fun resendMediaMessage(localEcho: TimelineEvent): Cancelable - /** - * Send a live location event to the room. beacon_info state event has to be sent before sending live location updates. - * @param beaconInfoEventId event id of the initial beacon info state event - * @param latitude required latitude of the location - * @param longitude required longitude of the location - * @param uncertainty Accuracy of the location in meters - */ - fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable - /** * Remove this failed message from the timeline. * @param localEcho the unsent local echo diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt index ee332890e4..271e82a1e0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomModule.kt @@ -51,9 +51,11 @@ import org.matrix.android.sdk.internal.session.room.directory.DefaultSetRoomDire import org.matrix.android.sdk.internal.session.room.directory.GetPublicRoomTask import org.matrix.android.sdk.internal.session.room.directory.GetRoomDirectoryVisibilityTask import org.matrix.android.sdk.internal.session.room.directory.SetRoomDirectoryVisibilityTask +import org.matrix.android.sdk.internal.session.room.location.DefaultSendLiveLocationTask import org.matrix.android.sdk.internal.session.room.location.DefaultSendStaticLocationTask import org.matrix.android.sdk.internal.session.room.location.DefaultStartLiveLocationShareTask import org.matrix.android.sdk.internal.session.room.location.DefaultStopLiveLocationShareTask +import org.matrix.android.sdk.internal.session.room.location.SendLiveLocationTask import org.matrix.android.sdk.internal.session.room.location.SendStaticLocationTask import org.matrix.android.sdk.internal.session.room.location.StartLiveLocationShareTask import org.matrix.android.sdk.internal.session.room.location.StopLiveLocationShareTask @@ -314,4 +316,7 @@ internal abstract class RoomModule { @Binds abstract fun bindSendStaticLocationTask(task: DefaultSendStaticLocationTask): SendStaticLocationTask + + @Binds + abstract fun bindSendLiveLocationTask(task: DefaultSendLiveLocationTask): SendLiveLocationTask } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt index 407ae60e4b..ba6e7bd3fa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt @@ -34,6 +34,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor( @Assisted private val roomId: String, @SessionDatabase private val monarchy: Monarchy, private val sendStaticLocationTask: SendStaticLocationTask, + private val sendLiveLocationTask: SendLiveLocationTask, private val startLiveLocationShareTask: StartLiveLocationShareTask, private val stopLiveLocationShareTask: StopLiveLocationShareTask, private val liveLocationShareAggregatedSummaryMapper: LiveLocationShareAggregatedSummaryMapper, @@ -50,11 +51,22 @@ internal class DefaultLocationSharingService @AssistedInject constructor( latitude = latitude, longitude = longitude, uncertainty = uncertainty, - isUserLocation = isUserLocation + isUserLocation = isUserLocation, ) return sendStaticLocationTask.execute(params) } + override suspend fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable { + val params = SendLiveLocationTask.Params( + beaconInfoEventId = beaconInfoEventId, + roomId = roomId, + latitude = latitude, + longitude = longitude, + uncertainty = uncertainty, + ) + return sendLiveLocationTask.execute(params) + } + override suspend fun startLiveLocationShare(timeoutMillis: Long): String { val params = StartLiveLocationShareTask.Params( roomId = roomId, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/SendLiveLocationTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/SendLiveLocationTask.kt new file mode 100644 index 0000000000..ed40c82b66 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/SendLiveLocationTask.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.room.location + +import org.matrix.android.sdk.api.util.Cancelable +import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory +import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor +import org.matrix.android.sdk.internal.task.Task +import javax.inject.Inject + +internal interface SendLiveLocationTask : Task { + data class Params( + val roomId: String, + val beaconInfoEventId: String, + val latitude: Double, + val longitude: Double, + val uncertainty: Double?, + ) +} + +// TODO add unit tests +internal class DefaultSendLiveLocationTask @Inject constructor( + private val localEchoEventFactory: LocalEchoEventFactory, + private val eventSenderProcessor: EventSenderProcessor, +) : SendLiveLocationTask { + + override suspend fun execute(params: SendLiveLocationTask.Params): Cancelable { + val event = localEchoEventFactory.createLiveLocationEvent( + beaconInfoEventId = params.beaconInfoEventId, + roomId = params.roomId, + latitude = params.latitude, + longitude = params.longitude, + uncertainty = params.uncertainty, + ) + localEchoEventFactory.createLocalEcho(event) + return eventSenderProcessor.postEvent(event) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt index e83175151e..418000abed 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt @@ -129,12 +129,6 @@ internal class DefaultSendService @AssistedInject constructor( .let { sendEvent(it) } } - override fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable { - return localEchoEventFactory.createLiveLocationEvent(beaconInfoEventId, roomId, latitude, longitude, uncertainty) - .also { createLocalEcho(it) } - .let { sendEvent(it) } - } - override fun redactEvent(event: Event, reason: String?): Cancelable { // TODO manage media/attachements? val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason) diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt index 39fc526f80..77f3abcc28 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt @@ -25,6 +25,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.services.VectorService import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.session.coroutineScope +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.Session @@ -79,13 +80,9 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { scheduleTimer(roomArgs.roomId, roomArgs.durationMillis) // Send beacon info state event - activeSessionHolder - .getSafeActiveSession() - ?.let { session -> - session.coroutineScope.launch(session.coroutineDispatchers.io) { - sendStartingLiveBeaconInfo(session, roomArgs) - } - } + launchInIO { session -> + sendStartingLiveBeaconInfo(session, roomArgs) + } } return START_STICKY @@ -143,15 +140,11 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { } private fun sendStoppedBeaconInfo(roomId: String) { - activeSessionHolder - .getSafeActiveSession() - ?.let { session -> - session.coroutineScope.launch(session.coroutineDispatchers.io) { - session.getRoom(roomId) - ?.locationSharingService() - ?.stopLiveLocationShare() - } - } + launchInIO { session -> + session.getRoom(roomId) + ?.locationSharingService() + ?.stopLiveLocationShare() + } } override fun onLocationUpdate(locationData: LocationData) { @@ -168,20 +161,16 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { beaconInfoEventId: String, locationData: LocationData ) { - val session = activeSessionHolder.getSafeActiveSession() - val room = session?.getRoom(roomId) - val userId = session?.myUserId - - if (room == null || userId == null) { - return + launchInIO { session -> + session.getRoom(roomId) + ?.locationSharingService() + ?.sendLiveLocation( + beaconInfoEventId = beaconInfoEventId, + latitude = locationData.latitude, + longitude = locationData.longitude, + uncertainty = locationData.uncertainty + ) } - - room.sendService().sendLiveLocation( - beaconInfoEventId = beaconInfoEventId, - latitude = locationData.latitude, - longitude = locationData.longitude, - uncertainty = locationData.uncertainty - ) } override fun onNoLocationProviderAvailable() { @@ -202,6 +191,16 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { destroyMe() } + private fun launchInIO(block: suspend CoroutineScope.(Session) -> Unit) = + activeSessionHolder + .getSafeActiveSession() + ?.let { session -> + session.coroutineScope.launch( + context = session.coroutineDispatchers.io, + block = { block(session) } + ) + } + override fun onBind(intent: Intent?): IBinder { return binder }