Napraw otwieranie nawigacji do geofence
This commit is contained in:
@@ -2,6 +2,7 @@ package pl.firmatpp.kierowca.ui
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -12,6 +13,7 @@ import android.location.LocationManager
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
@@ -3565,7 +3567,10 @@ private fun RoutePointBlock(
|
|||||||
Text(subtitle, color = TppTheme.colors.muted, style = MaterialTheme.typography.bodyLarge)
|
Text(subtitle, color = TppTheme.colors.muted, style = MaterialTheme.typography.bodyLarge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (navigationPoint?.hasCoordinates() == true) {
|
if (
|
||||||
|
navigationPoint != null &&
|
||||||
|
hasValidNavigationCoordinates(navigationPoint.latitude, navigationPoint.longitude)
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { onNavigate(navigationPoint) },
|
onClick = { onNavigate(navigationPoint) },
|
||||||
modifier = Modifier.size(42.dp).background(TppTheme.colors.forest, RoundedCornerShape(21.dp)),
|
modifier = Modifier.size(42.dp).background(TppTheme.colors.forest, RoundedCornerShape(21.dp)),
|
||||||
@@ -4356,24 +4361,29 @@ private fun createCameraUri(context: Context): Uri {
|
|||||||
return FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file)
|
return FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun NavigationPointDto.hasCoordinates(): Boolean = latitude != null && longitude != null
|
|
||||||
|
|
||||||
private fun openNavigation(context: Context, point: NavigationPointDto) {
|
private fun openNavigation(context: Context, point: NavigationPointDto) {
|
||||||
val latitude = point.latitude ?: return
|
val candidates = navigationIntentCandidates(point.latitude, point.longitude, point.label)
|
||||||
val longitude = point.longitude ?: return
|
|
||||||
val googleMapsIntent = Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q=$latitude,$longitude"))
|
|
||||||
.setPackage("com.google.android.apps.maps")
|
|
||||||
|
|
||||||
if (googleMapsIntent.resolveActivity(context.packageManager) != null) {
|
for (candidate in candidates) {
|
||||||
context.startActivity(googleMapsIntent)
|
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(candidate.uri)).apply {
|
||||||
return
|
candidate.packageName?.let(::setPackage)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
context.startActivity(intent)
|
||||||
|
return
|
||||||
|
} catch (_: ActivityNotFoundException) {
|
||||||
|
// Try the next navigation provider.
|
||||||
|
} catch (_: SecurityException) {
|
||||||
|
// The provider is unavailable to this app; use the next fallback.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val label = Uri.encode(point.label?.takeIf { it.isNotBlank() } ?: "Cel")
|
Toast.makeText(
|
||||||
val geoIntent = Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=$latitude,$longitude($label)"))
|
context,
|
||||||
if (geoIntent.resolveActivity(context.packageManager) != null) {
|
"Nie znaleziono aplikacji, która może otworzyć nawigację.",
|
||||||
context.startActivity(geoIntent)
|
Toast.LENGTH_LONG,
|
||||||
}
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cameraCapturePermissions(context: Context, requirePreciseLocation: Boolean): Array<String> = buildList {
|
private fun cameraCapturePermissions(context: Context, requirePreciseLocation: Boolean): Array<String> = buildList {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package pl.firmatpp.kierowca.ui
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
|
import java.net.URLEncoder
|
||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
@@ -24,6 +25,42 @@ import pl.firmatpp.kierowca.data.upload.RouteActionType
|
|||||||
private val shortDateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM")
|
private val shortDateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM")
|
||||||
private val routeWeightKilogramInputThreshold = BigDecimal("1000")
|
private val routeWeightKilogramInputThreshold = BigDecimal("1000")
|
||||||
private const val routeWeightMaxTons = 999.999
|
private const val routeWeightMaxTons = 999.999
|
||||||
|
private const val googleMapsPackage = "com.google.android.apps.maps"
|
||||||
|
|
||||||
|
data class NavigationIntentCandidate(
|
||||||
|
val uri: String,
|
||||||
|
val packageName: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun hasValidNavigationCoordinates(latitude: Double?, longitude: Double?): Boolean =
|
||||||
|
latitude != null &&
|
||||||
|
longitude != null &&
|
||||||
|
latitude.isFinite() &&
|
||||||
|
longitude.isFinite() &&
|
||||||
|
latitude in -90.0..90.0 &&
|
||||||
|
longitude in -180.0..180.0
|
||||||
|
|
||||||
|
fun navigationIntentCandidates(
|
||||||
|
latitude: Double?,
|
||||||
|
longitude: Double?,
|
||||||
|
label: String?,
|
||||||
|
): List<NavigationIntentCandidate> {
|
||||||
|
if (!hasValidNavigationCoordinates(latitude, longitude)) return emptyList()
|
||||||
|
|
||||||
|
val coordinates = "$latitude,$longitude"
|
||||||
|
val encodedLabel = URLEncoder
|
||||||
|
.encode(label?.takeIf { it.isNotBlank() } ?: "Cel", Charsets.UTF_8.name())
|
||||||
|
.replace("+", "%20")
|
||||||
|
|
||||||
|
return listOf(
|
||||||
|
NavigationIntentCandidate(
|
||||||
|
uri = "google.navigation:q=$coordinates",
|
||||||
|
packageName = googleMapsPackage,
|
||||||
|
),
|
||||||
|
NavigationIntentCandidate(uri = "geo:0,0?q=$coordinates($encodedLabel)"),
|
||||||
|
NavigationIntentCandidate(uri = "https://www.google.com/maps/dir/?api=1&destination=$coordinates"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
enum class RouteFlowStepState {
|
enum class RouteFlowStepState {
|
||||||
Todo,
|
Todo,
|
||||||
|
|||||||
@@ -82,6 +82,39 @@ class DriverUiRulesTest {
|
|||||||
assertEquals("—", routeDateChipLabel("", today))
|
assertEquals("—", routeDateChipLabel("", today))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun buildsNavigationCandidatesFromGeofenceCoordinatesWithFallbacks() {
|
||||||
|
val candidates = navigationIntentCandidates(
|
||||||
|
latitude = 50.0619474,
|
||||||
|
longitude = 19.9368564,
|
||||||
|
label = "Brama główna",
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(3, candidates.size)
|
||||||
|
assertEquals("com.google.android.apps.maps", candidates[0].packageName)
|
||||||
|
assertEquals("google.navigation:q=50.0619474,19.9368564", candidates[0].uri)
|
||||||
|
assertEquals(null, candidates[1].packageName)
|
||||||
|
assertEquals(
|
||||||
|
"geo:0,0?q=50.0619474,19.9368564(Brama%20g%C5%82%C3%B3wna)",
|
||||||
|
candidates[1].uri,
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"https://www.google.com/maps/dir/?api=1&destination=50.0619474,19.9368564",
|
||||||
|
candidates[2].uri,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun doesNotBuildNavigationCandidatesForMissingOrInvalidCoordinates() {
|
||||||
|
assertFalse(hasValidNavigationCoordinates(null, 19.9368564))
|
||||||
|
assertFalse(hasValidNavigationCoordinates(50.0619474, null))
|
||||||
|
assertFalse(hasValidNavigationCoordinates(Double.NaN, 19.9368564))
|
||||||
|
assertFalse(hasValidNavigationCoordinates(91.0, 19.9368564))
|
||||||
|
assertFalse(hasValidNavigationCoordinates(50.0619474, 181.0))
|
||||||
|
assertTrue(hasValidNavigationCoordinates(50.0619474, 19.9368564))
|
||||||
|
assertTrue(navigationIntentCandidates(null, null, "Cel").isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun calculatesPhotoGridRowsForTwoColumnInlineGallery() {
|
fun calculatesPhotoGridRowsForTwoColumnInlineGallery() {
|
||||||
assertEquals(0, inlinePhotoGridRows(0))
|
assertEquals(0, inlinePhotoGridRows(0))
|
||||||
|
|||||||
Reference in New Issue
Block a user