chore: add build artifacts, map assets, and routing data

This commit is contained in:
Hamza-Ayed
2026-09-19 12:34:24 +03:00
parent aa2b9f131f
commit 43ad2e0ad4
327 changed files with 52421 additions and 1810 deletions
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
@@ -0,0 +1,89 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Permissions for High-Precision Navigation and Background Audio -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:label="خرائط سيرو"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:supportsPictureInPicture="true"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- Custom URI Scheme: siromaps:// -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="siromaps" />
</intent-filter>
<!-- Standard Geo Scheme: geo:lat,lng -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="geo" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- Android Auto Navigation Service -->
<service
android:name=".car.SiroCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.NAVIGATION"/>
</intent-filter>
</service>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1" />
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
@@ -0,0 +1,63 @@
package com.siro_map.siro_maps
import com.siro_map.siro_maps.car.CarNavigationState
import com.siro_map.siro_maps.car.SiroCarAppService
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private val CHANNEL = "com.siro.siro_maps/car_navigation"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
when (call.method) {
"isCarAppConnected" -> {
result.success(SiroCarAppService.isConnected)
}
"updateNavState" -> {
try {
val lat = call.argument<Double>("lat") ?: 0.0
val lng = call.argument<Double>("lng") ?: 0.0
val bearing = call.argument<Double>("bearing") ?: 0.0
val speed = call.argument<Double>("speed") ?: 0.0
val instruction = call.argument<String>("instruction") ?: ""
val distanceToStep = call.argument<Double>("distanceToStep") ?: 0.0
val totalDistance = call.argument<Double>("totalDistance") ?: 0.0
val eta = call.argument<Double>("eta") ?: 0.0
val maneuver = call.argument<Int>("maneuver") ?: 0
val isNavigating = call.argument<Boolean>("isNavigating") ?: false
val isMapDarkMode = call.argument<Boolean>("isMapDarkMode") ?: false
val newState = CarNavigationState(
lat = lat,
lng = lng,
bearing = bearing,
speed = speed,
instruction = instruction,
distanceToStep = distanceToStep,
totalDistance = totalDistance,
eta = eta,
maneuver = maneuver,
isNavigating = isNavigating,
isMapDarkMode = isMapDarkMode
)
SiroCarAppService.updateNavState(newState)
result.success(true)
} catch (e: Exception) {
result.error("UPDATE_FAILED", e.localizedMessage, null)
}
}
"stopNavigation" -> {
SiroCarAppService.stopNavigation()
result.success(true)
}
else -> {
result.notImplemented()
}
}
}
}
}
@@ -0,0 +1,44 @@
package com.siro_map.siro_maps.car
data class CarNavigationState(
val lat: Double = 0.0,
val lng: Double = 0.0,
val bearing: Double = 0.0,
val speed: Double = 0.0,
val instruction: String = "",
val distanceToStep: Double = 0.0,
val totalDistance: Double = 0.0,
val eta: Double = 0.0,
val maneuver: Int = 0,
val isNavigating: Boolean = false,
val isMapDarkMode: Boolean = false
) {
val formattedSpeed: String
get() = "${speed.toInt()} كم/س"
val formattedRemainingDistance: String
get() = if (totalDistance >= 1000) {
String.format("%.1f كم", totalDistance / 1000.0)
} else {
"${totalDistance.toInt()} م"
}
val formattedDistanceToStep: String
get() = if (distanceToStep >= 1000) {
String.format("بعد %.1f كم", distanceToStep / 1000.0)
} else {
"بعد ${distanceToStep.toInt()} م"
}
val formattedRemainingDuration: String
get() {
val minutes = (eta / 60.0).toInt()
return if (minutes >= 60) {
val hours = minutes / 60
val remMin = minutes % 60
"$hours س $remMin د"
} else {
"$minutes دقيقة"
}
}
}
@@ -0,0 +1,41 @@
package com.siro_map.siro_maps.car
import androidx.car.app.CarAppService
import androidx.car.app.Session
import androidx.car.app.validation.HostValidator
class SiroCarAppService : CarAppService() {
companion object {
var currentNavState: CarNavigationState = CarNavigationState()
var activeSession: SiroCarSession? = null
fun updateNavState(state: CarNavigationState) {
currentNavState = state
activeSession?.requestScreenUpdate()
}
fun stopNavigation() {
currentNavState = currentNavState.copy(isNavigating = false)
activeSession?.requestScreenUpdate()
}
val isConnected: Boolean
get() = activeSession != null
}
override fun createHostValidator(): HostValidator {
return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
}
override fun onCreateSession(): Session {
val session = SiroCarSession()
activeSession = session
return session
}
override fun onDestroy() {
activeSession = null
super.onDestroy()
}
}
@@ -0,0 +1,23 @@
package com.siro_map.siro_maps.car
import android.content.Intent
import androidx.car.app.Screen
import androidx.car.app.Session
class SiroCarSession : Session() {
private var activeScreen: SiroNavScreen? = null
init {
SiroCarAppService.activeSession = this
}
override fun onCreateScreen(intent: Intent): Screen {
val screen = SiroNavScreen(carContext)
activeScreen = screen
return screen
}
fun requestScreenUpdate() {
activeScreen?.invalidate()
}
}
@@ -0,0 +1,92 @@
package com.siro_map.siro_maps.car
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.*
class SiroNavScreen(carContext: CarContext) : Screen(carContext) {
override fun onGetTemplate(): Template {
val state = SiroCarAppService.currentNavState
return if (state.isNavigating) {
buildActiveNavTemplate(state)
} else {
buildIdleTemplate(state)
}
}
private fun buildActiveNavTemplate(state: CarNavigationState): Template {
val paneBuilder = Pane.Builder()
// 1. Current instruction & distance
paneBuilder.addRow(
Row.Builder()
.setTitle(state.instruction.ifEmpty { "تابع السير نحو الوجهة" })
.addText(state.formattedDistanceToStep)
.build()
)
// 2. Trip summary (Distance and Duration)
paneBuilder.addRow(
Row.Builder()
.setTitle("المسار المتبقي")
.addText("${state.formattedRemainingDistance} • الوصول خلال ${state.formattedRemainingDuration}")
.build()
)
// 3. Live Speed
paneBuilder.addRow(
Row.Builder()
.setTitle("السرعة الحالية")
.addText(state.formattedSpeed)
.build()
)
// Stop navigation action button
paneBuilder.addAction(
Action.Builder()
.setTitle("إنهاء الملاحة")
.setOnClickListener {
SiroCarAppService.stopNavigation()
invalidate()
}
.build()
)
return PaneTemplate.Builder(paneBuilder.build())
.setTitle("ملاحة سيرو • جارية الآن")
.setHeaderAction(Action.APP_ICON)
.build()
}
private fun buildIdleTemplate(state: CarNavigationState): Template {
val paneBuilder = Pane.Builder()
paneBuilder.addRow(
Row.Builder()
.setTitle("خرائط سيرو السيادية (Siro Maps)")
.addText("التطبيق متصل بنجاح بشاشة السيارة")
.build()
)
paneBuilder.addRow(
Row.Builder()
.setTitle("وضع القيادة الحر")
.addText("السرعة: ${state.formattedSpeed}")
.build()
)
paneBuilder.addRow(
Row.Builder()
.setTitle("بدء الملاحة")
.addText("حدد وجهتك من شاشة الهاتف للانتقال الفوري إلى وضع الملاحة ثلاثية الأبعاد")
.build()
)
return PaneTemplate.Builder(paneBuilder.build())
.setTitle("خرائط سيرو")
.setHeaderAction(Action.APP_ICON)
.build()
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<automotiveApp>
<uses name="navigation" />
</automotiveApp>
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>