Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Administrative area in Location Detection #2637

Open
wants to merge 4 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GeoLocationViewModel(private val locationService: LocationService) : ViewM
private val compositeDisposable = CompositeDisposable()

fun configure() {
compositeDisposable += locationService.getAdministrativeArea()
compositeDisposable += locationService.getCityName()
.subscribe({
mutableLocation.value = it
}, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,47 @@ class LocationServiceImpl(
}
}
}

@SuppressLint("MissingPermission")
override fun getCityName(): Single<String> {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
?: return Single.error(IllegalStateException())
val geoCoder = Geocoder(context, Locale.getDefault())

return Single.create { emitter ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add single cancel handler

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will create a memory leak when Single is cancelled. Add logic to handle the cancellation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay

try {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f,
object : LocationListener {
override fun onLocationChanged(location: Location?) {
if (location == null) {
emitter.onError(java.lang.IllegalStateException())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What IllegalState?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given for the condition if incase it fails to update location to the variable then it gives the error for it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't see that message in IllegalStateException constructor. How would I know?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should I remove the it? or I had a question is there need of AdminArea if we are implementing it using cityName if not then should I change the method for calling the admin area with the city name as it will also save from creating another function for it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you should throw error with a proper message

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, I will fix it soon

return
}
val addresses = geoCoder.getFromLocation(location.latitude, location.longitude, 1)
try {
val adminArea = if (addresses.isNotEmpty()) addresses[0].locality
else resource.getString(R.string.no_location).nullToEmpty()
emitter.onSuccess(adminArea)
} catch (e: IllegalArgumentException) {
emitter.onError(e)
}
}

override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
// To change body of created functions use File | Settings | File Templates.
}

override fun onProviderEnabled(provider: String?) {
// To change body of created functions use File | Settings | File Templates.
}

override fun onProviderDisabled(provider: String?) {
// To change body of created functions use File | Settings | File Templates.
}
})
} catch (e: SecurityException) {
emitter.onError(e)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ interface LocationService {
* Gives the administrative area of the current location the user is in.
* */
fun getAdministrativeArea(): Single<String>
/**
* Gives the city name of the current location the user is in.
* */
fun getCityName(): Single<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class GeoLocationViewModel(private val locationService: LocationService) : ViewM
private val compositeDisposable = CompositeDisposable()

fun configure() {
compositeDisposable += locationService.getAdministrativeArea()
compositeDisposable += locationService.getCityName()
.subscribe(
{ adminArea ->
mutableLocation.value = adminArea
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,46 @@ class LocationServiceImpl(
}
}

override fun getCityName(): Single<String> {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE)

if (locationManager !is LocationManager) {
return Single.error(IllegalStateException())
}

if (!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
return Single.error(NoLocationSourceException())
}

val locationRequest = LocationRequest.create().apply {
priority = LocationRequest.PRIORITY_LOW_POWER
}
return Single.create { emitter ->
try {
LocationServices
.getFusedLocationProviderClient(context)
.requestLocationUpdates(locationRequest, object : LocationCallback() {

override fun onLocationResult(locationResult: LocationResult?) {
if (locationResult == null) {
emitter.onError(IllegalStateException())
return
}
try {
val locality = locationResult.getLocality()
emitter.onSuccess(locality)
} catch (e: Exception) {
Timber.e(e, "Error finding user current location")
emitter.onSuccess(resource.getString(R.string.no_location).nullToEmpty())
}
}
}, null)
} catch (e: SecurityException) {
emitter.onError(LocationPermissionException())
}
}
}

private fun LocationResult.getAdminArea(): String {
locations.filterNotNull().forEach { location ->
val latitude = location.latitude
Expand All @@ -80,4 +120,22 @@ class LocationServiceImpl(
}
throw IllegalArgumentException()
}

private fun LocationResult.getLocality(): String {
locations.filterNotNull().forEach { location ->
val latitude = location.latitude
val longitude = location.longitude
try {
val maxResults = 2
val geocoder = Geocoder(context, Locale.getDefault())
val addresses = geocoder.getFromLocation(latitude, longitude, maxResults)
val address = addresses.first { address -> address.locality != null }
return address.locality
} catch (exception: IOException) {
Timber.e(exception, "Error Fetching Location")
throw IllegalArgumentException()
}
}
throw IllegalArgumentException()
}
}