From 16bc3633da0734e27cb87c3ed9a1f874678565c4 Mon Sep 17 00:00:00 2001 From: Anthony La Date: Wed, 16 Oct 2024 19:38:45 -0700 Subject: [PATCH] feat: Added support for control with bluetooth pause/play buttons (#118) * Added support for control with bluetooth pause/play buttons * Added a settings item to disable MediaSession control (default:ON) * Added noisy receiver to catch audio sudden change --- .../mpvkt/preferences/PlayerPreferences.kt | 2 + .../mehiz/mpvkt/ui/player/PlayerActivity.kt | 60 +++++++++++++++++++ .../ui/preferences/PlayerPreferencesScreen.kt | 6 ++ app/src/main/res/values/strings.xml | 1 + 4 files changed, 69 insertions(+) diff --git a/app/src/main/java/live/mehiz/mpvkt/preferences/PlayerPreferences.kt b/app/src/main/java/live/mehiz/mpvkt/preferences/PlayerPreferences.kt index f66d65e..1a73557 100644 --- a/app/src/main/java/live/mehiz/mpvkt/preferences/PlayerPreferences.kt +++ b/app/src/main/java/live/mehiz/mpvkt/preferences/PlayerPreferences.kt @@ -45,4 +45,6 @@ class PlayerPreferences( val allowGesturesInPanels = preferenceStore.getBoolean("allow_gestures_in_panels") val showSystemStatusBar = preferenceStore.getBoolean("show_system_status_bar") + + val allowHeadsetControl = preferenceStore.getBoolean("allow_headset_control", true) } diff --git a/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt b/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt index 4061a11..502080c 100644 --- a/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt +++ b/app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt @@ -10,6 +10,8 @@ import android.content.pm.ActivityInfo import android.content.pm.PackageManager import android.content.res.Configuration import android.media.AudioManager +import android.media.session.MediaSession +import android.media.session.PlaybackState import android.net.Uri import android.os.Build import android.os.Bundle @@ -68,6 +70,7 @@ class PlayerActivity : AppCompatActivity() { val player by lazy { binding.player } val windowInsetsController by lazy { WindowCompat.getInsetsController(window, window.decorView) } val audioManager by lazy { getSystemService(Context.AUDIO_SERVICE) as AudioManager } + private var mediaSession: MediaSession? = null private val playerPreferences: PlayerPreferences by inject() private val audioPreferences: AudioPreferences by inject() private val subtitlesPreferences: SubtitlesPreferences by inject() @@ -89,6 +92,16 @@ class PlayerActivity : AppCompatActivity() { } private var pipReceiver: BroadcastReceiver? = null + private val noisyReceiver = object : BroadcastReceiver() { + var initialized = false + override fun onReceive(context: Context?, intent: Intent?) { + if (intent?.action == AudioManager.ACTION_AUDIO_BECOMING_NOISY) { + viewModel.pause() + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + } + } + override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) @@ -96,6 +109,7 @@ class PlayerActivity : AppCompatActivity() { setupMPV() setupAudio() + setupMediaSession() getPlayableUri(intent)?.let { player.playFile(it) } setIntentExtras(intent.extras) setOrientation() @@ -123,6 +137,11 @@ class PlayerActivity : AppCompatActivity() { AudioManagerCompat.abandonAudioFocusRequest(audioManager, it) } audioFocusRequest = null + mediaSession?.release() + if (noisyReceiver.initialized) { + unregisterReceiver(noisyReceiver) + noisyReceiver.initialized = false + } unloadKoinModules(viewModelModule) MPVLib.removeObserver(playerObserver) @@ -663,6 +682,47 @@ class PlayerActivity : AppCompatActivity() { if (player.onKey(event!!)) return true return super.onKeyUp(keyCode, event) } + + private fun setupMediaSession() { + val allowHeadsetControl = playerPreferences.allowHeadsetControl.get() + if (allowHeadsetControl) { + mediaSession = MediaSession(this, "PlayerActivity").apply { + setCallback(object : MediaSession.Callback() { + override fun onPlay() { + super.onPlay() + viewModel.unpause() + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + + override fun onPause() { + super.onPause() + viewModel.pause() + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + + override fun onStop() { + super.onStop() + isActive = false + this@PlayerActivity.onStop() + } + }) + setPlaybackState( + PlaybackState.Builder() + .setActions( + PlaybackState.ACTION_PLAY or + PlaybackState.ACTION_PAUSE or + PlaybackState.ACTION_STOP + ) + .build() + ) + isActive = true + } + + val filter = IntentFilter().apply { addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY) } + registerReceiver(noisyReceiver, filter) + noisyReceiver.initialized = true + } + } } const val TAG = "mpvKt" diff --git a/app/src/main/java/live/mehiz/mpvkt/ui/preferences/PlayerPreferencesScreen.kt b/app/src/main/java/live/mehiz/mpvkt/ui/preferences/PlayerPreferencesScreen.kt index 6e9ae69..eba76e8 100644 --- a/app/src/main/java/live/mehiz/mpvkt/ui/preferences/PlayerPreferencesScreen.kt +++ b/app/src/main/java/live/mehiz/mpvkt/ui/preferences/PlayerPreferencesScreen.kt @@ -212,6 +212,12 @@ object PlayerPreferencesScreen : Screen() { onValueChange = preferences.showSystemStatusBar::set, title = { Text(stringResource(R.string.pref_player_controls_show_status_bar)) }, ) + val allowHeadsetControl by preferences.allowHeadsetControl.collectAsState() + SwitchPreference( + value = allowHeadsetControl, + onValueChange = preferences.allowHeadsetControl::set, + title = { Text(stringResource(R.string.control_player_with_media_buttons)) }, + ) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b14348b..4dca3af 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -208,6 +208,7 @@ %.2f\%% https://github.com/abdallahmehiz/mpvKt + Control player with media buttons Swap volume and brightness slider