I want to implement mediaKeyEvents in my Exoplayer for usage on TVs.
For now I have a working setup:
override fun onCreate(savedInstanceState: Bundle?) {
...
//Don't show controller on start
viewBinding.playerView.controllerAutoShow = false
...
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_MEDIA_PLAY -> {
if (viewBinding.playerView.player!!.isPlaying) {
viewBinding.playerView.player!!.pause()
} else {
viewBinding.playerView.player!!.play()
}
return true
}
KeyEvent.KEYCODE_DPAD_RIGHT -> {
viewBinding.playerView.player!!.seekForward()
return true
}
KeyEvent.KEYCODE_DPAD_LEFT -> {
viewBinding.playerView.player!!.seekBack()
return true
}
}
return super.onKeyDown(keyCode, event)
}
The TV controlls that matter the most to me are those for the Nvidia Shield Pro Controller.
The issue: in this setup, the controller shows whenever I play/pause. I have tried to disable the controller, and then the seek back/forward works, however, the play/pause stops working (additionally, I would like to keep the controller, just hidden).
Desired behaviour:
Something like plex or youtube, where these actions occur:
Actions that don't show the controller:
Actions that show the controller:
My ExoPlayer layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
<com.google.android.exoplayer2.ui.StyledPlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
app:show_shuffle_button="false"
app:show_subtitle_button="true" />
<LinearLayout
android:id="@+id/controls_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone">
<Button
android:id="@+id/select_tracks_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="TEST" />
</LinearLayout>
</FrameLayout>
I found the solution, I shouldn't use the onKeyDown, but rather the :
@SuppressLint("RestrictedApi")
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
if (event?.action == KeyEvent.ACTION_DOWN) {
when (event?.keyCode) {
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
if (viewBinding.playerView.player!!.isPlaying) {
viewBinding.playerView.player!!.pause()
} else {
viewBinding.playerView.player!!.play()
}
return true
}
KeyEvent.KEYCODE_DPAD_RIGHT -> {
viewBinding.playerView.player!!.seekForward()
return true
}
KeyEvent.KEYCODE_DPAD_LEFT -> {
viewBinding.playerView.player!!.seekBack()
return true
}
}
}
return false
}
Small note if you copy paste: This will remove all of the other keybinds as well, because I would love to program the back button as well to close the controller if open and else go back.