diff --git a/app/src/fdroid/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt b/app/src/fdroid/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt index b44c94cb21..39bb25e33f 100644 --- a/app/src/fdroid/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt +++ b/app/src/fdroid/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt @@ -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 }, { diff --git a/app/src/fdroid/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt b/app/src/fdroid/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt index e569f3dc91..af3eebe94e 100644 --- a/app/src/fdroid/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt +++ b/app/src/fdroid/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt @@ -61,4 +61,47 @@ class LocationServiceImpl( } } } + + @SuppressLint("MissingPermission") + override fun getCityName(): Single { + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as? LocationManager + ?: return Single.error(IllegalStateException()) + val geoCoder = Geocoder(context, Locale.getDefault()) + + return Single.create { emitter -> + try { + locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f, + object : LocationListener { + override fun onLocationChanged(location: Location?) { + if (location == null) { + emitter.onError(java.lang.IllegalStateException()) + 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) + } + } + } } diff --git a/app/src/main/java/org/fossasia/openevent/general/search/location/LocationService.kt b/app/src/main/java/org/fossasia/openevent/general/search/location/LocationService.kt index dbfcf15907..874a1b4fd4 100644 --- a/app/src/main/java/org/fossasia/openevent/general/search/location/LocationService.kt +++ b/app/src/main/java/org/fossasia/openevent/general/search/location/LocationService.kt @@ -11,4 +11,8 @@ interface LocationService { * Gives the administrative area of the current location the user is in. * */ fun getAdministrativeArea(): Single + /** + * Gives the city name of the current location the user is in. + * */ + fun getCityName(): Single } diff --git a/app/src/playStore/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt b/app/src/playStore/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt index 1efd84e923..409b2c8d77 100644 --- a/app/src/playStore/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt +++ b/app/src/playStore/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt @@ -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 diff --git a/app/src/playStore/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt b/app/src/playStore/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt index 96bc7250ca..7205ac69a5 100644 --- a/app/src/playStore/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt +++ b/app/src/playStore/java/org/fossasia/openevent/general/search/location/LocationServiceImpl.kt @@ -63,6 +63,46 @@ class LocationServiceImpl( } } + override fun getCityName(): Single { + 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 @@ -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() + } }