This commit is contained in:
Dimitris
2025-11-17 10:11:15 +01:00
parent 1773ec2244
commit 3f3bdeb96d
12 changed files with 153 additions and 88 deletions

View File

@@ -48,7 +48,6 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -152,7 +151,7 @@ class MainActivity : ComponentActivity() {
val curLocation = Location(LocationManager.GPS_PROVIDER) val curLocation = Location(LocationManager.GPS_PROVIDER)
curLocation.longitude = loc[0] curLocation.longitude = loc[0]
curLocation.latitude = loc[1] curLocation.latitude = loc[1]
routeModel.findManeuver(curLocation) routeModel.updateLocation(curLocation)
val leftTime = routeModel.travelLeftTime() val leftTime = routeModel.travelLeftTime()
val leftDistance = routeModel.travelLeftDistance() val leftDistance = routeModel.travelLeftDistance()
Log.i(TAG, " leftTime: ${leftTime / 60}") Log.i(TAG, " leftTime: ${leftTime / 60}")

View File

@@ -187,7 +187,7 @@ class NavigationSession : Session() {
fun update(location: Location) { fun update(location: Location) {
surfaceRenderer.updateLocation(location) surfaceRenderer.updateLocation(location)
if (routeModel.isNavigating()) { if (routeModel.isNavigating()) {
routeModel.findManeuver(location) routeModel.updateLocation(location)
// if (routeModel.distanceToRoute > 50) { // if (routeModel.distanceToRoute > 50) {
// routeModel.stopNavigation() // routeModel.stopNavigation()
// locationIndex = 0 // locationIndex = 0

View File

@@ -11,11 +11,9 @@ import androidx.car.app.AppManager
import androidx.car.app.CarContext import androidx.car.app.CarContext
import androidx.car.app.SurfaceCallback import androidx.car.app.SurfaceCallback
import androidx.car.app.SurfaceContainer import androidx.car.app.SurfaceContainer
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -28,8 +26,8 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.setViewTreeLifecycleOwner import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.kouros.navigation.car.navigation.RouteCarModel import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.utils.NavigationUtils import com.kouros.navigation.utils.NavigationUtils
import kotlinx.coroutines.flow.onSubscription
import org.maplibre.compose.camera.CameraPosition import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.rememberCameraState import org.maplibre.compose.camera.rememberCameraState
import org.maplibre.compose.expressions.dsl.const import org.maplibre.compose.expressions.dsl.const
@@ -65,6 +63,7 @@ class SurfaceRenderer(
val previewRouteData = MutableLiveData("") val previewRouteData = MutableLiveData("")
lateinit var centerLocation : Location
var preview = false var preview = false
lateinit var mapView: ComposeView lateinit var mapView: ComposeView
@@ -72,7 +71,7 @@ class SurfaceRenderer(
val tilt = 55.0 val tilt = 55.0
val padding = PaddingValues(start = 150.dp, top = 250.dp) val padding = PaddingValues(start = 150.dp, top = 250.dp)
val prePadding = PaddingValues(start = 150.dp, bottom = 300.dp) val prePadding = PaddingValues(start = 150.dp, bottom = 0.dp)
val mSurfaceCallback: SurfaceCallback = object : SurfaceCallback { val mSurfaceCallback: SurfaceCallback = object : SurfaceCallback {
@@ -107,7 +106,7 @@ class SurfaceRenderer(
this.setViewTreeLifecycleOwner(lifecycleOwner) this.setViewTreeLifecycleOwner(lifecycleOwner)
this.setViewTreeSavedStateRegistryOwner(lifecycleOwner) this.setViewTreeSavedStateRegistryOwner(lifecycleOwner)
setContent { setContent {
Map() MapView()
} }
} }
presentation = Presentation(carContext, virtualDisplay.display) presentation = Presentation(carContext, virtualDisplay.display)
@@ -154,7 +153,9 @@ class SurfaceRenderer(
} }
@Composable @Composable
fun Map() { fun MapView() {
val locationProvider = rememberDefaultLocationProvider()
val locationState = rememberUserLocationState(locationProvider)
val position: CameraPosition? by cameraPosition.observeAsState() val position: CameraPosition? by cameraPosition.observeAsState()
val route: String? by routeData.observeAsState() val route: String? by routeData.observeAsState()
val previewRoute: String? by previewRouteData.observeAsState() val previewRoute: String? by previewRouteData.observeAsState()
@@ -171,8 +172,6 @@ class SurfaceRenderer(
padding = getPaddingValues() padding = getPaddingValues()
) )
) )
val locationProvider = rememberDefaultLocationProvider()
val locationState = rememberUserLocationState(locationProvider)
MaplibreMap( MaplibreMap(
cameraState = cameraState, cameraState = cameraState,
//baseStyle = BaseStyle.Uri("https://tiles.openfreemap.org/styles/liberty"), //baseStyle = BaseStyle.Uri("https://tiles.openfreemap.org/styles/liberty"),
@@ -191,6 +190,7 @@ class SurfaceRenderer(
) )
} }
if (!preview) {
LaunchedEffect(position) { LaunchedEffect(position) {
cameraState.animateTo( cameraState.animateTo(
finalPosition = CameraPosition( finalPosition = CameraPosition(
@@ -203,6 +203,20 @@ class SurfaceRenderer(
duration = 3.seconds duration = 3.seconds
) )
} }
} else {
LaunchedEffect(position) {
cameraState.animateTo(
finalPosition = CameraPosition(
bearing = 0.0,
zoom = 9.0,
target = Position(centerLocation.longitude, centerLocation.latitude),
tilt = 0.0,
padding = getPaddingValues()
),
duration = 3.seconds
)
}
}
} }
@Composable @Composable
@@ -266,6 +280,7 @@ class SurfaceRenderer(
fun updateLocation(location: Location) { fun updateLocation(location: Location) {
synchronized(this) { synchronized(this) {
if (!preview) {
var bearing: Double var bearing: Double
if (routeModel.isNavigating()) { if (routeModel.isNavigating()) {
bearing = routeModel.currentStep().bearing bearing = routeModel.currentStep().bearing
@@ -277,11 +292,7 @@ class SurfaceRenderer(
} }
} }
} }
var zoom = NavigationUtils().calculateZoom(location.speed.toDouble()) val zoom = NavigationUtils().calculateZoom(location.speed.toDouble())
if (preview) {
bearing = 0.0
zoom = 11.0
}
cameraPosition.postValue( cameraPosition.postValue(
cameraPosition.value!!.copy( cameraPosition.value!!.copy(
bearing = bearing, bearing = bearing,
@@ -291,16 +302,30 @@ class SurfaceRenderer(
) )
) )
lastLocation = location lastLocation = location
} else {
val bearing = 0.0
val zoom = 11.0
cameraPosition.postValue(
cameraPosition.value!!.copy(
bearing = bearing,
zoom = zoom,
tilt = 0.0,
target = Position(centerLocation.longitude, centerLocation.latitude)
)
)
} }
} }
}
fun setRouteData() { fun setRouteData() {
routeData.value = routeModel.route routeData.value = routeModel.route
preview = false preview = false
} }
fun setPreviewRouteData(route: String) { fun setPreviewRouteData(routeModel: RouteModel) {
previewRouteData.value = route previewRouteData.value = routeModel.route
centerLocation = routeModel.centerLocation
preview = true preview = true
} }

View File

@@ -134,7 +134,7 @@ class RouteCarModel() : RouteModel() {
ManeuverType.Left.value -> { ManeuverType.Left.value -> {
type = Maneuver.TYPE_TURN_NORMAL_LEFT type = Maneuver.TYPE_TURN_NORMAL_LEFT
currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_slight_left) currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_normal_left)
} }
ManeuverType.RampLeft.value -> { ManeuverType.RampLeft.value -> {
@@ -149,7 +149,7 @@ class RouteCarModel() : RouteModel() {
ManeuverType.StayLeft.value -> { ManeuverType.StayLeft.value -> {
type = Maneuver.TYPE_KEEP_LEFT type = Maneuver.TYPE_KEEP_LEFT
currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_slight_left) currentTurnIcon = createCarIcon(carContext, R.drawable.ic_turn_name_change)
} }
} }
maneuverType = type maneuverType = type

View File

@@ -53,7 +53,7 @@ class PlaceListScreen(
} }
if (category == Constants.CONTACTS) { if (category == Constants.CONTACTS) {
viewModel.contactAddress.observe(this, observerAddress) viewModel.contactAddress.observe(this, observerAddress)
viewModel.loadContacts(carContext) viewModel.loadContacts(carContext, location)
} }
} }

View File

@@ -47,6 +47,9 @@ import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.model.ViewModel import com.kouros.navigation.model.ViewModel
import java.math.BigDecimal
import java.math.RoundingMode
import kotlin.math.roundToInt
/** Creates a screen using the new [androidx.car.app.navigation.model.MapWithContentTemplate] */ /** Creates a screen using the new [androidx.car.app.navigation.model.MapWithContentTemplate] */
class RoutePreviewScreen( class RoutePreviewScreen(
@@ -68,7 +71,7 @@ class RoutePreviewScreen(
val observer = Observer<String> { route -> val observer = Observer<String> { route ->
if (route.isNotEmpty()) { if (route.isNotEmpty()) {
routeModel.startNavigation(route) routeModel.startNavigation(route)
surfaceRenderer.setPreviewRouteData(routeModel.route) surfaceRenderer.setPreviewRouteData(routeModel)
val geocoder = Geocoder(carContext) val geocoder = Geocoder(carContext)
geocoder.getFromLocation(destination.latitude, destination.longitude, 1) { geocoder.getFromLocation(destination.latitude, destination.longitude, 1) {
for (address in it) { for (address in it) {
@@ -198,8 +201,9 @@ class RoutePreviewScreen(
private fun createRouteText(index: Int): CarText { private fun createRouteText(index: Int): CarText {
val time = routeModel.summary.getInt("time") val time = routeModel.routeTime
val length = routeModel.summary.getInt("length")
val length = BigDecimal(routeModel.routeDistance).setScale(1, RoundingMode.HALF_EVEN)
val firstRoute = SpannableString(" \u00b7 $length km") val firstRoute = SpannableString(" \u00b7 $length km")
firstRoute.setSpan( firstRoute.setSpan(
DurationSpan.create(time.toLong()), 0, 1,0 DurationSpan.create(time.toLong()), 0, 1,0
@@ -208,7 +212,6 @@ class RoutePreviewScreen(
.build() .build()
} }
private fun onNavigate() { private fun onNavigate() {
setResult(destination) setResult(destination)
finish() finish()

View File

@@ -9,6 +9,7 @@ import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.model.ViewModel import com.kouros.navigation.model.ViewModel
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
/** /**
* Example local unit test, which will execute on the development machine (host). * Example local unit test, which will execute on the development machine (host).

View File

@@ -17,6 +17,7 @@
package com.kouros.navigation.data package com.kouros.navigation.data
import android.location.Location import android.location.Location
import com.kouros.navigation.model.RouteModel
import org.json.JSONArray import org.json.JSONArray
import java.net.Authenticator import java.net.Authenticator
import java.net.HttpURLConnection import java.net.HttpURLConnection
@@ -47,6 +48,13 @@ class NavigationRepository {
return fetchUrl(routeUrl + routeLocation) return fetchUrl(routeUrl + routeLocation)
} }
fun getRouteDistance(currentLocation : Location, location: Location): Double {
val route = getRoute(currentLocation, location)
val routeModel = RouteModel()
routeModel.startNavigation(route)
return routeModel.routeDistance
}
fun getPlaces(): List<Place> { fun getPlaces(): List<Place> {
val places: MutableList<Place> = ArrayList() val places: MutableList<Place> = ArrayList()
val placesStr = fetchUrl(placesUrl) val placesStr = fetchUrl(placesUrl)

View File

@@ -36,7 +36,7 @@ class Contacts(private var context: Context) {
if (name.contains("Jola") if (name.contains("Jola")
|| name.contains("Dominic") || name.contains("Dominic")
|| name.contains("Martha") || name.contains("Martha")
|| name.contains("Μεντή") || name.contains("Μεντη")
|| name.contains("David")) { || name.contains("David")) {
val mimeType: String = getString(getColumnIndex(ContactsContract.Data.MIMETYPE)) val mimeType: String = getString(getColumnIndex(ContactsContract.Data.MIMETYPE))
if (mimeType == ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) { if (mimeType == ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE) {

View File

@@ -4,22 +4,26 @@ import android.location.Location
import android.location.LocationManager import android.location.LocationManager
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.data.StepData import com.kouros.navigation.data.StepData
import com.kouros.navigation.utils.NavigationUtils
import com.kouros.navigation.utils.NavigationUtils.Utils.createGeoJson import com.kouros.navigation.utils.NavigationUtils.Utils.createGeoJson
import com.kouros.navigation.utils.NavigationUtils.Utils.decodePolyline import com.kouros.navigation.utils.NavigationUtils.Utils.decodePolyline
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import kotlin.math.absoluteValue
import kotlin.math.roundToInt import kotlin.math.roundToInt
// Source - https://stackoverflow.com/a
// Posted by Dmitrii Bychkov
// Retrieved 2025-11-14, License - CC BY-SA 4.0
open class RouteModel () { open class RouteModel () {
var polylineLocations: List<List<Double>> = emptyList() var polylineLocations: List<List<Double>> = emptyList()
lateinit var maneuvers: JSONArray lateinit var maneuvers: JSONArray
lateinit var locations: JSONArray lateinit var locations: JSONArray
lateinit var summary: JSONObject private lateinit var summary: JSONObject
var routeDistance = 0.0
var routeTime = 0.0
lateinit var centerLocation: Location
lateinit var destination: Place lateinit var destination: Place
var navigating = false var navigating = false
var arrived = false var arrived = false
var maneuverIndex = 0 var maneuverIndex = 0
@@ -28,12 +32,13 @@ open class RouteModel () {
var distanceToStepEnd = 0F var distanceToStepEnd = 0F
var bearing = 0F
var beginIndex = 0 var beginIndex = 0
var endIndex = 0 var endIndex = 0
var routingManeuvers = mutableListOf<JSONObject>()
var distanceToRoute = 0F var routingManeuvers = mutableListOf<JSONObject>()
var route = "" var route = ""
@@ -56,11 +61,20 @@ open class RouteModel () {
locations = trip.getJSONArray("locations") locations = trip.getJSONArray("locations")
val legs = trip.getJSONArray("legs") val legs = trip.getJSONArray("legs")
summary = trip.getJSONObject("summary") summary = trip.getJSONObject("summary")
routeTime = summary.getDouble("time")
routeDistance = summary.getDouble("length")
centerLocation = createCenterLocation()
maneuvers = legs.getJSONObject(0).getJSONArray("maneuvers") maneuvers = legs.getJSONObject(0).getJSONArray("maneuvers")
val shape = legs.getJSONObject(0).getString("shape") val shape = legs.getJSONObject(0).getString("shape")
polylineLocations = decodePolyline(shape) polylineLocations = decodePolyline(shape)
} }
private fun createCenterLocation() : Location {
val latitude = summary.getDouble("max_lat") - (summary.getDouble("max_lat") - summary.getDouble("min_lat"))
val longitude = summary.getDouble("max_lon") - (summary.getDouble("max_lon") - summary.getDouble("min_lon"))
return NavigationUtils().location(latitude, longitude)
}
fun startNavigation(valhallaRoute: String) { fun startNavigation(valhallaRoute: String) {
decodeValhallaRoute(valhallaRoute) decodeValhallaRoute(valhallaRoute)
for (i in 0..<maneuvers.length()) { for (i in 0..<maneuvers.length()) {
@@ -77,7 +91,7 @@ open class RouteModel () {
return ((leftStepDistance() * 1000).roundToInt().toDouble() / 10.0).roundToInt() * 10.0 return ((leftStepDistance() * 1000).roundToInt().toDouble() / 10.0).roundToInt() * 10.0
} }
fun findManeuver(location: Location) { fun updateLocation(location: Location) {
var nearestDistance = 100000.0f var nearestDistance = 100000.0f
maneuverIndex = -1 maneuverIndex = -1
// find maneuver // find maneuver
@@ -92,18 +106,18 @@ open class RouteModel () {
calculateCurrentIndex(beginShapeIndex, endShapeIndex, location) calculateCurrentIndex(beginShapeIndex, endShapeIndex, location)
} }
} }
distanceToRoute = nearestDistance
} }
fun currentStep(): StepData { fun currentStep(): StepData {
var bearing = 0
val maneuver = (maneuvers[maneuverIndex] as JSONObject) val maneuver = (maneuvers[maneuverIndex] as JSONObject)
var text = "" var text = ""
if (maneuver.optJSONArray("street_names") != null) { if (maneuver.optJSONArray("street_names") != null) {
text = maneuver.getJSONArray("street_names").get(0) as String text = maneuver.getJSONArray("street_names").get(0) as String
} }
if (bearing == 0F) {
if (maneuver.has("bearing_after")) { if (maneuver.has("bearing_after")) {
bearing = maneuver.getInt("bearing_after") bearing = maneuver.getInt("bearing_after").toFloat()
}
} }
val distanceStepLeft = leftStepDistance() * 1000 val distanceStepLeft = leftStepDistance() * 1000
when (distanceStepLeft) { when (distanceStepLeft) {
@@ -120,7 +134,6 @@ open class RouteModel () {
} }
/** Calculates the index in a maneuver. */ /** Calculates the index in a maneuver. */
private fun calculateCurrentIndex( private fun calculateCurrentIndex(
beginShapeIndex: Int, beginShapeIndex: Int,
@@ -139,9 +152,14 @@ open class RouteModel () {
beginIndex = beginShapeIndex beginIndex = beginShapeIndex
endIndex = endShapeIndex endIndex = endShapeIndex
distanceToStepEnd = 0F distanceToStepEnd = 0F
for (j in i + 1..endShapeIndex) {
val loc1 = Location(LocationManager.GPS_PROVIDER) val loc1 = Location(LocationManager.GPS_PROVIDER)
val loc2 = Location(LocationManager.GPS_PROVIDER) val loc2 = Location(LocationManager.GPS_PROVIDER)
loc1.longitude = polylineLocations[i][0]
loc1.latitude = polylineLocations[i][1]
loc2.longitude = polylineLocations[i+1][0]
loc2.latitude = polylineLocations[i+1][1]
bearing = loc1.bearingTo(loc2).absoluteValue
for (j in i + 1..endShapeIndex) {
loc1.longitude = polylineLocations[j - 1][0] loc1.longitude = polylineLocations[j - 1][0]
loc1.latitude = polylineLocations[j - 1][1] loc1.latitude = polylineLocations[j - 1][1]
loc2.longitude = polylineLocations[j][0] loc2.longitude = polylineLocations[j][0]
@@ -228,7 +246,6 @@ open class RouteModel () {
maneuverIndex = 0 maneuverIndex = 0
currentIndex = 0 currentIndex = 0
distanceToStepEnd = 0F distanceToStepEnd = 0F
distanceToRoute = 0F
beginIndex = 0 beginIndex = 0
endIndex = 0 endIndex = 0

View File

@@ -12,6 +12,7 @@ import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.ObjectBox.boxStore import com.kouros.navigation.data.ObjectBox.boxStore
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.data.Place_ import com.kouros.navigation.data.Place_
import com.kouros.navigation.utils.NavigationUtils
import io.objectbox.kotlin.boxFor import io.objectbox.kotlin.boxFor
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -42,11 +43,9 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
val placeBox = boxStore.boxFor(Place::class) val placeBox = boxStore.boxFor(Place::class)
pl.addAll(placeBox.all) pl.addAll(placeBox.all)
for (place in pl) { for (place in pl) {
val plLocation = Location(LocationManager.GPS_PROVIDER) val plLocation = NavigationUtils().location(place.latitude, place.longitude)
plLocation.longitude = place.longitude val distance = repository.getRouteDistance(location, plLocation)
plLocation.latitude = place.latitude place.distance = distance.toFloat()
val distance: Float = location.distanceTo(plLocation)
place.distance = distance / 1000
} }
places.postValue(pl) places.postValue(pl)
} catch (e: Exception) { } catch (e: Exception) {
@@ -75,7 +74,7 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
} }
} }
fun loadContacts(context: Context) { fun loadContacts(context: Context, currentLocation: Location) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
val geocoder = Geocoder(context) val geocoder = Geocoder(context)
@@ -83,23 +82,29 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
val contacts = Contacts(context = context) val contacts = Contacts(context = context)
val addresses = contacts.retrieveContacts() val addresses = contacts.retrieveContacts()
for (address in addresses) { for (address in addresses) {
val lines = address.address.split("\n") val addressLines = address.address.split("\n")
geocoder.getFromLocationName( geocoder.getFromLocationName(
address.address, 5) { address.address, 5) {
for (adr in it) { for (adr in it) {
if (addressLines.size > 1) {
val plLocation = NavigationUtils().location(adr.latitude, adr.longitude)
val distance = repository.getRouteDistance(currentLocation, plLocation)
contactList.add( contactList.add(
Place( Place(
id = address.contactId, id = address.contactId,
name = address.name + " " + lines[0] + " " + lines[1], name = address.name + " " + addressLines[0] + " " + addressLines[1],
Constants.CONTACTS, Constants.CONTACTS,
street = lines[0], street = addressLines[0],
city = lines[1], city = addressLines[1],
latitude = adr.latitude, latitude = adr.latitude,
longitude = adr.longitude, longitude = adr.longitude,
avatar = address.avatar avatar = address.avatar,
distance = distance.toFloat()
) )
) )
} }
}
contactAddress.postValue(contactList) contactAddress.postValue(contactList)
} }
} }

View File

@@ -121,4 +121,11 @@ class NavigationUtils() {
} }
return zoom.toDouble() return zoom.toDouble()
} }
fun location(latitude: Double, longitude: Double): Location {
val location = Location(LocationManager.GPS_PROVIDER)
location.longitude = longitude
location.latitude = latitude
return location
}
} }