|
|
|
|
@ -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) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |