Skip to content

Commit

Permalink
Add GPS Service.
Browse files Browse the repository at this point in the history
  • Loading branch information
alejandrocalles committed May 31, 2024
1 parent aac986d commit 188f72c
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 1 deletion.
5 changes: 4 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ dependencies {
// Map Libre
implementation(libs.android.sdk)
implementation(libs.ramani.maplibre)


// Location
implementation(libs.play.services.location)

// Hilt
implementation(libs.hilt.android)
implementation(libs.androidx.hilt.navigation.compose)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.github.swent.echo.connectivity

import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.mapbox.mapboxsdk.geometry.LatLng
import org.junit.Assert.assertNotNull
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class GPSServiceImplTest {
private lateinit var gpsService: GPSService

@get:Rule val composeTestRule = createComposeRule()

@Test
fun shouldRefreshLocation() {
lateinit var location: State<LatLng?>
composeTestRule.setContent {
gpsService = GPSServiceImpl(LocalContext.current)
location = gpsService.userLocation.collectAsState()
}
composeTestRule.waitForIdle()
assertNotNull(gpsService.userLocation)
}
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/github/swent/echo/connectivity/GPSService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.github.swent.echo.connectivity

import com.mapbox.mapboxsdk.geometry.LatLng
import kotlinx.coroutines.flow.StateFlow

/** A GPS service. Allows the location to be accessed either as */
interface GPSService {
val userLocation: StateFlow<LatLng?>

fun currentUserLocation(): LatLng?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.github.swent.echo.connectivity

import android.content.Context
import android.content.pm.PackageManager
import android.location.LocationManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat.getSystemService
import com.github.swent.echo.compose.navigation.LOCATION_PERMISSIONS
import com.google.android.gms.location.LocationServices
import com.mapbox.mapboxsdk.geometry.LatLng
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

class GPSServiceImpl(context: Context) : GPSService {
private val locationProviderClient = LocationServices.getFusedLocationProviderClient(context)
private val locationManager: LocationManager? =
getSystemService(context, LocationManager::class.java)
private var _location = MutableStateFlow<LatLng?>(null)

private fun getLocation(context: Context) {
if (
LOCATION_PERMISSIONS.any {
ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
) {
locationProviderClient.lastLocation.addOnSuccessListener {
it?.apply {
val old = _location.value
_location.compareAndSet(
old,
this.let { location -> LatLng(location.latitude, location.longitude) }
)
}
// Request again if null, unless location is turned off in settings
locationManager?.apply {
// TODO maybe also check for NETWORK_PROVIDER
if (isProviderEnabled(LocationManager.GPS_PROVIDER)) {
it ?: getLocation(context)
}
}
}
}
}

init {
getLocation(context)
}

override val userLocation: StateFlow<LatLng?> = _location.asStateFlow()

override fun currentUserLocation(): LatLng? = _location.value

fun refreshUserLocation(context: Context) = getLocation(context)
}
22 changes: 22 additions & 0 deletions app/src/main/java/com/github/swent/echo/di/GPSServiceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.github.swent.echo.di

import android.app.Application
import com.github.swent.echo.connectivity.GPSService
import com.github.swent.echo.connectivity.GPSServiceImpl
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object GPSServiceModule {

@Singleton
@Provides
fun provideGPSService(application: Application): GPSService {
val context = application.applicationContext
return GPSServiceImpl(context)
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ androidSdk = "10.2.0"
#####################
kotlinxSerializationJson = "1.6.3"
ktorClientAndroid = "2.3.9"
playServicesLocation = "21.3.0"
ramaniMaplibre = "0.3.0"
robolectric = "4.12"
roomRuntime = "2.6.1"
Expand Down Expand Up @@ -47,6 +48,7 @@ hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", vers
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktorClientAndroid" }
mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockk" }
play-services-location = { module = "com.google.android.gms:play-services-location", version.ref = "playServicesLocation" }
ramani-maplibre = { module = "org.ramani-maps:ramani-maplibre", version.ref = "ramaniMaplibre" }
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4jSimple" }
Expand Down

0 comments on commit 188f72c

Please sign in to comment.