fix AlarmSoundService crashing
This commit is contained in:
parent
3f77496c88
commit
7bc7388f06
4 changed files with 105 additions and 35 deletions
|
@ -22,7 +22,7 @@ import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
||||||
import info.nightscout.androidaps.services.AlarmSoundService
|
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.resources.IconsProvider
|
import info.nightscout.androidaps.utils.resources.IconsProvider
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
@ -39,6 +39,7 @@ class NotificationStore @Inject constructor(
|
||||||
private val resourceHelper: ResourceHelper,
|
private val resourceHelper: ResourceHelper,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val iconsProvider: IconsProvider,
|
private val iconsProvider: IconsProvider,
|
||||||
|
private val alarmSoundServiceHelper: AlarmSoundServiceHelper,
|
||||||
private val dateUtil: DateUtil
|
private val dateUtil: DateUtil
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -46,10 +47,12 @@ class NotificationStore @Inject constructor(
|
||||||
private var usesChannels = false
|
private var usesChannels = false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val CHANNEL_ID = "AndroidAPS-Overview"
|
private const val CHANNEL_ID = "AndroidAPS-Overview"
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class NotificationComparator : Comparator<Notification> {
|
inner class NotificationComparator : Comparator<Notification> {
|
||||||
|
|
||||||
override fun compare(o1: Notification, o2: Notification): Int {
|
override fun compare(o1: Notification, o2: Notification): Int {
|
||||||
return o1.level - o2.level
|
return o1.level - o2.level
|
||||||
}
|
}
|
||||||
|
@ -68,17 +71,9 @@ class NotificationStore @Inject constructor(
|
||||||
store.add(n)
|
store.add(n)
|
||||||
if (sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false) && n !is NotificationWithAction) {
|
if (sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, false) && n !is NotificationWithAction) {
|
||||||
raiseSystemNotification(n)
|
raiseSystemNotification(n)
|
||||||
if (usesChannels && n.soundId != null && n.soundId != 0) {
|
if (usesChannels && n.soundId != null && n.soundId != 0) alarmSoundServiceHelper.startAlarm(context, n.soundId)
|
||||||
val alarm = Intent(context, AlarmSoundService::class.java)
|
|
||||||
alarm.putExtra("soundid", n.soundId)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(alarm) else context.startService(alarm)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (n.soundId != null && n.soundId != 0) {
|
if (n.soundId != null && n.soundId != 0) alarmSoundServiceHelper.startAlarm(context, n.soundId)
|
||||||
val alarm = Intent(context, AlarmSoundService::class.java)
|
|
||||||
alarm.putExtra("soundid", n.soundId)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) context.startForegroundService(alarm) else context.startService(alarm)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Collections.sort(store, NotificationComparator())
|
Collections.sort(store, NotificationComparator())
|
||||||
return true
|
return true
|
||||||
|
@ -87,10 +82,7 @@ class NotificationStore @Inject constructor(
|
||||||
@Synchronized fun remove(id: Int): Boolean {
|
@Synchronized fun remove(id: Int): Boolean {
|
||||||
for (i in store.indices) {
|
for (i in store.indices) {
|
||||||
if (store[i].id == id) {
|
if (store[i].id == id) {
|
||||||
if (store[i].soundId != null) {
|
if (store[i].soundId != null) alarmSoundServiceHelper.stopService(context)
|
||||||
val alarm = Intent(context, AlarmSoundService::class.java)
|
|
||||||
context.stopService(alarm)
|
|
||||||
}
|
|
||||||
store.removeAt(i)
|
store.removeAt(i)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -208,6 +200,7 @@ class NotificationStore @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class NotificationsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class NotificationsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
var cv: CardView = itemView.findViewById(R.id.notification_cardview)
|
var cv: CardView = itemView.findViewById(R.id.notification_cardview)
|
||||||
var text: TextView = itemView.findViewById(R.id.notification_text)
|
var text: TextView = itemView.findViewById(R.id.notification_text)
|
||||||
var dismiss: Button = itemView.findViewById(R.id.notification_dismiss)
|
var dismiss: Button = itemView.findViewById(R.id.notification_dismiss)
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package info.nightscout.androidaps.dialogs
|
package info.nightscout.androidaps.dialogs
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -13,11 +10,13 @@ import dagger.android.support.DaggerDialogFragment
|
||||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.services.AlarmSoundService
|
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
||||||
import kotlinx.android.synthetic.main.dialog_error.*
|
import kotlinx.android.synthetic.main.dialog_error.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ErrorDialog : DaggerDialogFragment() {
|
class ErrorDialog : DaggerDialogFragment() {
|
||||||
|
|
||||||
|
@Inject lateinit var alarmSoundServiceHelper: AlarmSoundServiceHelper
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
|
|
||||||
var helperActivity: ErrorHelperActivity? = null
|
var helperActivity: ErrorHelperActivity? = null
|
||||||
|
@ -80,17 +79,10 @@ class ErrorDialog : DaggerDialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startAlarm() {
|
private fun startAlarm() {
|
||||||
if (sound != 0) {
|
if (sound != 0)
|
||||||
val alarm = Intent(context, AlarmSoundService::class.java)
|
context?.let { context -> alarmSoundServiceHelper.startAlarm(context, sound) }
|
||||||
alarm.putExtra("soundid", sound)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
context?.startForegroundService(alarm)
|
|
||||||
} else {
|
|
||||||
context?.startService(alarm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopAlarm() =
|
private fun stopAlarm() =
|
||||||
context?.stopService(Intent(context, AlarmSoundService::class.java))
|
context?.let { context -> alarmSoundServiceHelper.stopService(context) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
|
import android.os.Binder
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import dagger.android.DaggerService
|
import dagger.android.DaggerService
|
||||||
|
@ -43,11 +44,17 @@ class AlarmSoundService : DaggerService() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class LocalBinder : Binder() {
|
||||||
|
|
||||||
|
fun getService(): AlarmSoundService = this@AlarmSoundService
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binder = LocalBinder()
|
||||||
|
override fun onBind(intent: Intent): IBinder = binder
|
||||||
|
|
||||||
private val increaseVolumeHandler = Handler()
|
private val increaseVolumeHandler = Handler()
|
||||||
private var currentVolumeLevel = 0
|
private var currentVolumeLevel = 0
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? = null
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
aapsLogger.debug(LTag.CORE, "onCreate parent called")
|
aapsLogger.debug(LTag.CORE, "onCreate parent called")
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
package info.nightscout.androidaps.services
|
||||||
|
|
||||||
|
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 info.nightscout.androidaps.interfaces.NotificationHolderInterface
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
/*
|
||||||
|
This code replaces following
|
||||||
|
val alarm = Intent(context, AlarmSoundService::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.AlarmSoundService}
|
||||||
|
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
class AlarmSoundServiceHelper @Inject constructor(
|
||||||
|
private val notificationHolder: NotificationHolderInterface
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun startAlarm(context: Context, sound: Int) {
|
||||||
|
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: AlarmSoundService.LocalBinder = service as AlarmSoundService.LocalBinder
|
||||||
|
|
||||||
|
val alarmSoundService: AlarmSoundService = binder.getService()
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||||
|
context.startForegroundService(getServiceIntent(context, sound))
|
||||||
|
else
|
||||||
|
context.startService(getServiceIntent(context, sound))
|
||||||
|
|
||||||
|
// This is the key: Without waiting Android Framework to call this method
|
||||||
|
// inside Service.onCreate(), immediately call here to post the notification.
|
||||||
|
alarmSoundService.startForeground(notificationHolder.notificationID, notificationHolder.notification)
|
||||||
|
|
||||||
|
// Release the connection to prevent leaks.
|
||||||
|
context.unbindService(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(name: ComponentName?) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
context.bindService(getServiceIntent(context, sound), 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.
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||||
|
context.startForegroundService(getServiceIntent(context, sound))
|
||||||
|
else
|
||||||
|
context.startService(getServiceIntent(context, sound))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopService(context: Context) {
|
||||||
|
val alarm = Intent(context, AlarmSoundService::class.java)
|
||||||
|
context.stopService(alarm)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getServiceIntent(context: Context, sound: Int): Intent {
|
||||||
|
val alarm = Intent(context, AlarmSoundService::class.java)
|
||||||
|
alarm.putExtra("soundid", sound)
|
||||||
|
return alarm
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue