Add findNearestLocation & refactor callbacks management

feature/top10
Aurelien Hubert 7 years ago
parent 02b05d99f1
commit 7476af5e6c
  1. 55
      app/src/main/java/net/pokeranalytics/android/ui/activity/components/PokerAnalyticsActivity.kt
  2. 91
      app/src/main/java/net/pokeranalytics/android/util/LocationManager.kt

@ -10,8 +10,8 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.google.android.libraries.places.api.model.PlaceLikelihood
import io.realm.Realm
import net.pokeranalytics.android.model.realm.Location
import net.pokeranalytics.android.util.LocationManager
import java.util.*
open class PokerAnalyticsActivity : AppCompatActivity() {
@ -21,8 +21,7 @@ open class PokerAnalyticsActivity : AppCompatActivity() {
}
private val realm = Realm.getDefaultInstance()
private var askFromPlaces = false
private var currentCallback: ((success: Boolean, places: ArrayList<PlaceLikelihood>) -> Unit)? = null
private var permissionCallback: ((granted: Boolean) -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -36,8 +35,9 @@ open class PokerAnalyticsActivity : AppCompatActivity() {
if (permissions.isNotEmpty() && permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION
&& grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
locationPermissionGranted()
permissionCallback?.invoke(true)
} else {
permissionCallback?.invoke(false)
// permission denied, boo! Disable the
// functionality that depends on this permission.
// showMessage(getString(R.string.error));
@ -71,35 +71,50 @@ open class PokerAnalyticsActivity : AppCompatActivity() {
/**
* Ask for location permission
*/
private fun askForLocationPermission() {
private fun askForLocationPermission(permissionCallback: ((granted: Boolean) -> Unit)) {
this.permissionCallback = permissionCallback
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_ACCESS_FINE_LOCATION
this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_ACCESS_FINE_LOCATION
)
}
/**
* Called when the permission location has been granted
*/
open fun locationPermissionGranted() {
if (askFromPlaces) {
askFromPlaces = false
askForPlacesRequest(currentCallback)
}
}
/**
* Ask for places request
*/
fun askForPlacesRequest(callback: ((success: Boolean, places: ArrayList<PlaceLikelihood>) -> Unit)?) {
// Call findCurrentPlace and handle the response (first check that the user has granted permission).
if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationManager(this).askForPlacesRequest(callback)
} else {
askFromPlaces = true
currentCallback = callback
askForLocationPermission()
askForLocationPermission { granted ->
if (granted) {
LocationManager(this).askForPlacesRequest(callback)
} else {
callback?.invoke(false, ArrayList())
}
}
}
}
/**
* Find the nearest location from the user
*/
fun findNearestLocation(callback: ((location: Location?) -> Unit)?) {
if (LocationManager(this).databaseContainsLocationsWithCoordinates()) {
if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationManager(this).findNearestLocationFromUser(callback)
} else {
askForLocationPermission { granted ->
if (granted) {
LocationManager(this).findNearestLocationFromUser(callback)
} else {
callback?.invoke(null)
}
}
}
} else {
callback?.invoke(null)
}
}

@ -5,15 +5,25 @@ import android.content.Context
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.libraries.places.api.Places
import com.google.android.libraries.places.api.model.Place
import com.google.android.libraries.places.api.model.PlaceLikelihood
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest
import io.realm.Realm
import io.realm.kotlin.where
import net.pokeranalytics.android.model.realm.Location
import timber.log.Timber
import java.util.*
import kotlin.collections.ArrayList
class LocationManager(private var context: Context) {
companion object {
const val MAXIMUM_DISTANCE_FROM_USER = 5000 // in meters
}
/**
* Return the [places] around the user
*/
@ -50,8 +60,89 @@ class LocationManager(private var context: Context) {
callback?.invoke(task.isSuccessful, places)
}
} else {
// If we don't have the permission, return
callback?.invoke(false, ArrayList())
}
}
/**
* Return if the database contains one or many locations with coordinates
*/
fun databaseContainsLocationsWithCoordinates(): Boolean {
val realm = Realm.getDefaultInstance()
val result = realm.where<Location>().isNotNull("latitude")
.and().isNotNull("longitude").findAll().isNotEmpty()
realm.close()
return result
}
/**
* Find the nearest location from user
*/
fun findNearestLocationFromUser(callback: ((location: Location?) -> Unit)?) {
val locations = ArrayList<net.pokeranalytics.android.model.realm.Location>()
val realm = Realm.getDefaultInstance()
val realmResults = realm.where<Location>().isNotNull("latitude")
.and().isNotNull("longitude").findAll()
locations.addAll(realm.copyFromRealm(realmResults))
realm.close()
// If we have no locations with coordinates, return null
if (realmResults.size == 0) {
callback?.invoke(null)
return
}
val fusedLocationClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
if (ContextCompat.checkSelfPermission(context, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationClient.lastLocation.addOnSuccessListener { location: android.location.Location? ->
// Got last known location. In some rare situations this can be null.
location?.let { currentLocation ->
locations.sortBy {
val locationToSort = android.location.Location("")
locationToSort.latitude = it.latitude!!
locationToSort.longitude = it.longitude!!
currentLocation.distanceTo(locationToSort)
}
val nearestLocation = locations.firstOrNull()
nearestLocation?.let {
val locationForDistance = android.location.Location("")
locationForDistance.latitude = it.latitude ?: 0.0
locationForDistance.longitude = it.longitude ?: 0.0
// Final check: if the distance between the location and the user is lower than MAXIMUM_DISTANCE_FROM_USER
if (currentLocation.distanceTo(locationForDistance) < MAXIMUM_DISTANCE_FROM_USER) {
callback?.invoke(nearestLocation)
} else {
callback?.invoke(null)
}
} ?: run {
callback?.invoke(null)
}
} ?: run {
// If the current location is null, return null
callback?.invoke(null)
}
}.addOnCanceledListener {
// If there was a problem during the call to last location, return null
callback?.invoke(null)
}
} else {
// If we don't have the permission, return null
callback?.invoke(null)
}
}
}
Loading…
Cancel
Save