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