Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
android:name=".MainApplication"
Expand Down Expand Up @@ -30,6 +31,14 @@
</intent-filter>
</service>

<receiver
android:name=".service.BootReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package be.digitalia.mediasession2mqtt.service

import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.service.notification.NotificationListenerService

/**
* Works around a well-known Android bug where the [NotificationListenerService] is not
* automatically re-bound after a device reboot. When this happens the app silently stops
* receiving media session updates until the notification access permission is manually
* toggled off and on again (a frequent problem on Android TV).
*
* On boot we force the system to rebind the listener:
* 1. Disabling then re-enabling the service component. This is the programmatic equivalent
* of the manual permission toggle and reliably triggers a rebind, including on the
* devices where the official API alone is not enough. It does not affect the granted
* notification-access permission (that grant is stored separately, by component name).
* 2. [NotificationListenerService.requestRebind] — the official API (API 24+) as a final nudge.
*/
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action != Intent.ACTION_BOOT_COMPLETED) return

val component = ComponentName(context, MediaSessionListenerService::class.java)

// (1) Forceful rebind: toggle the component off and back on.
runCatching {
val pm = context.packageManager
pm.setComponentEnabledSetting(
component,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}

// (2) Ask the system to rebind the listener (available since API 24).
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
runCatching {
NotificationListenerService.requestRebind(component)
}
}
}
}