Skip to content

Commit 8dc82a0

Browse files
committed
added caching
1 parent 7147260 commit 8dc82a0

File tree

10 files changed

+145
-24
lines changed

10 files changed

+145
-24
lines changed

android/app/androidauto/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
id 'com.android.library'
33
id 'org.jetbrains.kotlin.android'
4+
id("com.google.devtools.ksp")
45
}
56

67
android {
@@ -32,10 +33,14 @@ android {
3233
dependencies {
3334
implementation("androidx.car.app:app:1.3.0-rc01")
3435
implementation("com.github.vietmap-company:maps-sdk-android:3.1.0")
36+
3537
// implementation("com.github.vietmap-company:vietmap-android-auto:1.5.1")
3638
implementation 'androidx.core:core-ktx:1.12.0'
3739
implementation 'androidx.appcompat:appcompat:1.6.1'
3840
implementation 'com.google.android.material:material:1.12.0'
41+
implementation 'androidx.room:room-runtime:2.6.1'
42+
annotationProcessor 'androidx.room:room-compiler:2.6.1'
43+
ksp("androidx.room:room-compiler:2.6.1")
3944
testImplementation 'junit:junit:4.13.2'
4045
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
4146
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package vn.vietmap.androidauto.cache
2+
3+
import androidx.room.Database
4+
import androidx.room.RoomDatabase
5+
import vn.vietmap.androidauto.model.PlaceItem
6+
7+
@Database(entities = [PlaceItem::class], version = 1)
8+
abstract class AppCacheDatabase : RoomDatabase() {
9+
abstract fun placeItemDAO(): PlaceItemDAO
10+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package vn.vietmap.androidauto.cache
2+
3+
import androidx.room.Dao
4+
import androidx.room.Delete
5+
import androidx.room.Insert
6+
import androidx.room.Query
7+
import vn.vietmap.androidauto.model.PlaceItem
8+
9+
@Dao
10+
interface PlaceItemDAO {
11+
@Query("SELECT * FROM PlaceItem")
12+
fun getAll(): List<PlaceItem>
13+
14+
@Insert
15+
fun insertAll(vararg placeItems: PlaceItem)
16+
17+
@Delete
18+
fun delete(placeItem: PlaceItem)
19+
}
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
package vn.vietmap.androidauto.model
22

3-
data class PlaceItem(val ref_id: String, val address: String, val name: String)
3+
import androidx.room.Entity
4+
import androidx.room.PrimaryKey
5+
6+
@Entity
7+
data class PlaceItem(
8+
@PrimaryKey val ref_id: String,
9+
val address: String,
10+
val name: String
11+
)
412

android/app/androidauto/src/main/java/vn/vietmap/androidauto/screens/VietMapNavigationScreen.kt

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,24 @@
11
package vn.vietmap.androidauto.screens
22

33
import android.annotation.SuppressLint
4-
import android.content.DialogInterface
54
import android.graphics.Color
65
import android.graphics.PointF
76
import android.location.Location
87
import android.os.Build
98
import android.util.Log
10-
import android.widget.Toast
119
import androidx.annotation.RequiresApi
12-
import androidx.car.app.AppManager
1310
import androidx.car.app.CarContext
1411
import androidx.car.app.OnScreenResultListener
1512
import androidx.car.app.Screen
1613
import androidx.car.app.ScreenManager
1714
import androidx.car.app.SurfaceCallback
18-
import androidx.car.app.model.Alert
19-
import androidx.car.app.model.CarText
2015
import androidx.car.app.model.Template
21-
import androidx.car.app.navigation.model.Maneuver
22-
import androidx.car.app.notification.CarAppExtender
23-
import androidx.core.app.NotificationCompat
2416
import androidx.lifecycle.Lifecycle
2517
import androidx.lifecycle.LifecycleObserver
2618
import androidx.lifecycle.OnLifecycleEvent
2719
import com.mapbox.api.directions.v5.models.BannerInstructions
2820
import com.mapbox.api.directions.v5.models.DirectionsResponse
2921
import com.mapbox.api.directions.v5.models.DirectionsRoute
30-
import com.mapbox.api.directions.v5.models.DirectionsWaypoint
3122
import com.mapbox.geojson.Point
3223
import com.mapbox.turf.TurfMisc
3324
import io.flutter.embedding.engine.FlutterEngine
@@ -66,10 +57,10 @@ import vn.vietmap.services.android.navigation.v5.navigation.VietmapNavigation
6657
import vn.vietmap.services.android.navigation.v5.navigation.VietmapNavigationOptions
6758
import vn.vietmap.services.android.navigation.v5.offroute.OffRouteListener
6859
import vn.vietmap.services.android.navigation.v5.route.FasterRouteListener
69-
import vn.vietmap.services.android.navigation.v5.route.OnRouteSelectionChangeListener
7060
import vn.vietmap.services.android.navigation.v5.routeprogress.ProgressChangeListener
7161
import vn.vietmap.services.android.navigation.v5.routeprogress.RouteProgress
7262
import vn.vietmap.services.android.navigation.v5.snap.SnapToRoute
63+
import vn.vietmap.services.android.navigation.v5.utils.RouteUtils
7364
import vn.vietmap.vietmapsdk.annotations.IconFactory
7465
import vn.vietmap.vietmapsdk.annotations.Marker
7566
import vn.vietmap.vietmapsdk.annotations.MarkerOptions
@@ -104,6 +95,8 @@ class VietMapNavigationScreen(
10495
FasterRouteListener, SpeechAnnouncementListener, BannerInstructionsListener, RouteListener,
10596
IVietMapCarMapController, IAndroidAutoNavigationCommunicator, LifecycleObserver{
10697

98+
private var routeUtils = RouteUtils()
99+
107100
private var routeClicked: Boolean = false
108101
private var currentRoute: DirectionsRoute? = null
109102
private var locationEngine: LocationEngine? = null
@@ -481,7 +474,6 @@ class VietMapNavigationScreen(
481474
vietmapGL?.infoWindowAdapter = vietmapInfoWindowAdapter
482475
vietmapGL?.setOnMarkerClickListener {
483476
m ->
484-
Log.d("VietMapNavigationScreen", "Marker clicked: ${m.title}")
485477
m.showInfoWindow(vietmapGL!!, mSurfaceRenderer.getMapView()!!)
486478
true
487479
}
@@ -755,11 +747,21 @@ class VietMapNavigationScreen(
755747
}
756748

757749
override fun onMilestoneEvent(
758-
routeProgress: RouteProgress?,
759-
instruction: String?,
760-
milestone: Milestone?,
750+
routeProgress: RouteProgress,
751+
instruction: String,
752+
milestone: Milestone,
761753
) {
762-
// playVoiceAnnouncement(milestone)
754+
playVoiceAnnouncement(milestone)
755+
if (routeUtils.isArrivalEvent(routeProgress, milestone) && isNavigationInProgress) {
756+
vietmapGL?.locationComponent?.locationEngine = locationEngine
757+
758+
isPreviewingRoute = false
759+
onStopNavigationFunction()
760+
if(markers?.isNotEmpty() == true){
761+
vietMapCarSurfaceHelper.updateOnSingleMarkerChosen()
762+
invalidate()
763+
}
764+
}
763765
}
764766

765767
override fun onRunning(running: Boolean) {
@@ -1098,6 +1100,10 @@ class VietMapNavigationScreen(
10981100
override fun onStopNavigation(result: MethodChannel.Result) {
10991101
isPreviewingRoute = false
11001102
onStopNavigationFunction()
1103+
if(markers?.isNotEmpty() == true){
1104+
vietMapCarSurfaceHelper.updateOnSingleMarkerChosen()
1105+
invalidate()
1106+
}
11011107
result.success(true)
11021108
}
11031109

@@ -1169,6 +1175,9 @@ class VietMapNavigationScreen(
11691175

11701176
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
11711177
fun onDestroy() {
1178+
mapMethodChannel?.setMethodCallHandler(null)
1179+
navigationMethodChannel?.setMethodCallHandler(null)
11721180
mapMethodChannel = null
1181+
navigationMethodChannel = null
11731182
}
11741183
}

android/app/androidauto/src/main/java/vn/vietmap/androidauto/screens/VietMapSearchScreen.kt

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@ import androidx.lifecycle.Lifecycle
1616
import androidx.lifecycle.LifecycleObserver
1717
import androidx.lifecycle.OnLifecycleEvent
1818
import androidx.lifecycle.lifecycleScope
19+
import androidx.room.Room
1920
import io.flutter.embedding.engine.FlutterEngine
2021
import io.flutter.plugin.common.MethodCall
2122
import io.flutter.plugin.common.MethodChannel
23+
import kotlinx.coroutines.CoroutineScope
24+
import kotlinx.coroutines.Dispatchers
2225
import kotlinx.coroutines.delay
2326
import kotlinx.coroutines.flow.MutableStateFlow
2427
import kotlinx.coroutines.flow.StateFlow
2528
import kotlinx.coroutines.launch
29+
import vn.vietmap.androidauto.cache.AppCacheDatabase
30+
import vn.vietmap.androidauto.cache.PlaceItemDAO
2631
import vn.vietmap.androidauto.model.PlaceItem
2732
import vn.vietmap.androidauto.service.IAndroidAutoSearchCommunicator
2833
import vn.vietmap.androidauto.service.SearchScreenService
@@ -34,12 +39,16 @@ import vn.vietmap.vietmapsdk.location.engine.LocationEngineResult
3439
import java.lang.Exception
3540

3641
class VietMapSearchScreen(carContext: CarContext): Screen(carContext), LifecycleObserver, IAndroidAutoSearchCommunicator {
42+
private val appCacheDatabase = Room.databaseBuilder(carContext, AppCacheDatabase::class.java, "app-cache-database").build()
43+
private val placeItemDAO: PlaceItemDAO
3744
private val searchScreenService : SearchScreenService = ServiceGenerator.createService(SearchScreenService::class.java)
3845
private var locationEngine: LocationEngine? = null
39-
private var placeItems : List<PlaceItem> = emptyList()
46+
private var placeItems : ArrayList<PlaceItem> = ArrayList()
4047
private var searchMethodChannel: MethodChannel? = null
4148
private var flutterEngine: FlutterEngine? = null
4249
private var searchText: String = ""
50+
private val ioCoroutineScope : CoroutineScope = CoroutineScope(Dispatchers.IO)
51+
private val cachePlaceItems : ArrayList<PlaceItem> = ArrayList()
4352

4453
companion object {
4554
const val VIETMAP_ANDROID_AUTO_CHANNEL = "vn.vietmap.automotive/search"
@@ -56,6 +65,10 @@ class VietMapSearchScreen(carContext: CarContext): Screen(carContext), Lifecycle
5665
lifecycle.addObserver(this)
5766
locationEngine = LocationEngineProvider.getBestLocationEngine(carContext)
5867
setSearchScreenInstance(this)
68+
placeItemDAO = appCacheDatabase.placeItemDAO()
69+
ioCoroutineScope.launch {
70+
getInitialPlaceItems()
71+
}
5972
}
6073

6174
fun initFlutterEngine(flutterEngine: FlutterEngine){
@@ -78,7 +91,7 @@ class VietMapSearchScreen(carContext: CarContext): Screen(carContext), Lifecycle
7891
}
7992
}
8093
private fun performSearch(query: String, latLngString: String?){
81-
lifecycleScope.launch {
94+
ioCoroutineScope.launch {
8295
delay(500)
8396
val resp = searchScreenService.autocomplete(query, latLngString)
8497
setResults(if (resp.isSuccessful) resp.body() ?: emptyList() else emptyList())
@@ -87,7 +100,10 @@ class VietMapSearchScreen(carContext: CarContext): Screen(carContext), Lifecycle
87100

88101

89102
private fun setResults(results: List<PlaceItem>){
90-
placeItems = results.toList()
103+
placeItems.let {
104+
it.clear()
105+
it.addAll(results)
106+
}
91107
val itemList = ItemList.Builder()
92108
results.forEach{
93109
itemList.addItem(
@@ -112,14 +128,59 @@ class VietMapSearchScreen(carContext: CarContext): Screen(carContext), Lifecycle
112128
private fun onPlaceSelected(placeItem: PlaceItem){
113129
// Pop back to navigation place and set destination
114130
searchMethodChannel?.invokeMethod("selectSearchResult", mapOf("refId" to placeItem.ref_id))
115-
lifecycleScope.launch {
131+
ioCoroutineScope.launch {
116132
val resp = searchScreenService.getPlaceDetail(placeItem.ref_id)
117133
if(resp.isSuccessful){
134+
addPlaceItemToCache(placeItem)
118135
setResult(resp.body())
119-
finish()
136+
lifecycleScope.launch {
137+
finish()
138+
}
120139
}
121140
}
122141
}
142+
143+
private fun addPlaceItemToCache(placeItem: PlaceItem){
144+
val cachePlaceItems = placeItemDAO.getAll()
145+
if(cachePlaceItems.size >= 5){
146+
placeItemDAO.delete(cachePlaceItems[0])
147+
}
148+
cachePlaceItems.forEach {
149+
if(it.ref_id == placeItem.ref_id){
150+
placeItemDAO.delete(it)
151+
}
152+
}
153+
placeItemDAO.insertAll(placeItem)
154+
this.cachePlaceItems.let {
155+
it.clear()
156+
it.add(placeItem)
157+
}
158+
}
159+
160+
private fun getInitialPlaceItems(){
161+
cachePlaceItems.let {
162+
it.clear()
163+
it.addAll(placeItemDAO.getAll().reversed())
164+
}
165+
refreshSearchTemplate()
166+
searchTemplate.setItemList(
167+
ItemList.Builder()
168+
.apply {
169+
cachePlaceItems.forEach {
170+
addItem(
171+
Row.Builder()
172+
.setTitle(it.name)
173+
.setOnClickListener { onPlaceSelected(it) }
174+
.addText(it.address)
175+
.build()
176+
)
177+
}
178+
}
179+
.build()
180+
)
181+
invalidate()
182+
}
183+
123184
private var backAction = Action.Builder()
124185
.setIcon(CarIcon.BACK)
125186
.setOnClickListener { onBackPressed() }
@@ -194,11 +255,13 @@ class VietMapSearchScreen(carContext: CarContext): Screen(carContext), Lifecycle
194255
override fun onSearchResultSelected(call: MethodCall, result: MethodChannel.Result) {
195256
val args = call.arguments as Map<*, *>
196257
val refId = args["refId"] as String
197-
lifecycleScope.launch {
258+
ioCoroutineScope.launch {
198259
val resp = searchScreenService.getPlaceDetail(refId)
199260
if(resp.isSuccessful){
200261
setResult(resp.body())
201-
finish()
262+
lifecycleScope.launch {
263+
finish()
264+
}
202265
}
203266
}
204267
result.success(true)

android/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ if (flutterVersionName == null) {
2727
android {
2828
namespace 'vn.vietmap.vietmap_map'
2929
compileSdk 34
30-
ndkVersion flutter.ndkVersion
30+
ndkVersion "27.0.12077973"
3131

3232
compileOptions {
3333
sourceCompatibility JavaVersion.VERSION_1_8

android/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11

2+
plugins{
3+
id("com.google.devtools.ksp") version "1.9.22-1.0.17" apply false
4+
}
25

36
allprojects {
47
repositories {

lib/constants/events.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ class Events {
1515
static const String onCancelNavigation = 'cancelNavigation';
1616
static const String onRecenter = 'recenter';
1717
static const String onOverview = 'overview';
18+
static const String onFinishNavigation = 'finishNavigation';
1819
}

lib/features/routing_screen/routing_screen.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ class _RoutingScreenState extends State<RoutingScreen> {
192192
await _navigationController?.overview();
193193
_showRecenterButton();
194194
break;
195+
case Events.onFinishNavigation:
196+
await _navigationController?.finishNavigation();
197+
break;
195198
default:
196199
}
197200
},

0 commit comments

Comments
 (0)