Skip to content

Commit

Permalink
Use channel to ensure only one location push task is running at a giv…
Browse files Browse the repository at this point in the history
…en time
  • Loading branch information
newmanw committed Dec 20, 2023
1 parent dd2b07e commit 4130ef2
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,17 @@ class LocationRepository @Inject constructor(
try {
val response = locationService.pushLocations(event.remoteId, localLocations)
if (response.isSuccessful) {
val remoteLocations = response.body() ?: emptyList()
val pushedLocations = response.body() ?: emptyList()
// We've sync-ed locations to the server, lets remove the locations we synced from the database
Log.d(LOG_NAME, "Pushed " + remoteLocations.size + " locations.")
Log.d(LOG_NAME, "Pushed " + pushedLocations.size + " locations.")
try {
localLocations.forEachIndexed { index, localLocation ->
val remoteLocation = remoteLocations.getOrNull(index)
if (remoteLocation == null) {
val remoteId = pushedLocations.getOrNull(index)?.remoteId
if (remoteId == null) {
locationLocalDataSource.delete(listOf(localLocation))
} else {
remoteLocation.id = localLocation.id
remoteLocation.user = currentUser
remoteLocation.event = event
locationLocalDataSource.update(remoteLocation)
localLocation.remoteId = remoteId
locationLocalDataSource.update(localLocation)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ package mil.nga.giat.mage.location
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.location.Location
import android.location.LocationManager
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.lifecycle.LifecycleService
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import mil.nga.giat.mage.MageApplication
import mil.nga.giat.mage.R
Expand All @@ -34,6 +34,7 @@ open class LocationReportingService : LifecycleService(), Observer<Location>, Sh
private var shouldReportLocation: Boolean = false
private var locationPushFrequency: Long = 0
private var oldestLocationTime: Long = 0
private lateinit var locationChannel: Channel<Location>

companion object {
private val LOG_NAME = LocationReportingService::class.java.name
Expand All @@ -57,12 +58,10 @@ open class LocationReportingService : LifecycleService(), Observer<Location>, Sh
locationPushFrequency = getLocationPushFrequency()
shouldReportLocation = getShouldReportLocation()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, "MAGE", NotificationManager.IMPORTANCE_MIN)
channel.setShowBadge(true)
notificationManager.createNotificationChannel(channel)
}
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationChannel = NotificationChannel(NOTIFICATION_CHANNEL_ID, "MAGE", NotificationManager.IMPORTANCE_MIN)
notificationChannel.setShowBadge(true)
notificationManager.createNotificationChannel(notificationChannel)

val intent = Intent(applicationContext, LoginActivity::class.java)
intent.putExtra("LOGOUT", true)
Expand All @@ -77,6 +76,13 @@ open class LocationReportingService : LifecycleService(), Observer<Location>, Sh
.addAction(R.drawable.ic_power_settings_new_white_24dp, "Logout", pendingIntent)
.build()

locationChannel = Channel(Channel.CONFLATED)
lifecycleScope.launch {
locationChannel.receiveAsFlow().collect { location ->
pushLocations(location)
}
}

startForeground(NOTIFICATION_ID, notification)
}

Expand All @@ -85,34 +91,37 @@ open class LocationReportingService : LifecycleService(), Observer<Location>, Sh

locationProvider.observe(this, this)

return Service.START_STICKY
return START_STICKY
}

override fun onDestroy() {
super.onDestroy()

locationProvider.removeObserver(this)

locationChannel.close()
preferences.unregisterOnSharedPreferenceChangeListener(this)
}

override fun onChanged(location: Location) {
if (shouldReportLocation && location?.provider == LocationManager.GPS_PROVIDER) {
override fun onChanged(value: Location) {
if (shouldReportLocation && value.provider == LocationManager.GPS_PROVIDER) {
Log.v(LOG_NAME, "GPS location changed")

lifecycleScope.launch {
locationRepository.saveLocation(location)

if (oldestLocationTime == 0L) {
oldestLocationTime = location.time
}

if (!locationAccess.isPreciseLocationGranted() || (location.time - oldestLocationTime > locationPushFrequency)) {
val success = locationRepository.pushLocations()
if (success) {
oldestLocationTime = 0
}
}
locationRepository.saveLocation(value)
locationChannel.send(value)
}
}
}

private suspend fun pushLocations(location: Location) {
if (oldestLocationTime == 0L) {
oldestLocationTime = location.time
}

if (!locationAccess.isPreciseLocationGranted() || (location.time - oldestLocationTime > locationPushFrequency)) {
val success = locationRepository.pushLocations()
if (success) {
oldestLocationTime = 0
}
}
}
Expand Down

0 comments on commit 4130ef2

Please sign in to comment.