Skip to content

Instantly share code, notes, and snippets.

@mvasilova
Created December 9, 2019 08:05
Show Gist options
  • Save mvasilova/7f4604dc6cc3b293dfa9a7b26fff4de5 to your computer and use it in GitHub Desktop.
Save mvasilova/7f4604dc6cc3b293dfa9a7b26fff4de5 to your computer and use it in GitHub Desktop.
Definition of geolocation - latitude, longitude (with GPS, ipAddress, RxPermissions) - Android (Kotlin)
//Definition of geolocation - latitude, longitude in Fragment
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationRequest: LocationRequest
private lateinit var locationCallback: LocationCallback
private lateinit var rxPermissions: RxPermissions
private var latitude: Double? = 0.0
private var longitude: Double? = 0.0
val compositeDisposable = CompositeDisposable()
companion object {
private const val UPDATE_INTERVAL: Long = 15 * 1000
private const val FASTEST_INTERVAL: Long = 5000
}
override fun onCreate(savedInstanceState: Bundle?) {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(activity!!)
rxPermissions = RxPermissions(this)
locationCallback = LocationCallback()
super.onCreate(savedInstanceState)
}
//Call this method on ClickListener
private fun checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
compositeDisposable.add(rxPermissions
.request(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
.subscribe { granted ->
if (!granted) {
Toast.makeText(
activity,
getString(R.string.toast_location_permission),
Toast.LENGTH_LONG
).show()
} else {
checkEnabledGPS()
}
})
} else {
checkEnabledGPS()
}
}
private fun checkEnabledGPS() {
val service: LocationManager = activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val isEnabled =
service.isProviderEnabled(LocationManager.GPS_PROVIDER) || service.isProviderEnabled(
LocationManager.NETWORK_PROVIDER)
if (!isEnabled) {
Toast.makeText(activity, getString(R.string.toast_location_enabled), Toast.LENGTH_LONG).show()
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
} else {
startLocationUpdates()
}
}
private fun startLocationUpdates() {
locationRequest = LocationRequest.create()
locationRequest.run {
priority = LocationRequest.PRIORITY_LOW_POWER
interval = UPDATE_INTERVAL
setFastestInterval(FASTEST_INTERVAL)
}
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(locationRequest)
val locationSettingsRequest = builder.build()
val settingsClient = LocationServices.getSettingsClient(activity!!)
settingsClient!!.checkLocationSettings(locationSettingsRequest)
registerLocationListener()
}
private fun registerLocationListener() {
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult?.let {
obtainLocalization()
fusedLocationClient.removeLocationUpdates(this)
}
}
}
LocationServices.getFusedLocationProviderClient(activity!!)
.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
}
private fun obtainLocalization() {
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
location?.let {
latitude = location.latitude
longitude = location.longitude
//TODO
//Use latitude & longitude forward
}
}
}
override fun onDestroy() {
super.onDestroy()
fusedLocationClient.removeLocationUpdates(locationCallback)
compositeDisposable.clear()
}
import android.Manifest
import android.app.Activity
import android.content.Context
import android.location.Location
import android.location.LocationManager
import android.os.Build
import android.os.Looper
import androidx.fragment.app.Fragment
import com.google.android.gms.location.*
import com.tbruyelle.rxpermissions2.RxPermissions
import io.reactivex.disposables.CompositeDisposable
import ru.profsoft.farmakopeika.ui.utils.getLocalIpAddress
class LocationManager(val activity: Activity?, val fragment: Fragment) {
private lateinit var locationRequest: LocationRequest
private var fusedLocationClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity!!)
private var locationCallback: LocationCallback = LocationCallback()
private var rxPermissions: RxPermissions = RxPermissions(fragment)
private var latitude: Double = 0.0
private var longitude: Double = 0.0
private var ipAddress: String = ""
private val compositeDisposable = CompositeDisposable()
companion object {
private const val UPDATE_INTERVAL: Long = 15 * 1000
private const val FASTEST_INTERVAL: Long = 5000
}
fun getLocation(listener: (LocationData) -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
compositeDisposable.add(rxPermissions
.request(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
.subscribe { granted ->
if (!granted) {
//Use IP instead GPS when permissions not granted
ipAddress = getLocalIpAddress()
listener.invoke(LocationData(ipAddress, null))
} else {
checkEnabledGPS(listener)
}
})
} else {
checkEnabledGPS(listener)
}
}
private fun checkEnabledGPS(listener: (LocationData) -> Unit) {
val service: LocationManager =
activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val isEnabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER) || service.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
if (!isEnabled) {
ipAddress = getLocalIpAddress()
listener.invoke(LocationData(ipAddress, null))
} else {
locationRequest = LocationRequest.create()
locationRequest.run {
priority = LocationRequest.PRIORITY_LOW_POWER
interval = UPDATE_INTERVAL
setFastestInterval(FASTEST_INTERVAL)
}
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(locationRequest)
val locationSettingsRequest = builder.build()
val settingsClient = LocationServices.getSettingsClient(activity)
settingsClient!!.checkLocationSettings(locationSettingsRequest)
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult?.let {
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
location?.let {
latitude = location.latitude
longitude = location.longitude
listener.invoke(LocationData(null, Pair(latitude, longitude)))
}
}
fusedLocationClient.removeLocationUpdates(this)
}
}
}
LocationServices.getFusedLocationProviderClient(activity).requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
}
}
fun clearAll() {
fusedLocationClient.removeLocationUpdates(locationCallback)
compositeDisposable.clear()
}
data class LocationData(var ipAddress: String?, var coordinates: Pair<Double, Double>?)
}
//Usages in Activity or Fragment
lateinit var locationManager: LocationManager
//onCreate method
locationManager = LocationManager(activity, this)
//actions for clicklistener or sometheng else
locationManager.getLocation {
if (it.ipAddress != null && it.ipAddress != "") {
//TODO
//use ipAddress
//Example:
//presenter.getLocationByIp(it.ipAddress!!)
} else if (it.coordinates != null) {
//TODO
//use ipAddress
//Example:
//presenter.getLocationByCoordinates(it.coordinates!!.first, it.coordinates!!.second)
} else {
//TODO
//if ip == null && coordinates == null
}
}
//Extensions
fun getLocalIpAddress(): String {
try {
val en = NetworkInterface.getNetworkInterfaces()
while (en.hasMoreElements()) {
val intf = en.nextElement()
val enumIpAddr = intf.inetAddresses
while (enumIpAddr.hasMoreElements()) {
val inetAddress = enumIpAddr.nextElement()
if (!inetAddress.isLoopbackAddress && inetAddress is Inet4Address) {
return inetAddress.getHostAddress()
}
}
}
} catch (ex: SocketException) {
ex.printStackTrace()
}
return ""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment