summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2024-01-03 22:51:08 +0100
committerLeonard Kugis <leonard@kug.is>2024-01-03 22:51:08 +0100
commit992fa2d9a9bc519215c0b352688691ba012ca04a (patch)
treeb84ed8965cb828e7f53acf5c9a7e30edd3b7675d
parent5db0bdfdf62ae0915b587399a0ff4ce53bca813b (diff)
Fixed route interpolation
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt13
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt33
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt28
-rw-r--r--core/src/main/java/foundation/e/advancedprivacy/domain/entities/FakeLocationCoordinate.kt1
-rw-r--r--fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt65
5 files changed, 97 insertions, 43 deletions
diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt
index 27a2104..76a1e69 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/FakeLocationStateUseCase.kt
@@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import timber.log.Timber
import kotlin.random.Random
+import android.util.Log
class FakeLocationStateUseCase(
private val fakeLocationModule: FakeLocationModule,
@@ -215,12 +216,14 @@ class FakeLocationStateUseCase(
null,
null,
false,
- route,
- false,
+ route ?: localStateRepository.route,
+ localStateRepository.routeLoopEnabled,
false
)
localStateRepository.setLocationMode(LocationMode.ROUTE)
+ if(route != null)
+ localStateRepository.route = route
}
fun setRoute(route: List<FakeLocationCoordinate>) {
@@ -234,13 +237,16 @@ class FakeLocationStateUseCase(
null,
false,
route,
- false,
+ localStateRepository.routeLoopEnabled,
false
)
+
+ localStateRepository.route = route
}
fun routeStart() {
if (hasAcquireMockLocationPermission()) {
+ fakeLocationModule.startFakeLocation()
fakeLocationModule.routeStart(localStateRepository.route, localStateRepository.routeLoopEnabled)
} else {
useRealLocation()
@@ -249,6 +255,7 @@ class FakeLocationStateUseCase(
fun routeStop() {
if (hasAcquireMockLocationPermission()) {
+ fakeLocationModule.stopFakeLocation()
fakeLocationModule.routeStop()
} else {
useRealLocation()
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
index b70ae36..a155216 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationFragment.kt
@@ -67,7 +67,13 @@ import timber.log.Timber
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import foundation.e.advancedprivacy.domain.entities.FakeLocationCoordinate
-import java.io.File
+import java.io.BufferedReader
+import java.io.IOException
+import java.io.InputStream
+import java.io.InputStreamReader
+import android.util.Log
+import kotlin.math.sqrt
+import kotlin.math.pow
class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location) {
@@ -341,11 +347,26 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.let { uri ->
- if(uri.path != null) {
- var routeFile = File(uri.path ?: ".")
- //val filePath = selectedFile?.uri?.path ?: "Path not found"
- //binding.locationRoutePath.text = "Path: $filePath"
- route = Gson().fromJson(routeFile.readText(Charsets.UTF_8), object : TypeToken<List<FakeLocationCoordinate>>() {}.type)
+ var activity = getActivity()
+ if(uri.path != null && activity != null) {
+ var inputStream: InputStream? = null
+ var reader: BufferedReader? = null
+ var route_str: String? = null
+ try {
+ inputStream = activity.contentResolver.openInputStream(uri)
+ reader = BufferedReader(InputStreamReader(inputStream))
+ route_str = reader.readLines().joinToString("")
+ } catch(e: IOException) {
+ Log.e("FakeLocationFragment", "Error reading JSON file", e)
+ } finally {
+ try {
+ reader?.close()
+ inputStream?.close()
+ } catch (e: IOException) {
+ Log.e("FakeLocationFragment", "Error closing streams", e)
+ }
+ }
+ route = Gson().fromJson(route_str, object : TypeToken<List<FakeLocationCoordinate>>() {}.type)
var route_buf = route
route_buf?.let {
viewModel.submitAction(Action.SetRoute(route_buf))
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt
index c88c638..049c707 100644
--- a/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/location/FakeLocationViewModel.kt
@@ -37,6 +37,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.time.Duration.Companion.milliseconds
import foundation.e.advancedprivacy.domain.entities.FakeLocationCoordinate
+import android.util.Log
class FakeLocationViewModel(
private val fakeLocationStateUseCase: FakeLocationStateUseCase
@@ -58,8 +59,8 @@ class FakeLocationViewModel(
private val specificLocationInputFlow = MutableSharedFlow<Action.SetSpecificLocationAction>()
private val mockLocationParametersInputFlow = MutableSharedFlow<Action.UpdateMockLocationParameters>()
- private val setRouteLoopEnabledInputFlow = MutableSharedFlow<Action.SetRouteLoopEnabledAction>()
- private val setRouteInputFlow = MutableSharedFlow<Action.SetRoute>()
+ private val routeLoopEnabledInputFlow = MutableSharedFlow<Action.SetRouteLoopEnabledAction>()
+ private val routeInputFlow = MutableSharedFlow<Action.SetRoute>()
@OptIn(FlowPreview::class)
suspend fun doOnStartedState() = withContext(Dispatchers.Main) {
@@ -73,7 +74,9 @@ class FakeLocationViewModel(
speed = ss.speed,
jitter = ss.jitter,
specificLatitude = ss.specificLatitude,
- specificLongitude = ss.specificLongitude
+ specificLongitude = ss.specificLongitude,
+ route = ss.route,
+ loopRoute = ss.loopRoute
)
}
},
@@ -85,14 +88,14 @@ class FakeLocationViewModel(
.debounce(SET_MOCK_LOCATION_PARAMETERS_DELAY).map { action ->
fakeLocationStateUseCase.setFakeLocationParameters(action.altitude, action.speed, action.jitter)
},
- setRouteLoopEnabledInputFlow
- .debounce(SET_ROUTE_LOOP_ENABLED_DELAY).map { action ->
- fakeLocationStateUseCase.setRouteLoopEnabled(action.isEnabled)
- },
- setRouteInputFlow
+ routeInputFlow
.debounce(SET_ROUTE_DELAY).map { action ->
fakeLocationStateUseCase.setRoute(action.route)
},
+ routeLoopEnabledInputFlow
+ .debounce(SET_ROUTE_LOOP_ENABLED_DELAY).map { action ->
+ fakeLocationStateUseCase.setRouteLoopEnabled(action.isEnabled)
+ },
).collect {}
}
}
@@ -106,7 +109,7 @@ class FakeLocationViewModel(
is Action.UseRealLocationAction -> fakeLocationStateUseCase.useRealLocation()
is Action.UseRoute -> fakeLocationStateUseCase.useRoute()
is Action.UpdateMockLocationParameters -> updateMockLocationParameters(action)
- is Action.SetRoute -> setRouteInputFlow.emit(action)
+ is Action.SetRoute -> setRoute(action)
is Action.SetRouteLoopEnabledAction -> setRouteLoopEnabled(action)
is Action.RouteStartAction -> fakeLocationStateUseCase.routeStart()
is Action.RouteStopAction -> fakeLocationStateUseCase.routeStop()
@@ -128,8 +131,13 @@ class FakeLocationViewModel(
mockLocationParametersInputFlow.emit(action)
}
+ private suspend fun setRoute(action: Action.SetRoute) {
+ fakeLocationStateUseCase.setRoute(action.route)
+ routeInputFlow.emit(action)
+ }
+
private suspend fun setRouteLoopEnabled(action: Action.SetRouteLoopEnabledAction) {
- setRouteLoopEnabledInputFlow.emit(action)
+ routeLoopEnabledInputFlow.emit(action)
}
sealed class SingleEvent {
diff --git a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/FakeLocationCoordinate.kt b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/FakeLocationCoordinate.kt
index a7992a9..b497b13 100644
--- a/core/src/main/java/foundation/e/advancedprivacy/domain/entities/FakeLocationCoordinate.kt
+++ b/core/src/main/java/foundation/e/advancedprivacy/domain/entities/FakeLocationCoordinate.kt
@@ -24,5 +24,6 @@
val speed: Float,
val jitter: Float,
val bearing: Float,
+ val timestamp: Float
)
\ No newline at end of file
diff --git a/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt b/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt
index c388afc..d13e263 100644
--- a/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt
+++ b/fakelocation/src/main/java/foundation/e/advancedprivacy/fakelocation/services/FakeLocationService.kt
@@ -154,31 +154,49 @@ class FakeLocationService : Service() {
}.start()
}
- private fun calculateRouteSegment(route: List<FakeLocationCoordinate>, routeTime: Float): Pair<FakeLocationCoordinate,Pair<Float,Float>>? {
- if(route.size < 2)
+ private fun calculateRouteSegment(): Pair<FakeLocationCoordinate,Pair<Float,Float>>? {
+ var route_buf: List<FakeLocationCoordinate> = route ?: return null
+ if(route_buf.size < 2)
return null
- var prev = route.first()
- var timeCurrent: Float = 0f
- do {
- var route_current = if(routeReversed) route.reversed() else route
- for(coord in route_current) {
- var direction = Pair<Float,Float>((coord.latitude - prev.latitude) * 111139.0f, (coord.longitude - prev.longitude) * 111139.0f)
- if(!(coord.latitude == prev.latitude && coord.longitude == prev.longitude)) {
- var distance_target = sqrt((direction.first * direction.first) + (direction.second * direction.second))
- var direction_unit = Pair<Float,Float>(direction.first / distance_target, direction.second / distance_target)
- var location_meters = Pair<Float,Float>(direction_unit.first * (routeTime - timeCurrent) * prev.speed,
- direction_unit.second * (routeTime - timeCurrent) * prev.speed)
- var distance_current = sqrt((location_meters.first * location_meters.first) + (location_meters.second - location_meters.second))
- var location = Pair<Float,Float>(prev.latitude + (location_meters.first / 111139.0f), prev.longitude + (location_meters.second / 111139.0f))
- if(distance_current < distance_target)
- return Pair<FakeLocationCoordinate,Pair<Float,Float>>(prev, location)
- timeCurrent += distance_target / prev.speed
- prev = coord
+ var segment: Pair<FakeLocationCoordinate,FakeLocationCoordinate>? = null
+ var factor: Float? = null
+ var iter = route_buf.iterator()
+ while(iter.hasNext()) {
+ segment = Pair<FakeLocationCoordinate,FakeLocationCoordinate>(
+ if(segment == null) iter.next() else segment.second,
+ iter.next()
+ )
+ if(routeTime >= segment.first.timestamp && routeTime < segment.second.timestamp) {
+ factor = (routeTime - segment.first.timestamp) / (segment.second.timestamp - segment.first.timestamp)
+ break
+ }
+ }
+ if(factor == null && loopRoute) {
+ iter = route_buf.reversed().iterator()
+ while(iter.hasNext()) {
+ segment = Pair<FakeLocationCoordinate,FakeLocationCoordinate>(
+ if(segment == null) iter.next() else segment.second,
+ iter.next()
+ )
+ if(routeTime >= ((2 * route_buf.last().timestamp) - segment.first.timestamp) && routeTime < ((2 * route_buf.last().timestamp) - segment.second.timestamp)) {
+ factor = (routeTime - ((2 * route_buf.last().timestamp) - segment.first.timestamp)) / (((2 * route_buf.last().timestamp) - segment.second.timestamp) - ((2 * route_buf.last().timestamp) - segment.first.timestamp))
+ break
}
}
- if(loopRoute)
- routeReversed = !routeReversed
- } while(loopRoute)
+ if(factor == null) {
+ routeTime -= (2 * route_buf.last().timestamp)
+ return calculateRouteSegment()
+ }
+ }
+ if(segment != null && factor != null) {
+ return Pair<FakeLocationCoordinate,Pair<Float,Float>>(
+ segment.first,
+ Pair<Float,Float>(
+ segment.first.latitude + ((segment.second.latitude - segment.first.latitude) * factor),
+ segment.first.longitude + ((segment.second.longitude - segment.first.longitude) * factor)
+ )
+ )
+ }
return null
}
@@ -187,8 +205,7 @@ class FakeLocationService : Service() {
routeTime = 0f
cdtRoute = object : CountDownTimer(PERIOD_UPDATES_SERIE, PERIOD_LOCATION_UPDATE) {
override fun onTick(millisUntilFinished: Long) {
- var route_buf: List<FakeLocationCoordinate> = route ?: return
- var coord = calculateRouteSegment(route_buf, routeTime)
+ var coord = calculateRouteSegment()
if(coord == null) {
// done with route
return