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..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 @@ -10,6 +10,7 @@ import android.media.session.MediaSessionManager import android.media.session.PlaybackState import android.os.Handler import android.os.PowerManager +import android.os.UserHandle import android.view.Display import android.view.KeyEvent import ru.hepolise.volumekeytrackcontrol.util.AppFilterType @@ -17,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 @@ -46,22 +51,62 @@ 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_ALL) + @Suppress("UNCHECKED_CAST") + return controllers as List + } catch (_: Exception) { + } - method.isAccessible = true + 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) { + } + } + + return try { + mediaSessionManager.getActiveSessions(null) + } catch (_: Exception) { + 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_ALL) }, + { clazz.getMethod("of", Int::class.javaPrimitiveType).invoke(null, USER_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 +168,4 @@ class MediaSessionManager(private val context: Context) { audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, direction, 0) } } -} \ No newline at end of file +}