From 0d08a2df779d847938bd589a72db849efd2aa982 Mon Sep 17 00:00:00 2001 From: Andy-Dunne <69418566+Andy-Dunne@users.noreply.github.com> Date: Sun, 13 Sep 2026 21:40:36 +0800 Subject: [PATCH 1/2] Refactor MediaSessionManager to access active controllers --- .../module/util/MediaSessionManager.kt | 77 +++++++++++++++---- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt index 92a25ab..4743001 100644 --- a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt @@ -10,6 +10,8 @@ import android.media.session.MediaSessionManager import android.media.session.PlaybackState import android.os.Handler import android.os.PowerManager +import android.os.UserHandle +import android.util.Log import android.view.Display import android.view.KeyEvent import ru.hepolise.volumekeytrackcontrol.util.AppFilterType @@ -46,22 +48,63 @@ class MediaSessionManager(private val context: Context) { ?: throw NullPointerException("Unable to get MediaSessionLegacyHelper") } - @SuppressLint("BlockedPrivateApi") fun refreshControllers() { - val method = MediaSessionManager::class.java.getDeclaredMethod( - "getActiveSessionsForUser", - ComponentName::class.java, - Int::class.javaPrimitiveType - ) + mediaControllers = getActiveControllers() + } + + @SuppressLint("BlockedPrivateApi") + private fun getActiveControllers(): List? { + try { + val legacy = MediaSessionManager::class.java.getDeclaredMethod( + "getActiveSessionsForUser", + ComponentName::class.java, + Int::class.javaPrimitiveType + ) + legacy.isAccessible = true + val controllers = legacy.invoke(mediaSessionManager, null, USER_ID_ALL) + @Suppress("UNCHECKED_CAST") + return controllers as List + } catch (_: Exception) { + } + + getUserHandleAll()?.let { userHandle -> + try { + val perUser = MediaSessionManager::class.java.getDeclaredMethod( + "getActiveSessionsForUser", + ComponentName::class.java, + UserHandle::class.java + ) + perUser.isAccessible = true + val controllers = perUser.invoke(mediaSessionManager, null, userHandle) + @Suppress("UNCHECKED_CAST") + return controllers as List + } catch (_: Exception) { + } + } - method.isAccessible = true + return try { + mediaSessionManager.getActiveSessions(null) + } catch (e: Exception) { + Log.e(TAG, "Failed to get active media sessions", e) + null + } + } - @Suppress("UNCHECKED_CAST") - mediaControllers = method.invoke( - mediaSessionManager, - null, // ComponentName - -1 // android.os.UserHandle.ALL - ) as List + @SuppressLint("BlockedPrivateApi") + private fun getUserHandleAll(): UserHandle? { + val clazz = UserHandle::class.java + val candidates: List<() -> Any?> = listOf( + { clazz.getField("ALL").get(null) }, + { clazz.getConstructor(Int::class.javaPrimitiveType).newInstance(USER_ID_ALL) }, + { clazz.getMethod("of", Int::class.javaPrimitiveType).invoke(null, USER_ID_ALL) } + ) + for (candidate in candidates) { + try { + (candidate() as? UserHandle)?.let { return it } + } catch (_: Exception) { + } + } + return null } fun getActiveMediaController(prefs: android.content.SharedPreferences): MediaController? { @@ -123,4 +166,10 @@ class MediaSessionManager(private val context: Context) { audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, direction, 0) } } -} \ No newline at end of file + + companion object { + private const val TAG = "VolumeControl" + + private const val USER_ID_ALL = -1 + } +} From 1f23324a4926b4d251603c01cb2ac7f56997dd4d Mon Sep 17 00:00:00 2001 From: Andy-Dunne <69418566+Andy-Dunne@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:21:55 +0800 Subject: [PATCH 2/2] Update MediaSessionManager.kt --- .../module/util/MediaSessionManager.kt | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt index 4743001..84bbf7d 100644 --- a/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt +++ b/app/src/main/java/ru/hepolise/volumekeytrackcontrol/module/util/MediaSessionManager.kt @@ -11,7 +11,6 @@ import android.media.session.PlaybackState import android.os.Handler import android.os.PowerManager import android.os.UserHandle -import android.util.Log import android.view.Display import android.view.KeyEvent import ru.hepolise.volumekeytrackcontrol.util.AppFilterType @@ -19,6 +18,10 @@ import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getAppFilter import ru.hepolise.volumekeytrackcontrol.util.SharedPreferencesUtil.getApps class MediaSessionManager(private val context: Context) { + companion object { + private const val USER_ALL = -1 + } + lateinit var audioManager: AudioManager private set private lateinit var powerManager: PowerManager @@ -61,7 +64,7 @@ class MediaSessionManager(private val context: Context) { Int::class.javaPrimitiveType ) legacy.isAccessible = true - val controllers = legacy.invoke(mediaSessionManager, null, USER_ID_ALL) + val controllers = legacy.invoke(mediaSessionManager, null, USER_ALL) @Suppress("UNCHECKED_CAST") return controllers as List } catch (_: Exception) { @@ -84,8 +87,7 @@ class MediaSessionManager(private val context: Context) { return try { mediaSessionManager.getActiveSessions(null) - } catch (e: Exception) { - Log.e(TAG, "Failed to get active media sessions", e) + } catch (_: Exception) { null } } @@ -95,8 +97,8 @@ class MediaSessionManager(private val context: Context) { val clazz = UserHandle::class.java val candidates: List<() -> Any?> = listOf( { clazz.getField("ALL").get(null) }, - { clazz.getConstructor(Int::class.javaPrimitiveType).newInstance(USER_ID_ALL) }, - { clazz.getMethod("of", Int::class.javaPrimitiveType).invoke(null, USER_ID_ALL) } + { clazz.getConstructor(Int::class.javaPrimitiveType).newInstance(USER_ALL) }, + { clazz.getMethod("of", Int::class.javaPrimitiveType).invoke(null, USER_ALL) } ) for (candidate in candidates) { try { @@ -166,10 +168,4 @@ class MediaSessionManager(private val context: Context) { audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, direction, 0) } } - - companion object { - private const val TAG = "VolumeControl" - - private const val USER_ID_ALL = -1 - } }