mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
fix: Call startForeground() before Hilt DI to prevent timing crash
Move startForeground() before super.onCreate() in MonitorService to avoid ForegroundServiceDidNotStartInTimeException when Hilt DI is slow on backgrounded cold starts. An early minimal notification is shown immediately, then replaced with the full one after DI completes.
This commit is contained in:
@@ -73,9 +73,26 @@ class MonitorService : Service() {
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
override fun onCreate() {
|
||||
// Promote to foreground BEFORE Hilt DI (triggered by super.onCreate()) to avoid
|
||||
// ForegroundServiceDidNotStartInTimeException when DI is slow on backgrounded cold starts.
|
||||
MonitorNotifications.ensureChannel(this)
|
||||
val earlyNotification = MonitorNotifications.createEarlyNotification(this)
|
||||
if (hasApiLevel(29)) {
|
||||
startForeground(
|
||||
MonitorNotifications.NOTIFICATION_ID,
|
||||
earlyNotification,
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE,
|
||||
)
|
||||
} else {
|
||||
startForeground(MonitorNotifications.NOTIFICATION_ID, earlyNotification)
|
||||
}
|
||||
|
||||
super.onCreate()
|
||||
log(TAG, VERBOSE) { "onCreate()" }
|
||||
|
||||
// Replace early notification with the full one from injected MonitorNotifications.
|
||||
// Second startForeground() with the same ID updates the notification in place and is
|
||||
// preferred over notify() for robust foreground state on OEM variants.
|
||||
val notification = notifications.getStartupNotification()
|
||||
if (hasApiLevel(29)) {
|
||||
startForeground(
|
||||
|
||||
@@ -37,11 +37,7 @@ class MonitorNotifications @Inject constructor(
|
||||
private val builder: NotificationCompat.Builder
|
||||
|
||||
init {
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANNEL_ID,
|
||||
context.getString(R.string.notification_channel_device_status_label),
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
).run { notificationManager.createNotificationChannel(this) }
|
||||
ensureChannel(context)
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANNEL_ID_CONNECTED,
|
||||
context.getString(R.string.notification_channel_device_status_connected_label),
|
||||
@@ -51,7 +47,7 @@ class MonitorNotifications @Inject constructor(
|
||||
val openIntent = Intent(context, MainActivity::class.java)
|
||||
val openPi = PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
PENDING_INTENT_REQUEST_CODE,
|
||||
openIntent,
|
||||
PendingIntentCompat.FLAG_IMMUTABLE
|
||||
)
|
||||
@@ -164,10 +160,37 @@ class MonitorNotifications @Inject constructor(
|
||||
|
||||
companion object {
|
||||
val TAG = logTag("Monitor", "Notifications")
|
||||
private val NOTIFICATION_CHANNEL_ID = "${BuildConfigWrap.APPLICATION_ID}.notification.channel.device.status"
|
||||
internal val NOTIFICATION_CHANNEL_ID = "${BuildConfigWrap.APPLICATION_ID}.notification.channel.device.status"
|
||||
private val NOTIFICATION_CHANNEL_ID_CONNECTED =
|
||||
"${BuildConfigWrap.APPLICATION_ID}.notification.channel.device.status.connected"
|
||||
internal const val NOTIFICATION_ID = 1
|
||||
internal const val NOTIFICATION_ID_CONNECTED = 2
|
||||
private const val PENDING_INTENT_REQUEST_CODE = 0
|
||||
|
||||
fun ensureChannel(context: Context) {
|
||||
val nm = context.getSystemService(NotificationManager::class.java)
|
||||
nm.createNotificationChannel(
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANNEL_ID,
|
||||
context.getString(R.string.notification_channel_device_status_label),
|
||||
NotificationManager.IMPORTANCE_LOW,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createEarlyNotification(context: Context): Notification {
|
||||
val openPi = PendingIntent.getActivity(
|
||||
context, PENDING_INTENT_REQUEST_CODE,
|
||||
Intent(context, MainActivity::class.java),
|
||||
PendingIntentCompat.FLAG_IMMUTABLE,
|
||||
)
|
||||
return NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
|
||||
.setContentIntent(openPi)
|
||||
.setSmallIcon(R.drawable.devic_earbuds_generic_both)
|
||||
.setContentTitle(context.getString(R.string.app_name))
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setOngoing(true)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user