Compare commits
5 Commits
e5c74f6fa2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b8abbd4eb | ||
|
|
d0a07e1315 | ||
|
|
ddae6f2189 | ||
|
|
01a4eb7fca | ||
|
|
8673380b9e |
@@ -14,8 +14,8 @@ android {
|
|||||||
applicationId = "com.kouros.navigation"
|
applicationId = "com.kouros.navigation"
|
||||||
minSdk = 33
|
minSdk = 33
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 13
|
versionCode = 14
|
||||||
versionName = "0.1.3.13"
|
versionName = "0.1.3.14"
|
||||||
base.archivesName = "navi-$versionName"
|
base.archivesName = "navi-$versionName"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
app/src/main/ic_launcher-playstore.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
@@ -41,12 +41,9 @@ import com.google.android.gms.location.LocationServices
|
|||||||
import com.kouros.navigation.MainApplication.Companion.navigationViewModel
|
import com.kouros.navigation.MainApplication.Companion.navigationViewModel
|
||||||
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
|
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
|
||||||
import com.kouros.navigation.data.Constants.homeLocation
|
import com.kouros.navigation.data.Constants.homeLocation
|
||||||
import com.kouros.navigation.data.NavigationRepository
|
|
||||||
import com.kouros.navigation.data.StepData
|
import com.kouros.navigation.data.StepData
|
||||||
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
|
||||||
import com.kouros.navigation.model.MockLocation
|
import com.kouros.navigation.model.MockLocation
|
||||||
import com.kouros.navigation.model.RouteModel
|
import com.kouros.navigation.model.RouteModel
|
||||||
import com.kouros.navigation.model.ViewModel
|
|
||||||
import com.kouros.navigation.ui.theme.NavigationTheme
|
import com.kouros.navigation.ui.theme.NavigationTheme
|
||||||
import com.kouros.navigation.utils.bearing
|
import com.kouros.navigation.utils.bearing
|
||||||
import com.kouros.navigation.utils.calculateZoom
|
import com.kouros.navigation.utils.calculateZoom
|
||||||
@@ -114,13 +111,16 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
|
locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
|
||||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
||||||
if (useMock) {
|
fusedLocationClient.lastLocation
|
||||||
mock = MockLocation(locationManager)
|
.addOnSuccessListener { location : android.location.Location? ->
|
||||||
mock.setMockLocation(
|
if (useMock) {
|
||||||
homeLocation.latitude,
|
mock = MockLocation(locationManager)
|
||||||
homeLocation.longitude
|
mock.setMockLocation(
|
||||||
)
|
location?.latitude ?: homeLocation.latitude,
|
||||||
}
|
location?.longitude ?: homeLocation.longitude
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
CheckPermissionScreen()
|
CheckPermissionScreen()
|
||||||
@@ -165,11 +165,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
val step: StepData? by stepData.observeAsState()
|
val step: StepData? by stepData.observeAsState()
|
||||||
val nextStep: StepData? by nextStepData.observeAsState()
|
val nextStep: StepData? by nextStepData.observeAsState()
|
||||||
|
|
||||||
fun openSheet() {
|
|
||||||
scope.launch { scaffoldState.bottomSheetState.expand() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun closeSheet() {
|
fun closeSheet() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
scaffoldState.bottomSheetState.partialExpand()
|
scaffoldState.bottomSheetState.partialExpand()
|
||||||
@@ -236,13 +231,13 @@ class MainActivity : ComponentActivity() {
|
|||||||
if (isNavigating()) {
|
if (isNavigating()) {
|
||||||
updateLocation(currentLocation, navigationViewModel)
|
updateLocation(currentLocation, navigationViewModel)
|
||||||
stepData.value = currentStep()
|
stepData.value = currentStep()
|
||||||
if (route.currentManeuverIndex + 1 <= route.maneuvers.size) {
|
if (route.currentStep + 1 <= legs.steps.size) {
|
||||||
nextStepData.value = nextStep()
|
nextStepData.value = nextStep()
|
||||||
}
|
}
|
||||||
if (routeState.maneuverType == 39
|
if (routeState.maneuverType == 39
|
||||||
&& leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE
|
&& leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE
|
||||||
) {
|
) {
|
||||||
stopNavigation()
|
// stopNavigation()
|
||||||
routeState = routeState.copy(arrived = true)
|
routeState = routeState.copy(arrived = true)
|
||||||
routeData.value = ""
|
routeData.value = ""
|
||||||
}
|
}
|
||||||
@@ -302,20 +297,21 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
fun simulate() = GlobalScope.async {
|
fun simulate() = GlobalScope.async {
|
||||||
for ((_, loc) in routeModel.route.waypoints.withIndex()) {
|
for ((index, step) in routeModel.legs.steps.withIndex()) {
|
||||||
if (routeModel.isNavigating()) {
|
for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) {
|
||||||
mock.setMockLocation(loc[1], loc[0])
|
mock.setMockLocation(waypoint[1], waypoint[0])
|
||||||
delay(500L) //
|
delay(600L) //
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for ((index, loc) in routeModel.route.waypoints.withIndex()) {
|
for ((index, step) in routeModel.legs.steps.withIndex()) {
|
||||||
if (index > 300) {
|
println("${step.maneuver.waypoints.size}")
|
||||||
routeModel.updateLocation(location(loc[0], loc[1]), navigationViewModel)
|
for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) {
|
||||||
|
routeModel.updateLocation(location(waypoint[0], waypoint[1]), navigationViewModel)
|
||||||
routeModel.currentStep()
|
routeModel.currentStep()
|
||||||
if (routeModel.route.currentManeuverIndex + 1 <= routeModel.route.maneuvers.size) {
|
if (index + 1 <= routeModel.legs.steps.size) {
|
||||||
nextStepData.value = routeModel.nextStep()
|
nextStepData.value = routeModel.nextStep()
|
||||||
}
|
}
|
||||||
println(routeModel.routeState.maneuverType)
|
println(routeModel.routeState.maneuverType)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ fun NavigationSheet(
|
|||||||
simulateNavigation()
|
simulateNavigation()
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.assistant_navigation_48px),
|
painter = painterResource(id = R.drawable.navigation_48px),
|
||||||
"Simulate",
|
"Simulate",
|
||||||
modifier = Modifier.size(24.dp, 24.dp),
|
modifier = Modifier.size(24.dp, 24.dp),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ fun SearchBar(
|
|||||||
SearchBarDefaults.InputField(
|
SearchBarDefaults.InputField(
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_search_black36dp),
|
painter = painterResource(id = R.drawable.search_48px),
|
||||||
"Search",
|
"Search",
|
||||||
modifier = Modifier.size(24.dp, 24.dp),
|
modifier = Modifier.size(24.dp, 24.dp),
|
||||||
)
|
)
|
||||||
|
|||||||
19
app/src/main/res/xml/automotive_app_desc.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<automotiveApp>
|
||||||
|
<uses name="template" />
|
||||||
|
</automotiveApp>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
4
automotive/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Navigation</string>
|
||||||
|
</resources>
|
||||||
19
automotive/src/main/res/xml/automotive_app_desc.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<automotiveApp>
|
||||||
|
<uses name="template" />
|
||||||
|
</automotiveApp>
|
||||||
18
automotive/src/main/res/xml/file_provider_paths.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<paths>
|
||||||
|
<files-path name="res" path="/res"/>
|
||||||
|
</paths>
|
||||||
BIN
common/car/src/main/ic_launcher-playstore.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
@@ -300,7 +300,7 @@ class SurfaceRenderer(
|
|||||||
with(routeModel) {
|
with(routeModel) {
|
||||||
routeData.value = route.routeGeoJson
|
routeData.value = route.routeGeoJson
|
||||||
centerLocation = route.centerLocation
|
centerLocation = route.centerLocation
|
||||||
previewDistance = route.distance
|
previewDistance = route.summary!!.distance
|
||||||
}
|
}
|
||||||
updateCameraPosition(
|
updateCameraPosition(
|
||||||
0.0,
|
0.0,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.kouros.navigation.car.map
|
package com.kouros.navigation.car.map
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.location.Location
|
import android.location.Location
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.compose.foundation.Canvas
|
import androidx.compose.foundation.Canvas
|
||||||
@@ -15,6 +16,7 @@ import androidx.compose.runtime.MutableState
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.drawscope.scale
|
import androidx.compose.ui.graphics.drawscope.scale
|
||||||
@@ -115,41 +117,41 @@ fun MapLibre(
|
|||||||
fun RouteLayer(routeData: String?) {
|
fun RouteLayer(routeData: String?) {
|
||||||
if (routeData != null && routeData.isNotEmpty()) {
|
if (routeData != null && routeData.isNotEmpty()) {
|
||||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||||
LineLayer(
|
LineLayer(
|
||||||
id = "routes-casing",
|
id = "routes-casing",
|
||||||
source = routes,
|
source = routes,
|
||||||
color = const(Color.White),
|
color = const(Color.White),
|
||||||
width =
|
width =
|
||||||
interpolate(
|
interpolate(
|
||||||
type = exponential(1.2f),
|
type = exponential(1.2f),
|
||||||
input = zoom(),
|
input = zoom(),
|
||||||
5 to const(0.4.dp),
|
5 to const(0.4.dp),
|
||||||
6 to const(0.8.dp),
|
6 to const(0.8.dp),
|
||||||
7 to const(2.0.dp),
|
7 to const(2.0.dp),
|
||||||
20 to const(24.dp),
|
20 to const(24.dp),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
LineLayer(
|
LineLayer(
|
||||||
id = "routes",
|
id = "routes",
|
||||||
source = routes,
|
source = routes,
|
||||||
color = const(RouteColor),
|
color = const(RouteColor),
|
||||||
width =
|
width =
|
||||||
interpolate(
|
interpolate(
|
||||||
type = exponential(1.2f),
|
type = exponential(1.2f),
|
||||||
input = zoom(),
|
input = zoom(),
|
||||||
5 to const(0.4.dp),
|
5 to const(0.4.dp),
|
||||||
6 to const(0.7.dp),
|
6 to const(0.7.dp),
|
||||||
7 to const(1.75.dp),
|
7 to const(1.75.dp),
|
||||||
20 to const(22.dp),
|
20 to const(22.dp),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AmenityLayer(routeData: String?) {
|
fun AmenityLayer(routeData: String?) {
|
||||||
if (routeData != null && routeData.isNotEmpty()) {
|
if (routeData != null && routeData.isNotEmpty()) {
|
||||||
val color = if (routeData.contains(Constants.PHARMACY)) {
|
val color = if (routeData.contains(Constants.PHARMACY)) {
|
||||||
const(Color.Red)
|
const(Color.Red)
|
||||||
} else {
|
} else {
|
||||||
const(Color.Green)
|
const(Color.Green)
|
||||||
@@ -164,6 +166,7 @@ fun AmenityLayer(routeData: String?) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BuildingLayer(tiles: Source) {
|
fun BuildingLayer(tiles: Source) {
|
||||||
Anchor.Replace("building-3d") {
|
Anchor.Replace("building-3d") {
|
||||||
@@ -177,7 +180,13 @@ fun BuildingLayer(tiles: Source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DrawNavigationImages(padding: PaddingValues, speed: Float?, maxSpeed: Int, width: Int, height: Int) {
|
fun DrawNavigationImages(
|
||||||
|
padding: PaddingValues,
|
||||||
|
speed: Float?,
|
||||||
|
maxSpeed: Int,
|
||||||
|
width: Int,
|
||||||
|
height: Int
|
||||||
|
) {
|
||||||
NavigationImage(padding, width, height)
|
NavigationImage(padding, width, height)
|
||||||
CurrentSpeed(width, height, speed)
|
CurrentSpeed(width, height, speed)
|
||||||
if (speed != null && maxSpeed > 0 && (speed * 3.6) > maxSpeed) {
|
if (speed != null && maxSpeed > 0 && (speed * 3.6) > maxSpeed) {
|
||||||
@@ -187,7 +196,7 @@ fun DrawNavigationImages(padding: PaddingValues, speed: Float?, maxSpeed: Int, w
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NavigationImage(padding: PaddingValues, width: Int, height: Int) {
|
fun NavigationImage(padding: PaddingValues, width: Int, height: Int) {
|
||||||
val imageSize = (height / 6)
|
val imageSize = (height / 8)
|
||||||
val color = remember { NavigationColor }
|
val color = remember { NavigationColor }
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(padding)) {
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(padding)) {
|
||||||
Canvas(
|
Canvas(
|
||||||
@@ -195,14 +204,15 @@ fun NavigationImage(padding: PaddingValues, width: Int, height: Int) {
|
|||||||
.size(imageSize.dp, imageSize.dp)
|
.size(imageSize.dp, imageSize.dp)
|
||||||
) {
|
) {
|
||||||
scale(scaleX = 1f, scaleY = 0.7f) {
|
scale(scaleX = 1f, scaleY = 0.7f) {
|
||||||
drawCircle(Color.DarkGray.copy(alpha = 0.2f))
|
drawCircle(Color.DarkGray.copy(alpha = 0.3f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.navigation),
|
painter = painterResource(id = R.drawable.navigation_48px),
|
||||||
"Navigation",
|
"Navigation",
|
||||||
tint = color.copy(alpha = 1f),
|
tint = color.copy(alpha = 0.7f),
|
||||||
modifier = Modifier.size(imageSize.dp, imageSize.dp),
|
modifier = Modifier.size(imageSize.dp, imageSize.dp)
|
||||||
|
.scale(scaleX = 1f, scaleY = 0.7f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class RouteCarModel() : RouteModel() {
|
|||||||
|
|
||||||
val dismissAction: Action = createToastAction(
|
val dismissAction: Action = createToastAction(
|
||||||
carContext,
|
carContext,
|
||||||
R.string.speed_camera, R.string.exit_action_title,
|
R.string.exit_action_title, R.string.exit_action_title,
|
||||||
FLAG_DEFAULT
|
FLAG_DEFAULT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ import com.kouros.navigation.data.Place
|
|||||||
import com.kouros.navigation.data.nominatim.SearchResult
|
import com.kouros.navigation.data.nominatim.SearchResult
|
||||||
import com.kouros.navigation.data.overpass.Elements
|
import com.kouros.navigation.data.overpass.Elements
|
||||||
import com.kouros.navigation.model.ViewModel
|
import com.kouros.navigation.model.ViewModel
|
||||||
|
import com.kouros.navigation.utils.bearing
|
||||||
import com.kouros.navigation.utils.location
|
import com.kouros.navigation.utils.location
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
class NavigationScreen(
|
class NavigationScreen(
|
||||||
carContext: CarContext,
|
carContext: CarContext,
|
||||||
@@ -294,7 +296,7 @@ class NavigationScreen(
|
|||||||
CarIcon.Builder(
|
CarIcon.Builder(
|
||||||
IconCompat.createWithResource(
|
IconCompat.createWithResource(
|
||||||
carContext,
|
carContext,
|
||||||
R.drawable.assistant_navigation_48px
|
R.drawable.navigation_48px
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
@@ -328,7 +330,7 @@ class NavigationScreen(
|
|||||||
|
|
||||||
private fun searchAction(): Action {
|
private fun searchAction(): Action {
|
||||||
return Action.Builder()
|
return Action.Builder()
|
||||||
.setIcon(routeModel.createCarIcon(carContext, R.drawable.ic_search_black36dp))
|
.setIcon(routeModel.createCarIcon(carContext, R.drawable.search_48px))
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
startSearchScreen()
|
startSearchScreen()
|
||||||
}
|
}
|
||||||
@@ -337,7 +339,7 @@ class NavigationScreen(
|
|||||||
|
|
||||||
private fun settingsAction(): Action {
|
private fun settingsAction(): Action {
|
||||||
return Action.Builder()
|
return Action.Builder()
|
||||||
.setIcon(routeModel.createCarIcon(carContext, R.drawable.settings_24px))
|
.setIcon(routeModel.createCarIcon(carContext, R.drawable.settings_applications_48px))
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
screenManager.push(SettingsScreen(carContext))
|
screenManager.push(SettingsScreen(carContext))
|
||||||
}
|
}
|
||||||
@@ -488,10 +490,15 @@ class NavigationScreen(
|
|||||||
it.distance = distance.toDouble()
|
it.distance = distance.toDouble()
|
||||||
updatedCameras.add(it)
|
updatedCameras.add(it)
|
||||||
}
|
}
|
||||||
val sortedList = updatedCameras.sortedWith(compareBy { it.distance })
|
val sortedList = updatedCameras.sortedWith(compareBy { it.distance })
|
||||||
val camera = sortedList.first()
|
val camera = sortedList.first()
|
||||||
if (camera.distance < 80) {
|
val bearingSpeedCamera = location.bearingTo(location(camera.lon!!, camera.lat!!))
|
||||||
routeModel.showSpeedCamera(carContext, camera.distance, camera.tags.maxspeed)
|
val bearingRoute = surfaceRenderer.lastLocation.bearingTo(location)
|
||||||
|
|
||||||
|
if (camera.distance < 80
|
||||||
|
&& (bearingSpeedCamera.absoluteValue - bearingRoute.absoluteValue).absoluteValue < 15.0
|
||||||
|
) {
|
||||||
|
routeModel.showSpeedCamera(carContext, camera.distance, camera.tags.maxspeed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ class PlaceListScreen(
|
|||||||
.setIcon(
|
.setIcon(
|
||||||
RouteCarModel().createCarIcon(
|
RouteCarModel().createCarIcon(
|
||||||
carContext,
|
carContext,
|
||||||
R.drawable.ic_delete_foreground
|
R.drawable.ic_pan_24
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class RoutePreviewScreen(
|
|||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val message = if (routeModel.isNavigating() && routeModel.route.waypoints.isNotEmpty()) {
|
val message = if (routeModel.isNavigating() && routeModel.route.waypoints!!.isNotEmpty()) {
|
||||||
createRouteText()
|
createRouteText()
|
||||||
} else {
|
} else {
|
||||||
CarText.Builder("Wait")
|
CarText.Builder("Wait")
|
||||||
@@ -143,7 +143,7 @@ class RoutePreviewScreen(
|
|||||||
.getString(R.string.favorites)
|
.getString(R.string.favorites)
|
||||||
else
|
else
|
||||||
carContext.getString(
|
carContext.getString(
|
||||||
R.string.not_favorite_toast_msg
|
R.string.favorites
|
||||||
),
|
),
|
||||||
CarToast.LENGTH_SHORT
|
CarToast.LENGTH_SHORT
|
||||||
)
|
)
|
||||||
@@ -165,7 +165,7 @@ class RoutePreviewScreen(
|
|||||||
CarIcon.Builder(
|
CarIcon.Builder(
|
||||||
IconCompat.createWithResource(
|
IconCompat.createWithResource(
|
||||||
carContext,
|
carContext,
|
||||||
R.drawable.ic_delete_foreground
|
R.drawable.ic_pan_24
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
@@ -173,8 +173,8 @@ class RoutePreviewScreen(
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
private fun createRouteText(): CarText {
|
private fun createRouteText(): CarText {
|
||||||
val time = routeModel.route.summary.time
|
val time = routeModel.route.summary!!.duration
|
||||||
val length = BigDecimal(routeModel.route.distance).setScale(1, RoundingMode.HALF_EVEN)
|
val length = BigDecimal(routeModel.route.summary!!.distance).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
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class SearchScreen(
|
|||||||
R.drawable.ic_favorite_white_24dp
|
R.drawable.ic_favorite_white_24dp
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
R.drawable.navigation
|
R.drawable.navigation_48px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CarIcon.Builder(
|
return CarIcon.Builder(
|
||||||
|
|||||||
10
common/car/src/main/res/drawable/navigation_48px.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M190,840L160,810L480,80L800,810L770,840L480,708L190,840Z"/>
|
||||||
|
</vector>
|
||||||
@@ -179,3 +179,6 @@ object Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum class RouteEngine {
|
||||||
|
VALHALLA, OSRM, GRAPHHOPPER
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ abstract class NavigationRepository {
|
|||||||
val route = getRoute(currentLocation, location, searchFilter)
|
val route = getRoute(currentLocation, location, searchFilter)
|
||||||
val routeModel = RouteModel()
|
val routeModel = RouteModel()
|
||||||
routeModel.startNavigation(route)
|
routeModel.startNavigation(route)
|
||||||
return routeModel.route.distance
|
return routeModel.route.summary!!.distance
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchPlaces(search: String, location: Location) : String {
|
fun searchPlaces(search: String, location: Location) : String {
|
||||||
|
|||||||
@@ -2,125 +2,97 @@ package com.kouros.navigation.data
|
|||||||
|
|
||||||
import android.location.Location
|
import android.location.Location
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.kouros.navigation.data.valhalla.Maneuvers
|
import com.kouros.navigation.data.osrm.OsrmResponse
|
||||||
import com.kouros.navigation.data.valhalla.Summary
|
import com.kouros.navigation.data.osrm.OsrmRoute
|
||||||
import com.kouros.navigation.data.valhalla.Trip
|
import com.kouros.navigation.data.route.Leg
|
||||||
import com.kouros.navigation.data.valhalla.ValhallaJson
|
import com.kouros.navigation.data.route.Step
|
||||||
|
import com.kouros.navigation.data.route.Summary
|
||||||
|
import com.kouros.navigation.data.valhalla.ValhallaResponse
|
||||||
|
import com.kouros.navigation.data.valhalla.ValhallaRoute
|
||||||
import com.kouros.navigation.utils.GeoUtils.createCenterLocation
|
import com.kouros.navigation.utils.GeoUtils.createCenterLocation
|
||||||
import com.kouros.navigation.utils.GeoUtils.createLineStringCollection
|
|
||||||
import com.kouros.navigation.utils.GeoUtils.decodePolyline
|
|
||||||
import com.kouros.navigation.utils.location
|
import com.kouros.navigation.utils.location
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
import org.maplibre.geojson.Point
|
import org.maplibre.geojson.Point
|
||||||
|
|
||||||
|
|
||||||
data class Route(
|
data class Route(
|
||||||
/**
|
|
||||||
* A Leg is a route between only two waypoints.
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
val maneuvers: List<Maneuvers>,
|
|
||||||
|
|
||||||
/**
|
val routeEngine: Int,
|
||||||
* The distance traveled from origin to destination.
|
val summary: Summary?,
|
||||||
*
|
val legs: List<Leg>?,
|
||||||
* @return a double number with unit meters
|
val routeGeoJson: String = "",
|
||||||
* @since 1.0.0
|
val centerLocation : Location = location(0.0, 0.0),
|
||||||
*/
|
var currentStep : Int = 0,
|
||||||
val distance: Double,
|
val waypoints: List<List<Double>>?,
|
||||||
|
) {
|
||||||
|
|
||||||
/**
|
data class Builder (
|
||||||
* List of [List<Double>] objects. Each `waypoint` is an input coordinate
|
|
||||||
* snapped to the road and path network. The `waypoint` appear in the list in the order of
|
|
||||||
* the input coordinates.
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
|
||||||
val waypoints: List<List<Double>>,
|
|
||||||
|
|
||||||
/**
|
var routeEngine : Int = RouteEngine.VALHALLA.ordinal,
|
||||||
* List of [List<Point>] objects. Each `Point` is an input coordinate
|
var summary: Summary? = null,
|
||||||
* snapped to the road and path network. The `waypoint` appear in the list in the order of
|
var legs: List<Leg>? = null,
|
||||||
* the input coordinates.
|
var routeGeoJson: String = "",
|
||||||
*
|
var centerLocation: Location = location(0.0, 0.0),
|
||||||
* @since 1.0.0
|
var waypoints : List<List<Double>>? = null,) {
|
||||||
*/
|
|
||||||
val pointLocations: List<Point>,
|
|
||||||
|
|
||||||
val summary: Summary,
|
|
||||||
|
|
||||||
val trip: Trip,
|
|
||||||
|
|
||||||
val time: Double,
|
|
||||||
|
|
||||||
val routeGeoJson: String,
|
|
||||||
|
|
||||||
val currentManeuverIndex : Int,
|
|
||||||
|
|
||||||
val centerLocation: Location
|
|
||||||
|
|
||||||
) {
|
|
||||||
|
|
||||||
class Builder {
|
|
||||||
private lateinit var maneuvers: List<Maneuvers>
|
|
||||||
private var distance: Double = 0.0
|
|
||||||
private var time: Double = 0.0
|
|
||||||
private lateinit var waypoints: List<List<Double>>
|
|
||||||
private lateinit var pointLocations: List<Point>
|
|
||||||
private lateinit var summary: Summary
|
|
||||||
private lateinit var trip: Trip
|
|
||||||
private var routeGeoJson = ""
|
|
||||||
private var centerLocation = location(0.0, 0.0)
|
|
||||||
|
|
||||||
|
fun routeType (routeEngine: Int) = apply {this.routeEngine = routeEngine }
|
||||||
|
fun summary(summary: Summary) = apply { this.summary = summary }
|
||||||
|
fun legs(legs: List<Leg>) = apply { this.legs = legs }
|
||||||
|
fun routeGeoJson(routeGeoJson: String) = apply {
|
||||||
|
this.routeGeoJson = routeGeoJson
|
||||||
|
centerLocation = createCenterLocation(routeGeoJson)
|
||||||
|
}
|
||||||
|
fun waypoints(waypoints: List<List<Double>>) = apply { this.waypoints = waypoints }
|
||||||
fun route(route: String) = apply {
|
fun route(route: String) = apply {
|
||||||
if (route.isNotEmpty() && route != "[]") {
|
if (route.isNotEmpty() && route != "[]") {
|
||||||
val gson = GsonBuilder().serializeNulls().create()
|
val gson = GsonBuilder().serializeNulls().create()
|
||||||
val routeJson = gson.fromJson(route, ValhallaJson::class.java)
|
if (routeEngine == RouteEngine.VALHALLA.ordinal) {
|
||||||
trip = routeJson.trip
|
val jsonObject: Map<String, JsonElement> = Json.parseToJsonElement(route).jsonObject
|
||||||
|
val routeJson = gson.fromJson(jsonObject["trip"].toString(), ValhallaResponse::class.java)
|
||||||
|
ValhallaRoute().mapJsonToValhalla(routeJson, this)
|
||||||
|
} else {
|
||||||
|
val osrmJson = gson.fromJson(route, OsrmResponse::class.java)
|
||||||
|
OsrmRoute().mapToOsrm(osrmJson, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(): Route {
|
fun build(): Route {
|
||||||
maneuvers = trip.legs[0].maneuvers
|
|
||||||
summary = trip.summary
|
|
||||||
distance = summary.length
|
|
||||||
time = summary.time
|
|
||||||
waypoints = decodePolyline(trip.legs[0].shape)
|
|
||||||
val points = mutableListOf<Point>()
|
|
||||||
for (loc in waypoints) {
|
|
||||||
val point = Point.fromLngLat(loc[0], loc[1])
|
|
||||||
points.add(point)
|
|
||||||
}
|
|
||||||
pointLocations = points
|
|
||||||
routeGeoJson = createLineStringCollection( waypoints)
|
|
||||||
centerLocation = createCenterLocation(routeGeoJson)
|
|
||||||
return Route(
|
return Route(
|
||||||
maneuvers,
|
routeEngine = this.routeEngine,
|
||||||
distance,
|
summary = this.summary,
|
||||||
waypoints,
|
legs = this.legs,
|
||||||
pointLocations,
|
waypoints = this.waypoints,
|
||||||
summary,
|
routeGeoJson = this.routeGeoJson,
|
||||||
trip,
|
|
||||||
time,
|
|
||||||
routeGeoJson,
|
|
||||||
0,
|
|
||||||
centerLocation
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun maneuverLocations(): List<Point> {
|
fun maneuverLocations(): List<Point> {
|
||||||
return pointLocations
|
val step = currentStep()
|
||||||
|
val waypoints = step.maneuver.waypoints
|
||||||
|
val points = mutableListOf<Point>()
|
||||||
|
for (loc in waypoints) {
|
||||||
|
val point = Point.fromLngLat(loc[0], loc[1])
|
||||||
|
points.add(point)
|
||||||
|
}
|
||||||
|
return points
|
||||||
}
|
}
|
||||||
|
|
||||||
fun currentManeuver(): Maneuvers {
|
fun currentStep(): Step {
|
||||||
return maneuvers[currentManeuverIndex]
|
if (legs != null) {
|
||||||
|
return legs.first().steps[currentStep]
|
||||||
|
} else {
|
||||||
|
throw IndexOutOfBoundsException("No legs available.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun nextManeuver(): Maneuvers {
|
fun nextStep(): Step {
|
||||||
val nextIndex = currentManeuverIndex + 1
|
val nextIndex = currentStep + 1
|
||||||
return if (nextIndex < maneuvers.size) {
|
return if (nextIndex < legs!!.first().steps.size) {
|
||||||
maneuvers[nextIndex]
|
legs.first().steps[currentStep + 1]
|
||||||
} else {
|
} else {
|
||||||
throw IndexOutOfBoundsException("No next maneuver available.")
|
throw IndexOutOfBoundsException("No next maneuver available.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.kouros.navigation.data.osrm
|
|||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
|
||||||
data class OsrmJson (
|
data class OsrmResponse (
|
||||||
|
|
||||||
@SerializedName("code" ) var code : String? = null,
|
@SerializedName("code" ) var code : String? = null,
|
||||||
@SerializedName("routes" ) var routes : ArrayList<Routes> = arrayListOf(),
|
@SerializedName("routes" ) var routes : ArrayList<Routes> = arrayListOf(),
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.kouros.navigation.data.osrm
|
||||||
|
|
||||||
|
import com.kouros.navigation.data.Route
|
||||||
|
import com.kouros.navigation.data.valhalla.ValhallaResponse
|
||||||
|
|
||||||
|
class OsrmRoute {
|
||||||
|
|
||||||
|
fun mapToOsrm(routeJson: OsrmResponse, builder: Route.Builder) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ class Overpass {
|
|||||||
|);
|
|);
|
||||||
|out body;
|
|out body;
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
|
println("way[highway](around:$radius,$linestring)")
|
||||||
return overpassApi(httpURLConnection, searchQuery)
|
return overpassApi(httpURLConnection, searchQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +61,6 @@ class Overpass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun overpassApi(httpURLConnection: HttpURLConnection, searchQuery: String) : List<Elements> {
|
fun overpassApi(httpURLConnection: HttpURLConnection, searchQuery: String) : List<Elements> {
|
||||||
// Send the JSON we created
|
|
||||||
val outputStreamWriter = OutputStreamWriter(httpURLConnection.outputStream)
|
val outputStreamWriter = OutputStreamWriter(httpURLConnection.outputStream)
|
||||||
outputStreamWriter.write(searchQuery)
|
outputStreamWriter.write(searchQuery)
|
||||||
outputStreamWriter.flush()
|
outputStreamWriter.flush()
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.kouros.navigation.data.route
|
||||||
|
|
||||||
|
data class Leg(
|
||||||
|
var steps : List<Step> = arrayListOf()
|
||||||
|
)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.kouros.navigation.data.route
|
||||||
|
|
||||||
|
data class Maneuver(
|
||||||
|
val bearingBefore : Int = 0,
|
||||||
|
val bearingAfter : Int = 0,
|
||||||
|
val type: Int = 0,
|
||||||
|
val waypoints: List<List<Double>>,
|
||||||
|
)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.kouros.navigation.data.route
|
||||||
|
|
||||||
|
class Step(
|
||||||
|
var index : Int = 0,
|
||||||
|
var waypointIndex : Int = 0,
|
||||||
|
val maneuver: Maneuver,
|
||||||
|
val duration: Double = 0.0,
|
||||||
|
val distance: Double = 0.0,
|
||||||
|
val name : String = "",
|
||||||
|
)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.kouros.navigation.data.route
|
||||||
|
|
||||||
|
data class Summary(
|
||||||
|
var duration : Double = 0.0,
|
||||||
|
var distance : Double = 0.0,
|
||||||
|
)
|
||||||
@@ -2,7 +2,6 @@ package com.kouros.navigation.data.valhalla
|
|||||||
|
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
||||||
|
|
||||||
|
|
||||||
@@ -11,7 +10,7 @@ import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
|||||||
data class Legs (
|
data class Legs (
|
||||||
|
|
||||||
@SerializedName("maneuvers" ) var maneuvers : ArrayList<Maneuvers> = arrayListOf(),
|
@SerializedName("maneuvers" ) var maneuvers : ArrayList<Maneuvers> = arrayListOf(),
|
||||||
@SerializedName("summary" ) var summary : Summary = Summary(),
|
@SerializedName("summary" ) var summaryValhalla : SummaryValhalla = SummaryValhalla(),
|
||||||
@SerializedName("shape" ) var shape : String = ""
|
@SerializedName("shape" ) var shape : String = ""
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -2,13 +2,12 @@ package com.kouros.navigation.data.valhalla
|
|||||||
|
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@JsonIgnoreUnknownKeys
|
@JsonIgnoreUnknownKeys
|
||||||
data class Summary (
|
data class SummaryValhalla (
|
||||||
|
|
||||||
@SerializedName("has_time_restrictions" ) var hasTimeRestrictions : Boolean = false,
|
@SerializedName("has_time_restrictions" ) var hasTimeRestrictions : Boolean = false,
|
||||||
@SerializedName("has_toll" ) var hasToll : Boolean = false,
|
@SerializedName("has_toll" ) var hasToll : Boolean = false,
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.kouros.navigation.data.valhalla
|
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
@JsonIgnoreUnknownKeys
|
|
||||||
data class Trip (
|
|
||||||
|
|
||||||
@SerializedName("locations" ) var locations : ArrayList<Locations> = arrayListOf(),
|
|
||||||
@SerializedName("legs" ) var legs : ArrayList<Legs> = arrayListOf(),
|
|
||||||
@SerializedName("summary" ) var summary : Summary = Summary(),
|
|
||||||
@SerializedName("status_message" ) var statusMessage : String = "",
|
|
||||||
@SerializedName("status" ) var status : Int = 0,
|
|
||||||
@SerializedName("units" ) var units : String = "",
|
|
||||||
@SerializedName("language" ) var language : String = "",
|
|
||||||
|
|
||||||
)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.kouros.navigation.data.valhalla
|
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
@JsonIgnoreUnknownKeys
|
|
||||||
data class ValhallaJson (
|
|
||||||
|
|
||||||
@SerializedName("trip" ) var trip : Trip = Trip(),
|
|
||||||
@SerializedName("id" ) var id : String = ""
|
|
||||||
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.kouros.navigation.data.valhalla
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.json.JsonIgnoreUnknownKeys
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
@JsonIgnoreUnknownKeys
|
||||||
|
data class ValhallaResponse(
|
||||||
|
|
||||||
|
@SerializedName("locations") var locations: ArrayList<Locations> = arrayListOf(),
|
||||||
|
@SerializedName("legs") var legs: ArrayList<Legs> = arrayListOf(),
|
||||||
|
@SerializedName("summary") var summaryValhalla: SummaryValhalla = SummaryValhalla(),
|
||||||
|
@SerializedName("status_message") var statusMessage: String = "",
|
||||||
|
@SerializedName("status") var status: Int = 0,
|
||||||
|
@SerializedName("units") var units: String = "",
|
||||||
|
@SerializedName("language") var language: String = "",
|
||||||
|
|
||||||
|
)
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.kouros.navigation.data.valhalla
|
||||||
|
|
||||||
|
import com.kouros.navigation.data.Route
|
||||||
|
import com.kouros.navigation.data.route.Leg
|
||||||
|
import com.kouros.navigation.data.route.Maneuver
|
||||||
|
import com.kouros.navigation.data.route.Step
|
||||||
|
import com.kouros.navigation.data.route.Summary
|
||||||
|
import com.kouros.navigation.utils.GeoUtils.createLineStringCollection
|
||||||
|
import com.kouros.navigation.utils.GeoUtils.decodePolyline
|
||||||
|
|
||||||
|
class ValhallaRoute {
|
||||||
|
|
||||||
|
fun mapJsonToValhalla(routeJson: ValhallaResponse, builder: Route.Builder) {
|
||||||
|
val waypoints = decodePolyline(routeJson.legs[0].shape)
|
||||||
|
val summary = Summary()
|
||||||
|
summary.distance = routeJson.summaryValhalla.length
|
||||||
|
summary.duration = routeJson.summaryValhalla.time
|
||||||
|
val steps = mutableListOf<Step>()
|
||||||
|
var stepIndex = 0
|
||||||
|
routeJson.legs[0].maneuvers.forEach {
|
||||||
|
val maneuver = Maneuver(
|
||||||
|
bearingBefore = 0,
|
||||||
|
bearingAfter = it.bearingAfter,
|
||||||
|
type = it.type,
|
||||||
|
waypoints =waypoints.subList(it.beginShapeIndex, it.endShapeIndex+1)
|
||||||
|
)
|
||||||
|
var name = ""
|
||||||
|
if (it.streetNames != null && it.streetNames.isNotEmpty()) {
|
||||||
|
name = it.streetNames[0]
|
||||||
|
}
|
||||||
|
val step = Step( index = stepIndex, name = name, distance = it.length, duration = it.time, maneuver = maneuver)
|
||||||
|
steps.add(step)
|
||||||
|
stepIndex += 1
|
||||||
|
}
|
||||||
|
val leg = Leg(steps)
|
||||||
|
builder
|
||||||
|
.routeType(1)
|
||||||
|
.summary(summary)
|
||||||
|
.routeGeoJson(createLineStringCollection(waypoints))
|
||||||
|
.legs(listOf(leg))
|
||||||
|
.waypoints(waypoints)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.kouros.navigation.data.ManeuverType
|
|||||||
import com.kouros.navigation.data.Place
|
import com.kouros.navigation.data.Place
|
||||||
import com.kouros.navigation.data.Route
|
import com.kouros.navigation.data.Route
|
||||||
import com.kouros.navigation.data.StepData
|
import com.kouros.navigation.data.StepData
|
||||||
|
import com.kouros.navigation.data.route.Leg
|
||||||
import com.kouros.navigation.utils.location
|
import com.kouros.navigation.utils.location
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -24,16 +25,11 @@ open class RouteModel() {
|
|||||||
val destination: Place = Place(),
|
val destination: Place = Place(),
|
||||||
val arrived: Boolean = false,
|
val arrived: Boolean = false,
|
||||||
val maneuverType: Int = 0,
|
val maneuverType: Int = 0,
|
||||||
var currentShapeIndex: Int = 0,
|
|
||||||
var distanceToStepEnd: Float = 0F,
|
|
||||||
var beginIndex: Int = 0,
|
|
||||||
var endIndex: Int = 0,
|
|
||||||
val travelMessage: String = "",
|
val travelMessage: String = "",
|
||||||
// max speed for street (maneuver)
|
val lastSpeedLocation: Location = location(0.0, 0.0),
|
||||||
val lastSpeedIndex: Int = 0,
|
val lastSpeedIndex: Int = 0,
|
||||||
val maxSpeed: Int = 0,
|
val maxSpeed: Int = 0,
|
||||||
|
)
|
||||||
)
|
|
||||||
|
|
||||||
var routeState = RouteState()
|
var routeState = RouteState()
|
||||||
|
|
||||||
@@ -43,6 +39,10 @@ open class RouteModel() {
|
|||||||
routeState = routeState.copy(route = value)
|
routeState = routeState.copy(route = value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val legs: Leg
|
||||||
|
get() = routeState.route!!.legs!!.first()
|
||||||
|
|
||||||
fun startNavigation(routeString: String) {
|
fun startNavigation(routeString: String) {
|
||||||
val newRoute = Route.Builder()
|
val newRoute = Route.Builder()
|
||||||
.route(routeString)
|
.route(routeString)
|
||||||
@@ -59,40 +59,41 @@ open class RouteModel() {
|
|||||||
isNavigating = false,
|
isNavigating = false,
|
||||||
arrived = false,
|
arrived = false,
|
||||||
maneuverType = 0,
|
maneuverType = 0,
|
||||||
currentShapeIndex = 0,
|
|
||||||
distanceToStepEnd = 0F,
|
|
||||||
beginIndex = 0,
|
|
||||||
endIndex = 0
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
fun updateLocation(location: Location, viewModel: ViewModel) {
|
fun updateLocation(location: Location, viewModel: ViewModel) {
|
||||||
var nearestDistance = 100000.0f
|
findStep(location)
|
||||||
var newShapeIndex = -1
|
|
||||||
// find nearest waypoint and current shape index
|
|
||||||
// start search at last shape index
|
|
||||||
for (i in routeState.currentShapeIndex..<route.waypoints.size) {
|
|
||||||
val waypoint = route.waypoints[i]
|
|
||||||
val distance = location.distanceTo(location(waypoint[0], waypoint[1]))
|
|
||||||
if (distance < nearestDistance) {
|
|
||||||
nearestDistance = distance
|
|
||||||
newShapeIndex = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// find maneuver
|
|
||||||
// calculate distance to step end
|
|
||||||
findManeuver(newShapeIndex)
|
|
||||||
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
updateSpeedLimit(location, viewModel)
|
updateSpeedLimit(location, viewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun findStep(location: Location) {
|
||||||
|
var nearestDistance = 100000.0f
|
||||||
|
for ((index, step) in legs.steps.withIndex()) {
|
||||||
|
if (index >= route.currentStep && nearestDistance > 0) {
|
||||||
|
for ((wayIndex, waypoint) in step.maneuver.waypoints.withIndex()) {
|
||||||
|
if (wayIndex >= step.waypointIndex) {
|
||||||
|
val distance = location.distanceTo(location(waypoint[0], waypoint[1]))
|
||||||
|
if (distance < nearestDistance) {
|
||||||
|
nearestDistance = distance
|
||||||
|
route.currentStep = step.index
|
||||||
|
step.waypointIndex = wayIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun updateSpeedLimit(location: Location, viewModel: ViewModel) {
|
fun updateSpeedLimit(location: Location, viewModel: ViewModel) {
|
||||||
// speed limit for each maneuver index
|
// speed limit
|
||||||
if (routeState.lastSpeedIndex < route.currentManeuverIndex) {
|
val distance = routeState.lastSpeedLocation.distanceTo(location)
|
||||||
routeState = routeState.copy(lastSpeedIndex = route.currentManeuverIndex)
|
if (distance > 500 || routeState.lastSpeedIndex < route.currentStep) {
|
||||||
|
routeState = routeState.copy(lastSpeedIndex = route.currentStep)
|
||||||
|
routeState = routeState.copy(lastSpeedLocation = location)
|
||||||
val elements = viewModel.getMaxSpeed(location)
|
val elements = viewModel.getMaxSpeed(location)
|
||||||
elements.forEach {
|
elements.forEach {
|
||||||
if (it.tags.name != null && it.tags.maxspeed != null) {
|
if (it.tags.name != null && it.tags.maxspeed != null) {
|
||||||
@@ -103,52 +104,30 @@ open class RouteModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findManeuver(newShapeIndex: Int) {
|
|
||||||
for (i in route.currentManeuverIndex..<route.maneuvers.size) {
|
|
||||||
val maneuver = route.maneuvers[i]
|
|
||||||
if (maneuver.beginShapeIndex <= newShapeIndex && maneuver.endShapeIndex >= newShapeIndex) {
|
|
||||||
route = route.copy(currentManeuverIndex = i)
|
|
||||||
routeState.apply {
|
|
||||||
currentShapeIndex = newShapeIndex
|
|
||||||
beginIndex = maneuver.beginShapeIndex
|
|
||||||
endIndex = maneuver.endShapeIndex
|
|
||||||
distanceToStepEnd = 0F
|
|
||||||
// calculate shape distance to step end
|
|
||||||
for (j in newShapeIndex + 1..maneuver.endShapeIndex) {
|
|
||||||
val loc1 = location(route!!.waypoints[j - 1][0], route.waypoints[j - 1][1])
|
|
||||||
val loc2 = location(route.waypoints[j][0], route.waypoints[j][1])
|
|
||||||
distanceToStepEnd += loc1.distanceTo(loc2)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun currentStep(): StepData {
|
fun currentStep(): StepData {
|
||||||
val currentManeuver = route.currentManeuver()
|
val currentStep = route.currentStep()
|
||||||
// Determine if we should display the current or the next maneuver
|
// Determine if we should display the current or the next maneuver
|
||||||
val distanceToNextStep = leftStepDistance()
|
val distanceToNextStep = leftStepDistance()
|
||||||
val isNearNextManeuver = distanceToNextStep in 0.0..NEXT_STEP_THRESHOLD
|
val isNearNextManeuver = distanceToNextStep in 0.0..NEXT_STEP_THRESHOLD
|
||||||
val shouldAdvance =
|
val shouldAdvance =
|
||||||
isNearNextManeuver && route.currentManeuverIndex < (route.maneuvers.size)
|
isNearNextManeuver && route.currentStep < (route.legs!!.first().steps.size)
|
||||||
|
|
||||||
// Determine the maneuver type and corresponding icon
|
// Determine the maneuver type and corresponding icon
|
||||||
var maneuverType = if (hasArrived(currentManeuver.type)) {
|
var maneuverType = if (hasArrived(currentStep.maneuver.type)) {
|
||||||
currentManeuver.type
|
currentStep.maneuver.type
|
||||||
} else {
|
} else {
|
||||||
ManeuverType.None.value
|
ManeuverType.None.value
|
||||||
}
|
}
|
||||||
// Get the single, correct maneuver for this state
|
// Get the single, correct maneuver for this state
|
||||||
val relevantManeuver = if (shouldAdvance) {
|
val relevantManeuver = if (shouldAdvance) {
|
||||||
route.nextManeuver() // This advances the route's state
|
route.nextStep() // This advances the route's state
|
||||||
} else {
|
} else {
|
||||||
route.currentManeuver()
|
route.currentStep()
|
||||||
}
|
}
|
||||||
// Safely get the street name from the maneuver
|
// Safely get the street name from the maneuver
|
||||||
val streetName = relevantManeuver.streetNames?.firstOrNull() ?: ""
|
val streetName = relevantManeuver.name
|
||||||
if (shouldAdvance) {
|
if (shouldAdvance) {
|
||||||
maneuverType = relevantManeuver.type
|
maneuverType = relevantManeuver.maneuver.type
|
||||||
}
|
}
|
||||||
val maneuverIconPair = maneuverIcon(maneuverType)
|
val maneuverIconPair = maneuverIcon(maneuverType)
|
||||||
routeState = routeState.copy(maneuverType = maneuverIconPair.first)
|
routeState = routeState.copy(maneuverType = maneuverIconPair.first)
|
||||||
@@ -165,8 +144,8 @@ open class RouteModel() {
|
|||||||
|
|
||||||
|
|
||||||
fun nextStep(): StepData {
|
fun nextStep(): StepData {
|
||||||
val maneuver = route.nextManeuver()
|
val step = route.nextStep()
|
||||||
val maneuverType = maneuver.type
|
val maneuverType = step.maneuver.type
|
||||||
val distanceLeft = leftStepDistance()
|
val distanceLeft = leftStepDistance()
|
||||||
var text = ""
|
var text = ""
|
||||||
|
|
||||||
@@ -175,8 +154,8 @@ open class RouteModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) {
|
if (step.name.isNotEmpty()) {
|
||||||
text = maneuver.streetNames[0]
|
text = step.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,18 +174,16 @@ open class RouteModel() {
|
|||||||
|
|
||||||
fun travelLeftTime(): Double {
|
fun travelLeftTime(): Double {
|
||||||
var timeLeft = 0.0
|
var timeLeft = 0.0
|
||||||
for (i in route.currentManeuverIndex + 1..<route.maneuvers.size) {
|
for (i in route.currentStep + 1..<legs.steps.size) {
|
||||||
val maneuver = route.maneuvers[i]
|
val step = legs.steps[i]
|
||||||
timeLeft += maneuver.time
|
timeLeft += step.duration
|
||||||
}
|
|
||||||
if (routeState.endIndex > 0) {
|
|
||||||
val maneuver = route.currentManeuver()
|
|
||||||
val curTime = maneuver.time
|
|
||||||
val percent =
|
|
||||||
100 * (routeState.endIndex - routeState.currentShapeIndex) / (routeState.endIndex - routeState.beginIndex)
|
|
||||||
val time = curTime * percent / 100
|
|
||||||
timeLeft += time
|
|
||||||
}
|
}
|
||||||
|
val step = route.nextStep()
|
||||||
|
val curTime = step.duration
|
||||||
|
val percent =
|
||||||
|
100 * (step.maneuver.waypoints.size - step.waypointIndex) / (step.maneuver.waypoints.size)
|
||||||
|
val time = curTime * percent / 100
|
||||||
|
timeLeft += time
|
||||||
return timeLeft
|
return timeLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,11 +198,11 @@ open class RouteModel() {
|
|||||||
|
|
||||||
/** Returns the current [Step] left distance in m. */
|
/** Returns the current [Step] left distance in m. */
|
||||||
fun leftStepDistance(): Double {
|
fun leftStepDistance(): Double {
|
||||||
val maneuver = route.currentManeuver()
|
val step = route.currentStep()
|
||||||
var leftDistance = maneuver.length
|
var leftDistance = step.distance
|
||||||
if (routeState.endIndex > 0) {
|
val percent =
|
||||||
leftDistance = (routeState.distanceToStepEnd / 1000).toDouble()
|
100 * (step.maneuver.waypoints.size - step.waypointIndex) / (step.maneuver.waypoints.size)
|
||||||
}
|
leftDistance = leftDistance * percent / 100
|
||||||
// The remaining distance to the step, rounded to the nearest 10 units.
|
// The remaining distance to the step, rounded to the nearest 10 units.
|
||||||
return (leftDistance * 1000 / 10.0).roundToInt() * 10.0
|
return (leftDistance * 1000 / 10.0).roundToInt() * 10.0
|
||||||
|
|
||||||
@@ -234,18 +211,17 @@ open class RouteModel() {
|
|||||||
/** Returns the left distance in km. */
|
/** Returns the left distance in km. */
|
||||||
fun travelLeftDistance(): Double {
|
fun travelLeftDistance(): Double {
|
||||||
var leftDistance = 0.0
|
var leftDistance = 0.0
|
||||||
for (i in route.currentManeuverIndex + 1..<route.maneuvers.size) {
|
for (i in route.currentStep + 1..<legs.steps.size) {
|
||||||
val maneuver = route.maneuvers[i]
|
val step = route.legs!![0].steps[i]
|
||||||
leftDistance += maneuver.length
|
leftDistance += step.distance
|
||||||
}
|
|
||||||
if (routeState.endIndex > 0) {
|
|
||||||
val maneuver = route.currentManeuver()
|
|
||||||
val curDistance = maneuver.length
|
|
||||||
val percent =
|
|
||||||
100 * (routeState.endIndex - routeState.currentShapeIndex) / (routeState.endIndex - routeState.beginIndex)
|
|
||||||
val time = curDistance * percent / 100
|
|
||||||
leftDistance += time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val step = route.currentStep()
|
||||||
|
val curDistance = step.distance
|
||||||
|
val percent =
|
||||||
|
100 * (step.maneuver.waypoints.size - step.waypointIndex) / (step.maneuver.waypoints.size)
|
||||||
|
val time = curDistance * percent / 100
|
||||||
|
leftDistance += time
|
||||||
return leftDistance
|
return leftDistance
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +287,6 @@ open class RouteModel() {
|
|||||||
currentTurnIcon = R.drawable.ic_roundabout_ccw
|
currentTurnIcon = R.drawable.ic_roundabout_ccw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//routeState.maneuverType = type
|
|
||||||
return Pair(type, currentTurnIcon)
|
return Pair(type, currentTurnIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +296,6 @@ open class RouteModel() {
|
|||||||
|
|
||||||
|
|
||||||
fun hasArrived(type: Int): Boolean {
|
fun hasArrived(type: Int): Boolean {
|
||||||
// return leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE && type == ManeuverType.DestinationRight.value
|
|
||||||
return type == ManeuverType.DestinationRight.value
|
return type == ManeuverType.DestinationRight.value
|
||||||
|| type == ManeuverType.Destination.value
|
|| type == ManeuverType.Destination.value
|
||||||
|| type == ManeuverType.DestinationLeft.value
|
|| type == ManeuverType.DestinationLeft.value
|
||||||
|
|||||||
@@ -6,5 +6,5 @@
|
|||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M220,408L489,408L489,180Q489,180 489,180Q489,180 489,180L220,180Q220,180 220,180Q220,180 220,180L220,408ZM160,840L160,180Q160,156 178,138Q196,120 220,120L489,120Q513,120 531,138Q549,156 549,180L549,468L614,468Q634.71,468 649.36,482.64Q664,497.29 664,518L664,737Q664,759 681.5,773.5Q699,788 722,788Q745,788 765,773.5Q785,759 785,737L785,350L770,350Q757.25,350 748.63,341.37Q740,332.75 740,320L740,230L760,230L760,180L790,180L790,230L830,230L830,180L860,180L860,230L880,230L880,320Q880,332.75 871.38,341.37Q862.75,350 850,350L835,350L835,736.69Q835,780 801,810Q767,840 721.82,840Q677.66,840 645.83,810Q614,780 614,737L614,518Q614,518 614,518Q614,518 614,518L549,518L549,840L160,840ZM337,746L425,606L372,606L372,501L285,641L337,641L337,746Z"/>
|
android:pathData="M337,746L425,606L372,606L372,501L285,641L337,641L337,746ZM220,408L489,408L489,180Q489,180 489,180Q489,180 489,180L220,180Q220,180 220,180Q220,180 220,180L220,408ZM220,780L489,780L489,468L220,468L220,780ZM160,840L160,180Q160,156 178,138Q196,120 220,120L489,120Q513,120 531,138Q549,156 549,180L549,468L614,468Q634.71,468 649.36,482.64Q664,497.29 664,518L664,737Q664,759 681.5,773.5Q699,788 722,788Q745,788 765,773.5Q785,759 785,737L785,350L770,350Q757.25,350 748.63,341.37Q740,332.75 740,320L740,230L760,230L760,180L790,180L790,230L830,230L830,180L860,180L860,230L880,230L880,320Q880,332.75 871.38,341.37Q862.75,350 850,350L835,350L835,736.69Q835,780 801,810Q767,840 721.82,840Q677.66,840 645.83,810Q614,780 614,737L614,518Q614,518 614,518Q614,518 614,518L549,518L549,840L160,840ZM489,780L220,780L220,780L489,780Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
26
common/data/src/main/res/drawable/ic_close_white_24dp.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2022 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M6.4,19 L5,17.6 10.6,12 5,6.4 6.4,5 12,10.6 17.6,5 19,6.4 13.4,12 19,17.6 17.6,19 12,13.4Z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2022 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,21 L10.55,19.7Q6.625,16.2 4.312,13.612Q2,11.025 2,8.15Q2,5.8 3.575,4.225Q5.15,2.65 7.5,2.65Q8.825,2.65 10,3.212Q11.175,3.775 12,4.75Q12.825,3.775 14,3.212Q15.175,2.65 16.5,2.65Q18.85,2.65 20.425,4.225Q22,5.8 22,8.15Q22,11.025 19.688,13.612Q17.375,16.2 13.45,19.7ZM12,18.3Q8.425,15.05 6.213,12.7Q4,10.35 4,8.15Q4,6.65 5,5.65Q6,4.65 7.5,4.65Q8.675,4.65 9.675,5.312Q10.675,5.975 11.05,7H12.95Q13.325,5.975 14.325,5.312Q15.325,4.65 16.5,4.65Q18,4.65 19,5.65Q20,6.65 20,8.15Q20,10.35 17.788,12.7Q15.575,15.05 12,18.3ZM12,18.3Q15.575,15.05 17.788,12.7Q20,10.35 20,8.15Q20,6.65 19,5.65Q18,4.65 16.5,4.65Q15.325,4.65 14.325,5.312Q13.325,5.975 12.95,7H11.05Q10.675,5.975 9.675,5.312Q8.675,4.65 7.5,4.65Q6,4.65 5,5.65Q4,6.65 4,8.15Q4,10.35 6.213,12.7Q8.425,15.05 12,18.3Z"/>
|
||||||
|
</vector>
|
||||||
26
common/data/src/main/res/drawable/ic_favorite_white_24dp.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2022 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,21 L10.55,19.7Q6.625,16.2 4.312,13.612Q2,11.025 2,8.15Q2,5.8 3.575,4.225Q5.15,2.65 7.5,2.65Q8.825,2.65 10,3.212Q11.175,3.775 12,4.75Q12.825,3.775 14,3.212Q15.175,2.65 16.5,2.65Q18.85,2.65 20.425,4.225Q22,5.8 22,8.15Q22,11.025 19.688,13.612Q17.375,16.2 13.45,19.7ZM12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475Q12,11.475 12,11.475ZM12,18.3Q15.575,15.05 17.788,12.7Q20,10.35 20,8.15Q20,6.65 19,5.65Q18,4.65 16.5,4.65Q15.325,4.65 14.325,5.312Q13.325,5.975 12.95,7H11.05Q10.675,5.975 9.675,5.312Q8.675,4.65 7.5,4.65Q6,4.65 5,5.65Q4,6.65 4,8.15Q4,10.35 6.213,12.7Q8.425,15.05 12,18.3Z"/>
|
||||||
|
</vector>
|
||||||
28
common/data/src/main/res/drawable/ic_pan_24.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M15.54,5.54L13.77,7.3 12,5.54 10.23,7.3 8.46,5.54 12,2zM18.46,15.54l-1.76,-1.77L18.46,12l-1.76,-1.77 1.76,-1.77L22,12zM8.46,18.46l1.77,-1.76L12,18.46l1.77,-1.76 1.77,1.76L12,22zM5.54,8.46l1.76,1.77L5.54,12l1.76,1.77 -1.76,1.77L2,12z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,12m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"/>
|
||||||
|
</vector>
|
||||||
25
common/data/src/main/res/drawable/ic_place_white_24dp.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M12,12c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM18,10.2C18,6.57 15.35,4 12,4s-6,2.57 -6,6.2c0,2.34 1.95,5.44 6,9.14 4.05,-3.7 6,-6.8 6,-9.14zM12,2c4.2,0 8,3.22 8,8.2 0,3.32 -2.67,7.25 -8,11.8 -5.33,-4.55 -8,-8.48 -8,-11.8C4,5.22 7.8,2 12,2z"
|
||||||
|
android:fillColor="#FFFFFF"/>
|
||||||
|
</vector>
|
||||||
BIN
common/data/src/main/res/drawable/ic_roundabout_ccw.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
common/data/src/main/res/drawable/ic_turn_destination.png
Normal file
|
After Width: | Height: | Size: 461 B |
BIN
common/data/src/main/res/drawable/ic_turn_name_change.png
Normal file
|
After Width: | Height: | Size: 396 B |
BIN
common/data/src/main/res/drawable/ic_turn_normal_left.png
Normal file
|
After Width: | Height: | Size: 650 B |
BIN
common/data/src/main/res/drawable/ic_turn_normal_right.png
Normal file
|
After Width: | Height: | Size: 651 B |
BIN
common/data/src/main/res/drawable/ic_turn_slight_left.png
Normal file
|
After Width: | Height: | Size: 463 B |
BIN
common/data/src/main/res/drawable/ic_turn_slight_right.png
Normal file
|
After Width: | Height: | Size: 464 B |
25
common/data/src/main/res/drawable/ic_zoom_in_24.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
|
</vector>
|
||||||
25
common/data/src/main/res/drawable/ic_zoom_out_24.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
Copyright 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,13H5v-2h14v2z"/>
|
||||||
|
</vector>
|
||||||
@@ -6,5 +6,5 @@
|
|||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M160,840L160,180Q160,156 178,138Q196,120 220,120L489,120Q513,120 531,138Q549,156 549,180L549,468L614,468Q634.63,468 649.31,482.69Q664,497.37 664,518L664,737Q664,758.68 679.5,773.34Q695,788 717,788Q739,788 754.5,773.34Q770,758.68 770,737L770,442Q759,448 747,451Q735,454 723,454Q683.52,454 656.26,426.74Q629,399.48 629,360Q629,328.39 647,303.19Q665,278 695,270L600,175L636,140L789,293Q803,307 811.5,323.5Q820,340 820,360L820,737Q820,780.26 790.18,810.13Q760.37,840 717.18,840Q674,840 644,810.13Q614,780.26 614,737L614,518Q614,518 614,518Q614,518 614,518L549,518L549,840L160,840ZM220,408L489,408L489,180Q489,180 489,180Q489,180 489,180L220,180Q220,180 220,180Q220,180 220,180L220,408ZM723,404Q741,404 754,391Q767,378 767,360Q767,342 754,329Q741,316 723,316Q705,316 692,329Q679,342 679,360Q679,378 692,391Q705,404 723,404Z"/>
|
android:pathData="M160,840L160,180Q160,156 178,138Q196,120 220,120L489,120Q513,120 531,138Q549,156 549,180L549,468L614,468Q634.63,468 649.31,482.69Q664,497.37 664,518L664,737Q664,758.68 679.5,773.34Q695,788 717,788Q739,788 754.5,773.34Q770,758.68 770,737L770,442Q759,448 747,451Q735,454 723,454Q683.52,454 656.26,426.74Q629,399.48 629,360Q629,328.39 647,303.19Q665,278 695,270L600,175L636,140L789,293Q803,307 811.5,323.5Q820,340 820,360L820,737Q820,780.26 790.18,810.13Q760.37,840 717.18,840Q674,840 644,810.13Q614,780.26 614,737L614,518Q614,518 614,518Q614,518 614,518L549,518L549,840L160,840ZM220,408L489,408L489,180Q489,180 489,180Q489,180 489,180L220,180Q220,180 220,180Q220,180 220,180L220,408ZM723,404Q741,404 754,391Q767,378 767,360Q767,342 754,329Q741,316 723,316Q705,316 692,329Q679,342 679,360Q679,378 692,391Q705,404 723,404ZM220,780L489,780L489,468L220,468L220,780ZM489,780L220,780L220,780L489,780Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -6,5 +6,5 @@
|
|||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M120,840L120,780L207,525L120,270L120,210L647,210L709,40L777,67L725,210L840,210L840,270L752,525L840,780L840,840L120,840ZM452,679L512,679L512,555L636,555L636,495L512,495L512,371L452,371L452,495L328,495L328,555L452,555L452,679Z"/>
|
android:pathData="M120,840L120,780L207,525L120,270L120,210L647,210L709,40L777,67L725,210L840,210L840,270L752,525L840,780L840,840L120,840ZM452,679L512,679L512,555L636,555L636,495L512,495L512,371L452,371L452,495L328,495L328,555L452,555L452,679ZM182,780L778,780L690,525L778,270L182,270L270,525L182,780ZM480,525L480,525L480,525L480,525L480,525L480,525Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
10
common/data/src/main/res/drawable/navigation_24px.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M200,840L160,800L480,80L800,800L760,840L480,720L200,840ZM284,716L480,632L676,716L480,276L284,716ZM480,632L480,632L480,632L480,632Z"/>
|
||||||
|
</vector>
|
||||||
10
common/data/src/main/res/drawable/navigation_48px.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M190,840L160,810L480,80L800,810L770,840L480,708L190,840ZM258,742L480,644L702,742L480,228L258,742ZM480,644L480,644L480,644L480,644Z"/>
|
||||||
|
</vector>
|
||||||
10
common/data/src/main/res/drawable/pan_tool_48px.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M402,920Q375,920 350.5,907.5Q326,895 311,872L54,492L74,476Q91,461 113.5,457Q136,453 158.07,470.19L280,563L280,150Q280,137.25 288.68,128.62Q297.35,120 310.18,120Q323,120 331.5,128.62Q340,137.25 340,150L340,678L166,550L361,838Q368,849 378.5,854.5Q389,860 402,860L541,860L690,860Q728,860 754,834Q780,808 780,770L780,190Q780,177.25 788.68,168.62Q797.35,160 810.18,160Q823,160 831.5,168.62Q840,177.25 840,190L840,770Q840,833 796.5,876.5Q753,920 690,920L402,920ZM447,480L447,70Q447,57.25 455.68,48.62Q464.35,40 477.18,40Q490,40 498.5,48.62Q507,57.25 507,70L507,480L447,480ZM614,480L614,110Q614,97.25 622.68,88.62Q631.35,80 644.18,80Q657,80 665.5,88.62Q674,97.25 674,110L674,480L614,480ZM473,670Q473,670 473,670Q473,670 473,670L473,670L473,670L473,670L473,670L473,670Q473,670 473,670Q473,670 473,670Z"/>
|
||||||
|
</vector>
|
||||||
10
common/data/src/main/res/drawable/search_48px.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M796,839L533,576Q503,602 463.04,616.5Q423.08,631 378,631Q269.84,631 194.92,556Q120,481 120,375Q120,269 195,194Q270,119 376.5,119Q483,119 557.5,194Q632,269 632,375.15Q632,418 618,458Q604,498 576,533L840,795L796,839ZM377,571Q458.25,571 515.13,513.5Q572,456 572,375Q572,294 515.13,236.5Q458.25,179 377,179Q294.92,179 237.46,236.5Q180,294 180,375Q180,456 237.46,513.5Q294.92,571 377,571Z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M452,674L508,674L518,620Q538,614 552,605Q566,596 578,584L640,603L666,549L619,519Q623,498 623,480Q623,462 619,441L666,411L640,357L578,376Q566,364 552,355Q538,346 518,340L508,286L452,286L442,340Q422,346 408,355Q394,364 382,376L320,357L294,411L341,441Q337,462 337,480Q337,498 341,519L294,549L320,603L382,584Q394,596 408,605Q422,614 442,620L452,674ZM480,565Q444,565 419.5,540.5Q395,516 395,480Q395,444 419.5,419.5Q444,395 480,395Q516,395 540.5,419.5Q565,444 565,480Q565,516 540.5,540.5Q516,565 480,565ZM180,840Q156,840 138,822Q120,804 120,780L120,180Q120,156 138,138Q156,120 180,120L780,120Q804,120 822,138Q840,156 840,180L840,780Q840,804 822,822Q804,840 780,840L180,840ZM180,780L780,780Q780,780 780,780Q780,780 780,780L780,180Q780,180 780,180Q780,180 780,180L180,180Q180,180 180,180Q180,180 180,180L180,780Q180,780 180,780Q180,780 180,780ZM180,180L180,180Q180,180 180,180Q180,180 180,180L180,780Q180,780 180,780Q180,780 180,780L180,780Q180,780 180,780Q180,780 180,780L180,180Q180,180 180,180Q180,180 180,180Z"/>
|
||||||
|
</vector>
|
||||||
10
common/data/src/main/res/drawable/speed_camera_48px.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M715,592L647,553L772,460L840,499L715,592ZM518,493L648,397L333,219Q333,219 333,219Q333,219 333,219L258,346Q258,346 258,346Q258,346 258,346L518,493ZM453,356L453,356Q453,356 453,356Q453,356 453,356L453,356Q453,356 453,356Q453,356 453,356L453,356ZM160,800L160,740L370,740Q370,740 370,740Q370,740 370,740L370,478L228,398Q205.93,385.04 199.47,361.02Q193,337 206,315L281,190Q294,169 317.5,162.5Q341,156 362,168L757,391L522,564L430,512L430,740Q430,764.75 412.38,782.37Q394.75,800 370,800L160,800Z"/>
|
||||||
|
</vector>
|
||||||
23
common/data/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="ShowcaseTheme">
|
||||||
|
<attr name="themedIconColor" format="color"/>
|
||||||
|
<attr name="markerIconTintColor" format="color"/>
|
||||||
|
<attr name="markerIconTintColorDark" format="color"/>
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
33
common/data/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="speed_camera">Speed camera</string>
|
||||||
|
<string name="exit_action_title">Dismiss</string>
|
||||||
|
<string name="fuel_station">Gas station</string>
|
||||||
|
<string name="pharmacy">Pharmacy</string>
|
||||||
|
<string name="charging_station">Charging station</string>
|
||||||
|
<string name="category_title">Category</string>
|
||||||
|
<string name="on_action_title">On</string>
|
||||||
|
<string name="off_action_title">Off</string>
|
||||||
|
<string name="use_telephon_settings">Use telephon settings</string>
|
||||||
|
<string name="dark_mode">Dark mode</string>
|
||||||
|
<string name="display_settings">Display settings</string>
|
||||||
|
<string name="threed_building">3D building</string>
|
||||||
|
<string name="arrived_exclamation_msg">Arrived!</string>
|
||||||
|
<string name="drive_now">Drive now</string>
|
||||||
|
<string name="stop_action_title">Stop</string>
|
||||||
|
<string name="avoid_highways_row_title">Avoid highways</string>
|
||||||
|
<string name="avoid_tolls_row_title">Avoid tolls rows</string>
|
||||||
|
<string name="no_places">No places</string>
|
||||||
|
<string name="recent_destinations">Recent destination</string>
|
||||||
|
<string name="contacts">Contacts</string>
|
||||||
|
<string name="favorites">Favorites</string>
|
||||||
|
<string name="recent_Item_deleted">Recent item deleted</string>
|
||||||
|
<string name="route_preview">Route preview</string>
|
||||||
|
<string name="display">Display</string>
|
||||||
|
<string name="navigation_settings">Navigation settings</string>
|
||||||
|
<string name="settings_action_title">Settings</string>
|
||||||
|
<string name="accept_action_title">Accept</string>
|
||||||
|
<string name="reject_action_title">Reject</string>
|
||||||
|
<string name="ok_action_title">OK</string>
|
||||||
|
<string name="search_action_title">Search</string>
|
||||||
|
</resources>
|
||||||
27
common/data/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<style name="CarAppTheme">
|
||||||
|
<item name="themedIconColor">#FFFF0000</item>
|
||||||
|
<item name="carColorPrimary">#ff7f39fb</item>
|
||||||
|
<item name="carColorPrimaryDark">#5904DF</item>
|
||||||
|
<item name="carColorSecondary">#328E10</item>
|
||||||
|
<item name="carColorSecondaryDark">#1A6004</item>
|
||||||
|
<item name="markerIconTintColor">#FF7F39FB</item>
|
||||||
|
<item name="markerIconTintColorDark">#FF5904DF</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||