Skip to content

Commit fe316eb

Browse files
committed
Add GetCurrentLocationUseCase and GoogleLocationService implementation
1 parent 6ec429c commit fe316eb

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.espressodev.gptmap.core.domain
2+
3+
import com.espressodev.gptmap.core.google.GoogleLocationService
4+
import kotlinx.coroutines.CoroutineDispatcher
5+
import kotlinx.coroutines.withContext
6+
import javax.inject.Inject
7+
8+
class GetCurrentLocationUseCase @Inject constructor(
9+
private val googleLocationService: GoogleLocationService,
10+
private val ioDispatcher: CoroutineDispatcher
11+
) {
12+
suspend operator fun invoke() = withContext(ioDispatcher) {
13+
googleLocationService.getCurrentLocation()
14+
}
15+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.espressodev.gptmap.core.google
2+
3+
import kotlinx.coroutines.flow.Flow
4+
5+
interface GoogleLocationService {
6+
suspend fun getCurrentLocation(): Flow<Result<Pair<Double, Double>>>
7+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.espressodev.gptmap.core.google.impl
2+
3+
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import android.location.Location
6+
import android.location.LocationManager
7+
import android.os.Build
8+
import androidx.annotation.RequiresApi
9+
import com.espressodev.gptmap.core.google.GoogleLocationService
10+
import com.espressodev.gptmap.core.model.Exceptions.GpsNotEnabledException
11+
import com.espressodev.gptmap.core.model.Exceptions.LocationNullThrowable
12+
import com.google.android.gms.location.FusedLocationProviderClient
13+
import com.google.android.gms.location.LocationCallback
14+
import com.google.android.gms.location.LocationRequest
15+
import com.google.android.gms.location.LocationResult
16+
import com.google.android.gms.location.Priority
17+
import kotlinx.coroutines.channels.awaitClose
18+
import kotlinx.coroutines.flow.Flow
19+
import kotlinx.coroutines.flow.callbackFlow
20+
import javax.inject.Inject
21+
22+
class GoogleLocationServiceImpl @Inject constructor(
23+
private val fusedLocationProviderClient: FusedLocationProviderClient,
24+
private val context: Context
25+
) : GoogleLocationService {
26+
27+
@SuppressLint("MissingPermission")
28+
@RequiresApi(Build.VERSION_CODES.S)
29+
override suspend fun getCurrentLocation(): Flow<Result<Pair<Double, Double>>> = callbackFlow {
30+
if (!isGpsEnabled()) {
31+
trySend(Result.failure(GpsNotEnabledException()))
32+
close()
33+
return@callbackFlow
34+
}
35+
36+
val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 500L)
37+
.setMaxUpdates(1)
38+
.setMinUpdateDistanceMeters(1000f)
39+
.build()
40+
41+
val locationCallback = object : LocationCallback() {
42+
override fun onLocationResult(locationResult: LocationResult) {
43+
locationResult.lastLocation?.let { newLocation ->
44+
trySend(Result.success(Pair(newLocation.latitude, newLocation.longitude)))
45+
} ?: trySend(Result.failure(LocationNullThrowable()))
46+
47+
close()
48+
}
49+
}
50+
51+
fusedLocationProviderClient.lastLocation
52+
.addOnSuccessListener { location: Location? ->
53+
location?.let {
54+
trySend(Result.success(Pair(location.latitude, location.longitude)))
55+
close()
56+
} ?: run {
57+
// If location is null, request a new location update
58+
fusedLocationProviderClient.requestLocationUpdates(
59+
locationRequest,
60+
locationCallback,
61+
null // We handle on the IO thread
62+
).addOnFailureListener { exception ->
63+
trySend(Result.failure(exception))
64+
close()
65+
}
66+
}
67+
}
68+
.addOnFailureListener { exception ->
69+
trySend(Result.failure(exception))
70+
close()
71+
}
72+
73+
awaitClose {
74+
fusedLocationProviderClient.removeLocationUpdates(locationCallback)
75+
}
76+
}
77+
78+
private fun isGpsEnabled(): Boolean {
79+
val locationManager =
80+
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
81+
return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) ||
82+
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
83+
}
84+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.espressodev.gptmap.core.google.module
2+
3+
import android.content.Context
4+
import com.espressodev.gptmap.core.google.GoogleLocationService
5+
import com.espressodev.gptmap.core.google.impl.GoogleLocationServiceImpl
6+
import com.google.android.gms.location.FusedLocationProviderClient
7+
import com.google.android.gms.location.LocationServices
8+
import dagger.Module
9+
import dagger.Provides
10+
import dagger.hilt.InstallIn
11+
import dagger.hilt.android.components.ViewModelComponent
12+
import dagger.hilt.android.qualifiers.ApplicationContext
13+
import dagger.hilt.android.scopes.ViewModelScoped
14+
15+
@Module
16+
@InstallIn(ViewModelComponent::class)
17+
object GoogleLocationModule {
18+
19+
@Provides
20+
@ViewModelScoped
21+
fun providesFusedLocationProviderClient(
22+
@ApplicationContext
23+
context: Context
24+
) = LocationServices.getFusedLocationProviderClient(context)
25+
26+
@Provides
27+
@ViewModelScoped
28+
fun providesGoogleLocationService(
29+
fusedLocationProviderClient: FusedLocationProviderClient,
30+
@ApplicationContext context: Context
31+
): GoogleLocationService = GoogleLocationServiceImpl(fusedLocationProviderClient, context)
32+
}

0 commit comments

Comments
 (0)