DummyServiceHelper
This commit is contained in:
parent
8a683ee571
commit
68faba8951
4 changed files with 106 additions and 28 deletions
|
@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.persistentNotification
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Binder
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import dagger.android.DaggerService
|
import dagger.android.DaggerService
|
||||||
import info.nightscout.androidaps.events.EventAppExit
|
import info.nightscout.androidaps.events.EventAppExit
|
||||||
|
@ -27,7 +28,13 @@ class DummyService : DaggerService() {
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? = null
|
inner class LocalBinder : Binder() {
|
||||||
|
|
||||||
|
fun getService(): DummyService = this@DummyService
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binder = LocalBinder()
|
||||||
|
override fun onBind(intent: Intent): IBinder = binder
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
@ -44,7 +51,7 @@ class DummyService : DaggerService() {
|
||||||
.subscribe({
|
.subscribe({
|
||||||
aapsLogger.debug(LTag.CORE, "EventAppExit received")
|
aapsLogger.debug(LTag.CORE, "EventAppExit received")
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}, fabricPrivacy::logException )
|
}, fabricPrivacy::logException)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.persistentNotification
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.IBinder
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import info.nightscout.androidaps.interfaces.NotificationHolderInterface
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
/*
|
||||||
|
This code replaces following
|
||||||
|
val alarm = Intent(context, DummyService::class.java)
|
||||||
|
alarm.putExtra("soundid", n.soundId)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(alarm) else context.startService(alarm)
|
||||||
|
|
||||||
|
it fails randomly with error
|
||||||
|
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{e317f7e u0 info.nightscout.nsclient/info.nightscout.androidaps.services.DummyService}
|
||||||
|
|
||||||
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
@Singleton
|
||||||
|
class DummyServiceHelper @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: DummyService.LocalBinder = service as DummyService.LocalBinder
|
||||||
|
|
||||||
|
val dummyService: DummyService = binder.getService()
|
||||||
|
|
||||||
|
context.startForegroundService(Intent(context, DummyService::class.java))
|
||||||
|
|
||||||
|
// This is the key: Without waiting Android Framework to call this method
|
||||||
|
// inside Service.onCreate(), immediately call here to post the notification.
|
||||||
|
dummyService.startForeground(notificationHolder.notificationID, notificationHolder.notification)
|
||||||
|
|
||||||
|
// Release the connection to prevent leaks.
|
||||||
|
context.unbindService(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(name: ComponentName?) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
context.bindService(Intent(context, DummyService::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, DummyService::class.java))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopService(context: Context) {
|
||||||
|
context.stopService(Intent(context, DummyService::class.java))
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,18 +30,20 @@ import io.reactivex.schedulers.Schedulers
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Suppress("PrivatePropertyName")
|
||||||
@Singleton
|
@Singleton
|
||||||
class PersistentNotificationPlugin @Inject constructor(
|
class PersistentNotificationPlugin @Inject constructor(
|
||||||
injector: HasAndroidInjector,
|
injector: HasAndroidInjector,
|
||||||
aapsLogger: AAPSLogger,
|
aapsLogger: AAPSLogger,
|
||||||
resourceHelper: ResourceHelper,
|
resourceHelper: ResourceHelper,
|
||||||
private var profileFunction: ProfileFunction,
|
private val profileFunction: ProfileFunction,
|
||||||
private var fabricPrivacy: FabricPrivacy,
|
private val fabricPrivacy: FabricPrivacy,
|
||||||
private var activePlugins: ActivePluginProvider,
|
private val activePlugins: ActivePluginProvider,
|
||||||
private var iobCobCalculatorPlugin: IobCobCalculatorPlugin,
|
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin,
|
||||||
private var rxBus: RxBusWrapper,
|
private val rxBus: RxBusWrapper,
|
||||||
private var context: Context,
|
private val context: Context,
|
||||||
private var notificationHolder: NotificationHolder,
|
private val notificationHolder: NotificationHolder,
|
||||||
|
private val dummyServiceHelper: DummyServiceHelper,
|
||||||
private val iconsProvider: IconsProvider,
|
private val iconsProvider: IconsProvider,
|
||||||
private val databaseHelper: DatabaseHelperInterface
|
private val databaseHelper: DatabaseHelperInterface
|
||||||
) : PluginBase(PluginDescription()
|
) : PluginBase(PluginDescription()
|
||||||
|
@ -112,13 +114,13 @@ class PersistentNotificationPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
context.stopService(Intent(context, DummyService::class.java))
|
dummyServiceHelper.stopService(context)
|
||||||
super.onStop()
|
super.onStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun triggerNotificationUpdate() {
|
private fun triggerNotificationUpdate() {
|
||||||
updateNotification()
|
updateNotification()
|
||||||
context.startForegroundService(Intent(context, DummyService::class.java))
|
dummyServiceHelper.startService(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateNotification() {
|
private fun updateNotification() {
|
||||||
|
@ -128,31 +130,31 @@ class PersistentNotificationPlugin @Inject constructor(
|
||||||
var line3: String? = null
|
var line3: String? = null
|
||||||
var unreadConversationBuilder: NotificationCompat.CarExtender.UnreadConversation.Builder? = null
|
var unreadConversationBuilder: NotificationCompat.CarExtender.UnreadConversation.Builder? = null
|
||||||
if (profileFunction.isProfileValid("Notification")) {
|
if (profileFunction.isProfileValid("Notification")) {
|
||||||
var line1_aa: String
|
var line1aa: String
|
||||||
val units = profileFunction.getUnits()
|
val units = profileFunction.getUnits()
|
||||||
val lastBG = iobCobCalculatorPlugin.lastBg()
|
val lastBG = iobCobCalculatorPlugin.lastBg()
|
||||||
val glucoseStatus = GlucoseStatus(injector).glucoseStatusData
|
val glucoseStatus = GlucoseStatus(injector).glucoseStatusData
|
||||||
if (lastBG != null) {
|
if (lastBG != null) {
|
||||||
line1_aa = lastBG.valueToUnitsToString(units)
|
line1aa = lastBG.valueToUnitsToString(units)
|
||||||
line1 = line1_aa
|
line1 = line1aa
|
||||||
if (glucoseStatus != null) {
|
if (glucoseStatus != null) {
|
||||||
line1 += (" Δ" + Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
line1 += (" Δ" + Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
||||||
+ " avgΔ" + Profile.toSignedUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units))
|
+ " avgΔ" + Profile.toSignedUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units))
|
||||||
line1_aa += " " + lastBG.directionToSymbol(databaseHelper)
|
line1aa += " " + lastBG.directionToSymbol(databaseHelper)
|
||||||
} else {
|
} else {
|
||||||
line1 += " " +
|
line1 += " " +
|
||||||
resourceHelper.gs(R.string.old_data) +
|
resourceHelper.gs(R.string.old_data) +
|
||||||
" "
|
" "
|
||||||
line1_aa += "$line1."
|
line1aa += "$line1."
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
line1_aa = resourceHelper.gs(R.string.missed_bg_readings)
|
line1aa = resourceHelper.gs(R.string.missed_bg_readings)
|
||||||
line1 = line1_aa
|
line1 = line1aa
|
||||||
}
|
}
|
||||||
val activeTemp = activePlugins.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis())
|
val activeTemp = activePlugins.activeTreatments.getTempBasalFromHistory(System.currentTimeMillis())
|
||||||
if (activeTemp != null) {
|
if (activeTemp != null) {
|
||||||
line1 += " " + activeTemp.toStringShort()
|
line1 += " " + activeTemp.toStringShort()
|
||||||
line1_aa += " " + activeTemp.toStringShort() + "."
|
line1aa += " " + activeTemp.toStringShort() + "."
|
||||||
}
|
}
|
||||||
//IOB
|
//IOB
|
||||||
activePlugins.activeTreatments.updateTotalIOBTreatments()
|
activePlugins.activeTreatments.updateTotalIOBTreatments()
|
||||||
|
@ -160,11 +162,11 @@ class PersistentNotificationPlugin @Inject constructor(
|
||||||
val bolusIob = activePlugins.activeTreatments.lastCalculationTreatments.round()
|
val bolusIob = activePlugins.activeTreatments.lastCalculationTreatments.round()
|
||||||
val basalIob = activePlugins.activeTreatments.lastCalculationTempBasals.round()
|
val basalIob = activePlugins.activeTreatments.lastCalculationTempBasals.round()
|
||||||
line2 = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString()
|
line2 = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString()
|
||||||
val line2_aa = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + "."
|
val line2aa = resourceHelper.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + resourceHelper.gs(R.string.cob) + ": " + iobCobCalculatorPlugin.getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + "."
|
||||||
line3 = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h"
|
line3 = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h"
|
||||||
var line3_aa = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h."
|
var line3aa = DecimalFormatter.to2Decimal(pump.baseBasalRate) + " U/h."
|
||||||
line3 += " - " + profileFunction.getProfileName()
|
line3 += " - " + profileFunction.getProfileName()
|
||||||
line3_aa += " - " + profileFunction.getProfileName() + "."
|
line3aa += " - " + profileFunction.getProfileName() + "."
|
||||||
/// For Android Auto
|
/// For Android Auto
|
||||||
val msgReadIntent = Intent()
|
val msgReadIntent = Intent()
|
||||||
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
|
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
|
||||||
|
@ -188,12 +190,12 @@ class PersistentNotificationPlugin @Inject constructor(
|
||||||
// Build a RemoteInput for receiving voice input from devices
|
// Build a RemoteInput for receiving voice input from devices
|
||||||
val remoteInput = RemoteInput.Builder(EXTRA_VOICE_REPLY).build()
|
val remoteInput = RemoteInput.Builder(EXTRA_VOICE_REPLY).build()
|
||||||
// Create the UnreadConversation
|
// Create the UnreadConversation
|
||||||
unreadConversationBuilder = NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa)
|
unreadConversationBuilder = NotificationCompat.CarExtender.UnreadConversation.Builder(line1aa + "\n" + line2aa)
|
||||||
.setLatestTimestamp(System.currentTimeMillis())
|
.setLatestTimestamp(System.currentTimeMillis())
|
||||||
.setReadPendingIntent(msgReadPendingIntent)
|
.setReadPendingIntent(msgReadPendingIntent)
|
||||||
.setReplyAction(msgReplyPendingIntent, remoteInput)
|
.setReplyAction(msgReplyPendingIntent, remoteInput)
|
||||||
/// Add dot to produce a "more natural sounding result"
|
/// Add dot to produce a "more natural sounding result"
|
||||||
unreadConversationBuilder.addMessage(line3_aa)
|
unreadConversationBuilder.addMessage(line3aa)
|
||||||
/// End Android Auto
|
/// End Android Auto
|
||||||
} else {
|
} else {
|
||||||
line1 = resourceHelper.gs(R.string.noprofileset)
|
line1 = resourceHelper.gs(R.string.noprofileset)
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
package info.nightscout.androidaps.receivers
|
package info.nightscout.androidaps.receivers
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService
|
import dagger.android.DaggerBroadcastReceiver
|
||||||
|
import info.nightscout.androidaps.plugins.general.persistentNotification.DummyServiceHelper
|
||||||
|
|
||||||
class AutoStartReceiver : BroadcastReceiver() {
|
class AutoStartReceiver constructor(
|
||||||
|
private val dummyServiceHelper: DummyServiceHelper
|
||||||
|
) : DaggerBroadcastReceiver() {
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
super.onReceive(context, intent)
|
||||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED)
|
if (intent.action == Intent.ACTION_BOOT_COMPLETED)
|
||||||
context.startForegroundService(Intent(context, DummyService::class.java))
|
dummyServiceHelper.startService(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue