Catching crash when offline during start of a live location share

This commit is contained in:
Maxime NATUREL 2022-06-15 10:01:35 +02:00
parent b16ccf5098
commit e55c378683
6 changed files with 71 additions and 14 deletions

View File

@ -46,9 +46,9 @@ interface LocationSharingService {
/**
* Starts sharing live location in the room.
* @param timeoutMillis timeout of the live in milliseconds
* @return the id of the created beacon info event
* @return the result of the update of the live
*/
suspend fun startLiveLocationShare(timeoutMillis: Long): String
suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult
/**
* Stops sharing live location in the room.

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* 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.api.session.room.location
/**
* Represents the result of an update of live location share like a start or a stop.
*/
sealed interface UpdateLiveLocationShareResult {
/**
* @param beaconEventId event id of the updated state event
*/
data class Success(val beaconEventId: String) : UpdateLiveLocationShareResult
/**
* @param error thrown during the update
*/
data class Failure(val error: Throwable) : UpdateLiveLocationShareResult
}

View File

@ -22,6 +22,7 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationShareAggregatedSummary
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.internal.database.mapper.LiveLocationShareAggregatedSummaryMapper
@ -66,7 +67,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
return sendLiveLocationTask.execute(params)
}
override suspend fun startLiveLocationShare(timeoutMillis: Long): String {
override suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult {
val params = StartLiveLocationShareTask.Params(
roomId = roomId,
timeoutMillis = timeoutMillis

View File

@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room.location
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.room.state.SendStateTask
@ -25,20 +26,21 @@ import org.matrix.android.sdk.internal.task.Task
import org.matrix.android.sdk.internal.util.time.Clock
import javax.inject.Inject
internal interface StartLiveLocationShareTask : Task<StartLiveLocationShareTask.Params, String> {
internal interface StartLiveLocationShareTask : Task<StartLiveLocationShareTask.Params, UpdateLiveLocationShareResult> {
data class Params(
val roomId: String,
val timeoutMillis: Long,
)
}
// TODO update unit test
internal class DefaultStartLiveLocationShareTask @Inject constructor(
@UserId private val userId: String,
private val clock: Clock,
private val sendStateTask: SendStateTask,
) : StartLiveLocationShareTask {
override suspend fun execute(params: StartLiveLocationShareTask.Params): String {
override suspend fun execute(params: StartLiveLocationShareTask.Params): UpdateLiveLocationShareResult {
val beaconContent = MessageBeaconInfoContent(
timeout = params.timeoutMillis,
isLive = true,
@ -51,6 +53,15 @@ internal class DefaultStartLiveLocationShareTask @Inject constructor(
eventType = eventType,
body = beaconContent
)
return sendStateTask.executeRetry(sendStateTaskParams, 3)
return try {
val eventId = sendStateTask.executeRetry(sendStateTaskParams, 3)
if (eventId.isNotEmpty()) {
UpdateLiveLocationShareResult.Success(eventId)
} else {
UpdateLiveLocationShareResult.Failure(Exception("empty event id for new state event"))
}
} catch (error: Throwable) {
UpdateLiveLocationShareResult.Failure(error)
}
}
}

View File

@ -41,6 +41,7 @@ internal class DefaultStopLiveLocationShareTask @Inject constructor(
private val stateEventDataSource: StateEventDataSource,
) : StopLiveLocationShareTask {
@Throws
override suspend fun execute(params: StopLiveLocationShareTask.Params) {
val beaconInfoStateEvent = getLiveLocationBeaconInfoForUser(userId, params.roomId) ?: return
val stateKey = beaconInfoStateEvent.stateKey ?: return

View File

@ -30,6 +30,7 @@ import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
import timber.log.Timber
import java.util.Timer
import java.util.TimerTask
@ -95,13 +96,20 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
?.startLiveLocationShare(timeoutMillis = roomArgs.durationMillis)
beaconEventId
?.takeUnless { it.isEmpty() }
?.let {
roomArgsMap[it] = roomArgs
?.let { result ->
when (result) {
is UpdateLiveLocationShareResult.Success -> {
roomArgsMap[result.beaconEventId] = roomArgs
locationTracker.requestLastKnownLocation()
}
is UpdateLiveLocationShareResult.Failure -> {
tryToDestroyMe()
}
}
}
?: run {
Timber.w("### LocationSharingService.sendStartingLiveBeaconInfo error, no received beacon info id")
tryToDestroyMe()
}
}
@ -132,10 +140,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
.map { it.key }
beaconIds.forEach { roomArgsMap.remove(it) }
if (roomArgsMap.isEmpty()) {
Timber.i("### LocationSharingService. Destroying self, time is up for all rooms")
destroyMe()
}
tryToDestroyMe()
}
}
@ -178,6 +183,13 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
stopSelf()
}
private fun tryToDestroyMe() {
if (roomArgsMap.isEmpty()) {
Timber.i("### LocationSharingService. Destroying self, time is up for all rooms")
destroyMe()
}
}
private fun destroyMe() {
locationTracker.removeCallback(this)
timers.forEach { it.cancel() }