Skip to content

Commit

Permalink
feat: Implement location feature in f-droid (fossasia#2006)
Browse files Browse the repository at this point in the history
  • Loading branch information
liveHarshit committed Jun 26, 2019
1 parent 7e3ca1e commit dc9f661
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 151 deletions.
Expand Up @@ -3,20 +3,30 @@ package org.fossasia.openevent.general.search.location
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.fossasia.openevent.general.common.SingleLiveEvent
import java.lang.IllegalArgumentException

class GeoLocationViewModel(locationService: LocationService) : ViewModel() {
class GeoLocationViewModel(private val locationService: LocationService) : ViewModel() {
private val mutableLocation = MutableLiveData<String>()
val location: LiveData<String> = mutableLocation
private val mutableVisibility = MutableLiveData<Boolean>(false)
val currentLocationVisibility: LiveData<Boolean> = mutableVisibility
private val mutableOpenLocationSettings = MutableLiveData<Boolean>()
val openLocationSettings: LiveData<Boolean> = mutableOpenLocationSettings
private val mutableErrorMessage = SingleLiveEvent<String>()
val errorMessage: LiveData<String> = mutableErrorMessage
private val compositeDisposable = CompositeDisposable()

fun configure() {
mutableVisibility.value = false
return
compositeDisposable += locationService.getAdministrativeArea()
.subscribe({
mutableLocation.value = it
}, {
mutableErrorMessage.value = if (it is IllegalArgumentException) "No area found"
else "Something went wrong"
})
}

override fun onCleared() {
super.onCleared()
compositeDisposable.clear()
}
}
@@ -1,11 +1,57 @@
package org.fossasia.openevent.general.search.location

import android.annotation.SuppressLint
import android.content.Context
import android.location.Geocoder
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import io.reactivex.Single
import java.lang.IllegalArgumentException
import java.util.Locale

class LocationServiceImpl(context: Context) : LocationService {
class LocationServiceImpl(private val context: Context) : LocationService {

@SuppressLint("MissingPermission")
override fun getAdministrativeArea(): Single<String> {
throw IllegalStateException("Attempt to use location functionality in F-Droid flavor")
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 = addresses[0].adminArea
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)
}
}
}
}

This file was deleted.

2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Expand Up @@ -7,6 +7,8 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<application
android:name=".OpenEventGeneral"
Expand Down
Expand Up @@ -7,7 +7,6 @@ import com.jakewharton.threetenabp.AndroidThreeTen
import org.fossasia.openevent.general.di.apiModule
import org.fossasia.openevent.general.di.commonModule
import org.fossasia.openevent.general.di.databaseModule
import org.fossasia.openevent.general.di.flavorSpecificModule
import org.fossasia.openevent.general.di.networkModule
import org.fossasia.openevent.general.di.viewModelModule
import org.koin.android.ext.koin.androidContext
Expand All @@ -34,8 +33,7 @@ class OpenEventGeneral : MultiDexApplication() {
apiModule,
viewModelModule,
networkModule,
databaseModule,
flavorSpecificModule
databaseModule
))
}
Timber.plant(Timber.DebugTree())
Expand Down
Expand Up @@ -66,10 +66,6 @@ class SearchLocationFragment : Fragment() {

setupRecentSearchLocations()

geoLocationViewModel.currentLocationVisibility.observe(viewLifecycleOwner, Observer {
rootView.currentLocation.isVisible = false
})

rootView.currentLocation.setOnClickListener {
checkLocationPermission()
if (isLocationEnabled(requireContext())) {
Expand All @@ -82,6 +78,13 @@ class SearchLocationFragment : Fragment() {
savePlaceAndRedirectToMain(location)
})

geoLocationViewModel.errorMessage
.nonNull()
.observe(viewLifecycleOwner, Observer {
rootView.snackbar(it)
rootView.locationProgressBar.visibility = View.GONE
})

searchLocationViewModel.placeSuggestions.observe(viewLifecycleOwner, Observer {
placeSuggestionsAdapter.submitList(it)
// To handle the case : search result comes after query is empty
Expand Down
@@ -1,10 +1,8 @@
package org.fossasia.openevent.general.welcome

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.provider.Settings
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand All @@ -19,7 +17,11 @@ import kotlinx.android.synthetic.main.fragment_welcome.view.currentLocation
import kotlinx.android.synthetic.main.fragment_welcome.view.locationProgressBar
import kotlinx.android.synthetic.main.fragment_welcome.view.skip
import org.fossasia.openevent.general.R
import org.fossasia.openevent.general.data.Preference
import org.fossasia.openevent.general.search.location.GeoLocationViewModel
import org.fossasia.openevent.general.search.location.SAVED_LOCATION
import org.fossasia.openevent.general.utils.Utils
import org.fossasia.openevent.general.utils.Utils.isLocationEnabled
import org.koin.androidx.viewmodel.ext.android.viewModel

const val LOCATION_SAVED = "LOCATION_SAVED"
Expand All @@ -28,7 +30,8 @@ const val WELCOME_FRAGMENT = "welcomeFragment"

class WelcomeFragment : Fragment() {
private lateinit var rootView: View
private val welcomeViewModel by viewModel<WelcomeViewModel>()
private val geoLocationViewModel by viewModel<GeoLocationViewModel>()
val preference = Preference()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_welcome, container, false)
Expand All @@ -39,35 +42,25 @@ class WelcomeFragment : Fragment() {
Navigation.findNavController(rootView).navigate(R.id.searchLocationFragment, null, Utils.getAnimSlide())
}

welcomeViewModel.currentLocationVisibility.observe(this, Observer {
rootView.currentLocation.visibility = View.GONE
})

rootView.currentLocation.setOnClickListener {
checkLocationPermission()
welcomeViewModel.configure()
rootView.locationProgressBar.visibility = View.VISIBLE
if (isLocationEnabled(requireContext())) {
geoLocationViewModel.configure()
rootView.locationProgressBar.visibility = View.VISIBLE
}
}

rootView.skip.setOnClickListener {
redirectToAuth()
}

welcomeViewModel.redirectToMain.observe(this, Observer { redirect ->
if (redirect) {
redirectToAuth()
}
})

welcomeViewModel.openLocationSettings.observe(this, Observer { open ->
if (open) {
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
}
geoLocationViewModel.location.observe(this, Observer {
preference.putString(SAVED_LOCATION, it)
redirectToAuth()
})

welcomeViewModel.errorMessage.observe(this, Observer { message ->
rootView.locationProgressBar.visibility = View.VISIBLE
geoLocationViewModel.errorMessage.observe(this, Observer { message ->
rootView.locationProgressBar.visibility = View.GONE
Snackbar.make(rootView, message, Snackbar.LENGTH_SHORT).show()
})

Expand All @@ -78,7 +71,7 @@ class WelcomeFragment : Fragment() {
when (requestCode) {
LOCATION_PERMISSION_REQUEST -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
welcomeViewModel.configure()
geoLocationViewModel.configure()
} else {
Snackbar.make(rootView, "Cannot fetch location!", Snackbar.LENGTH_SHORT).show()
rootView.locationProgressBar.visibility = View.GONE
Expand Down
6 changes: 0 additions & 6 deletions app/src/playStore/AndroidManifest.xml

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit dc9f661

Please sign in to comment.