LocationServiceHelper

This commit is contained in:
Milos Kozak 2021-01-16 18:36:57 +01:00
parent 22f9ccab32
commit d40559d444
3 changed files with 87 additions and 22 deletions

View file

@ -1,8 +1,6 @@
package info.nightscout.androidaps.plugins.general.automation
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import android.os.SystemClock
@ -27,7 +25,7 @@ import info.nightscout.androidaps.plugins.general.automation.events.EventAutomat
import info.nightscout.androidaps.plugins.general.automation.triggers.*
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.services.LocationService
import info.nightscout.androidaps.services.LocationServiceHelper
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
@ -55,6 +53,7 @@ class AutomationPlugin @Inject constructor(
private val rxBus: RxBusWrapper,
private val constraintChecker: ConstraintChecker,
aapsLogger: AAPSLogger,
private val locationServiceHelper: LocationServiceHelper,
private val dateUtil: DateUtil
) : PluginBase(PluginDescription()
.mainType(PluginType.GENERAL)
@ -91,10 +90,7 @@ class AutomationPlugin @Inject constructor(
}
override fun onStart() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
context.startForegroundService(Intent(context, LocationService::class.java))
else
context.startService(Intent(context, LocationService::class.java))
locationServiceHelper.startService(context)
super.onStart()
loadFromSP()
@ -105,17 +101,14 @@ class AutomationPlugin @Inject constructor(
.observeOn(Schedulers.io())
.subscribe({ e ->
if (e.isChanged(resourceHelper, R.string.key_location)) {
context.stopService(Intent(context, LocationService::class.java))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
context.startForegroundService(Intent(context, LocationService::class.java))
else
context.startService(Intent(context, LocationService::class.java))
locationServiceHelper.stopService(context)
locationServiceHelper.startService(context)
}
}, { fabricPrivacy.logException(it) })
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventAutomationDataChanged::class.java)
.observeOn(Schedulers.io())
.subscribe({ storeToSP() }, { fabricPrivacy.logException(it) })
.subscribe({ storeToSP() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventLocationChange::class.java)
.observeOn(Schedulers.io())
@ -124,19 +117,19 @@ class AutomationPlugin @Inject constructor(
aapsLogger.debug(LTag.AUTOMATION, "Grabbed location: $it.location.latitude $it.location.longitude Provider: $it.location.provider")
processActions()
}
}, { fabricPrivacy.logException(it) })
}, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventChargingState::class.java)
.observeOn(Schedulers.io())
.subscribe({ processActions() }, { fabricPrivacy.logException(it) })
.subscribe({ processActions() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNetworkChange::class.java)
.observeOn(Schedulers.io())
.subscribe({ processActions() }, { fabricPrivacy.logException(it) })
.subscribe({ processActions() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventAutosensCalculationFinished::class.java)
.observeOn(Schedulers.io())
.subscribe({ processActions() }, { fabricPrivacy.logException(it) })
.subscribe({ processActions() }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventBTChange::class.java)
.observeOn(Schedulers.io())
@ -144,13 +137,13 @@ class AutomationPlugin @Inject constructor(
aapsLogger.debug(LTag.AUTOMATION, "Grabbed new BT event: $it")
btConnects.add(it)
processActions()
}, { fabricPrivacy.logException(it) })
}, fabricPrivacy::logException)
}
override fun onStop() {
disposable.clear()
loopHandler.removeCallbacks(refreshLoop)
context.stopService(Intent(context, LocationService::class.java))
locationServiceHelper.stopService(context)
super.onStop()
}

View file

@ -1,3 +1,5 @@
@file:Suppress("PrivatePropertyName")
package info.nightscout.androidaps.services
import android.Manifest
@ -8,6 +10,7 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationManager
import android.os.Binder
import android.os.Bundle
import android.os.IBinder
import androidx.core.app.ActivityCompat
@ -44,9 +47,18 @@ class LocationService : DaggerService() {
private val LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs() // this doesn't cost more power
companion object {
private const val LOCATION_DISTANCE = 10f
}
inner class LocalBinder : Binder() {
fun getService(): LocationService = this@LocationService
}
private val binder = LocalBinder()
override fun onBind(intent: Intent): IBinder = binder
inner class LocationListener internal constructor(val provider: String) : android.location.LocationListener {
init {
@ -148,8 +160,6 @@ class LocationService : DaggerService() {
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) {

View file

@ -0,0 +1,62 @@
package info.nightscout.androidaps.services
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import info.nightscout.androidaps.interfaces.NotificationHolderInterface
import javax.inject.Inject
import javax.inject.Singleton
/*
This code replaces following
val intent = Intent(context, LocationService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(intent) else context.startService(intent)
it fails randomly with error
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{e317f7e u0 info.nightscout.nsclient/info.nightscout.androidaps.services.LocationService}
*/
@Singleton
class LocationServiceHelper @Inject constructor(
private val notificationHolder: NotificationHolderInterface
) {
fun startService(context: Context) {
val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
// The binder of the service that returns the instance that is created.
val binder = service as LocationService.LocalBinder
val locationService: LocationService = binder.getService()
context.startForegroundService(Intent(context, LocationService::class.java))
// This is the key: Without waiting Android Framework to call this method
// inside Service.onCreate(), immediately call here to post the notification.
locationService.startForeground(notificationHolder.notificationID, notificationHolder.notification)
// Release the connection to prevent leaks.
context.unbindService(this)
}
override fun onServiceDisconnected(name: ComponentName?) {
}
}
try {
context.bindService(Intent(context, LocationService::class.java), connection, Context.BIND_AUTO_CREATE)
} catch (ignored: RuntimeException) {
// This is probably a broadcast receiver context even though we are calling getApplicationContext().
// Just call startForegroundService instead since we cannot bind a service to a
// broadcast receiver context. The service also have to call startForeground in
// this case.
context.startForegroundService(Intent(context, LocationService::class.java))
}
}
fun stopService(context: Context) =
context.stopService(Intent(context, LocationService::class.java))
}