151 lines
6.1 KiB
Kotlin
151 lines
6.1 KiB
Kotlin
package info.nightscout.androidaps.services
|
|
|
|
import android.Manifest
|
|
import android.app.Service
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.pm.PackageManager
|
|
import android.location.Location
|
|
import android.location.LocationManager
|
|
import android.os.Bundle
|
|
import android.os.IBinder
|
|
import androidx.core.app.ActivityCompat
|
|
import com.google.android.gms.location.LocationServices
|
|
import dagger.android.DaggerService
|
|
import info.nightscout.androidaps.MainApp
|
|
import info.nightscout.androidaps.R
|
|
import info.nightscout.androidaps.events.EventAppExit
|
|
import info.nightscout.androidaps.events.EventLocationChange
|
|
import info.nightscout.androidaps.logging.AAPSLogger
|
|
import info.nightscout.androidaps.logging.LTag
|
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
|
import info.nightscout.androidaps.utils.T
|
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
|
import io.reactivex.disposables.CompositeDisposable
|
|
import io.reactivex.schedulers.Schedulers
|
|
import javax.inject.Inject
|
|
|
|
class LocationService : DaggerService() {
|
|
@Inject lateinit var aapsLogger: AAPSLogger
|
|
@Inject lateinit var rxBus: RxBusWrapper
|
|
@Inject lateinit var sp: SP
|
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
|
@Inject lateinit var mainApp: MainApp
|
|
|
|
private val disposable = CompositeDisposable()
|
|
private var locationManager: LocationManager? = null
|
|
private var locationListener: LocationListener? = null
|
|
|
|
private val LOCATION_INTERVAL_ACTIVE = T.mins(5).msecs()
|
|
private val LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs() // this doesn't cost more power
|
|
|
|
companion object {
|
|
private const val LOCATION_DISTANCE = 10f
|
|
private var lastLocation: Location? = null
|
|
|
|
@JvmStatic
|
|
@Deprecated("replace by injection")
|
|
fun getLastLocation(): Location? = lastLocation
|
|
}
|
|
|
|
inner class LocationListener internal constructor(val provider: String) : android.location.LocationListener {
|
|
|
|
init {
|
|
aapsLogger.debug(LTag.LOCATION, "LocationListener $provider")
|
|
}
|
|
|
|
override fun onLocationChanged(location: Location) {
|
|
aapsLogger.debug(LTag.LOCATION, "onLocationChanged: $location")
|
|
lastLocation = location
|
|
rxBus.send(EventLocationChange(location))
|
|
}
|
|
|
|
override fun onProviderDisabled(provider: String) {
|
|
aapsLogger.debug(LTag.LOCATION, "onProviderDisabled: $provider")
|
|
}
|
|
|
|
override fun onProviderEnabled(provider: String) {
|
|
aapsLogger.debug(LTag.LOCATION, "onProviderEnabled: $provider")
|
|
}
|
|
|
|
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
|
|
aapsLogger.debug(LTag.LOCATION, "onStatusChanged: $provider")
|
|
}
|
|
}
|
|
|
|
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
|
super.onStartCommand(intent, flags, startId)
|
|
startForeground(mainApp.notificationId(), mainApp.getNotification())
|
|
return Service.START_STICKY
|
|
}
|
|
|
|
override fun onCreate() {
|
|
super.onCreate()
|
|
startForeground(mainApp.notificationId(), mainApp.getNotification())
|
|
|
|
// Get last location once until we get regular update
|
|
LocationServices.getFusedLocationProviderClient(this).lastLocation.addOnSuccessListener {
|
|
lastLocation = it
|
|
}
|
|
|
|
initializeLocationManager()
|
|
|
|
try {
|
|
if (sp.getString(R.string.key_location, "NONE") == "NETWORK") locationManager?.requestLocationUpdates(
|
|
LocationManager.NETWORK_PROVIDER,
|
|
LOCATION_INTERVAL_ACTIVE,
|
|
LOCATION_DISTANCE,
|
|
LocationListener(LocationManager.NETWORK_PROVIDER).also { locationListener = it }
|
|
)
|
|
if (sp.getString(R.string.key_location, "NONE") == "GPS") locationManager?.requestLocationUpdates(
|
|
LocationManager.GPS_PROVIDER,
|
|
LOCATION_INTERVAL_ACTIVE,
|
|
LOCATION_DISTANCE,
|
|
LocationListener(LocationManager.GPS_PROVIDER).also { locationListener = it }
|
|
)
|
|
if (sp.getString(R.string.key_location, "NONE") == "PASSIVE") locationManager?.requestLocationUpdates(
|
|
LocationManager.PASSIVE_PROVIDER,
|
|
LOCATION_INTERVAL_PASSIVE,
|
|
LOCATION_DISTANCE,
|
|
LocationListener(LocationManager.PASSIVE_PROVIDER).also { locationListener = it }
|
|
)
|
|
} catch (ex: SecurityException) {
|
|
aapsLogger.error(LTag.LOCATION, "fail to request location update, ignore", ex)
|
|
} catch (ex: IllegalArgumentException) {
|
|
aapsLogger.error(LTag.LOCATION, "network provider does not exist", ex)
|
|
}
|
|
disposable.add(rxBus
|
|
.toObservable(EventAppExit::class.java)
|
|
.observeOn(Schedulers.io())
|
|
.subscribe({
|
|
aapsLogger.debug(LTag.LOCATION, "EventAppExit received")
|
|
stopSelf()
|
|
}) { fabricPrivacy.logException(it) }
|
|
)
|
|
}
|
|
|
|
override fun onDestroy() {
|
|
super.onDestroy()
|
|
if (locationManager != null) {
|
|
try {
|
|
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
|
return
|
|
}
|
|
locationManager!!.removeUpdates(locationListener)
|
|
} catch (ex: Exception) {
|
|
aapsLogger.error(LTag.LOCATION, "fail to remove location listener, ignore", ex)
|
|
}
|
|
}
|
|
disposable.clear()
|
|
}
|
|
|
|
override fun onBind(intent: Intent?): IBinder? = null
|
|
|
|
private fun initializeLocationManager() {
|
|
aapsLogger.debug(LTag.LOCATION, "initializeLocationManager - Provider: " + sp.getString(R.string.key_location, "NONE"))
|
|
if (locationManager == null) {
|
|
locationManager = applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
|
}
|
|
}
|
|
} |