Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
130f8bbecc | ||
|
|
4c00d46a14 |
@@ -34,8 +34,8 @@ android {
|
||||
applicationId = "pl.firmatpp.kierowca"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 112
|
||||
versionName = "1.0.59"
|
||||
versionCode = 113
|
||||
versionName = "1.0.60"
|
||||
setProperty("archivesBaseName", "pl.firmatpp.kierowca")
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package pl.firmatpp.kierowca.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -12,6 +13,7 @@ import android.location.LocationManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
@@ -3565,7 +3567,10 @@ private fun RoutePointBlock(
|
||||
Text(subtitle, color = TppTheme.colors.muted, style = MaterialTheme.typography.bodyLarge)
|
||||
}
|
||||
}
|
||||
if (navigationPoint?.hasCoordinates() == true) {
|
||||
if (
|
||||
navigationPoint != null &&
|
||||
hasValidNavigationCoordinates(navigationPoint.latitude, navigationPoint.longitude)
|
||||
) {
|
||||
IconButton(
|
||||
onClick = { onNavigate(navigationPoint) },
|
||||
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)
|
||||
}
|
||||
|
||||
private fun NavigationPointDto.hasCoordinates(): Boolean = latitude != null && longitude != null
|
||||
|
||||
private fun openNavigation(context: Context, point: NavigationPointDto) {
|
||||
val latitude = point.latitude ?: return
|
||||
val longitude = point.longitude ?: return
|
||||
val googleMapsIntent = Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q=$latitude,$longitude"))
|
||||
.setPackage("com.google.android.apps.maps")
|
||||
val candidates = navigationIntentCandidates(point.latitude, point.longitude, point.label)
|
||||
|
||||
if (googleMapsIntent.resolveActivity(context.packageManager) != null) {
|
||||
context.startActivity(googleMapsIntent)
|
||||
return
|
||||
for (candidate in candidates) {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(candidate.uri)).apply {
|
||||
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")
|
||||
val geoIntent = Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=$latitude,$longitude($label)"))
|
||||
if (geoIntent.resolveActivity(context.packageManager) != null) {
|
||||
context.startActivity(geoIntent)
|
||||
}
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Nie znaleziono aplikacji, która może otworzyć nawigację.",
|
||||
Toast.LENGTH_LONG,
|
||||
).show()
|
||||
}
|
||||
|
||||
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.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
import java.net.URLEncoder
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
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 routeWeightKilogramInputThreshold = BigDecimal("1000")
|
||||
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 {
|
||||
Todo,
|
||||
|
||||
@@ -82,6 +82,39 @@ class DriverUiRulesTest {
|
||||
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
|
||||
fun calculatesPhotoGridRowsForTwoColumnInlineGallery() {
|
||||
assertEquals(0, inlinePhotoGridRows(0))
|
||||
|
||||
Reference in New Issue
Block a user