@@ -9,6 +9,7 @@ import android.media.MediaPlayer
99import android.media.session.MediaController
1010import android.media.session.MediaSessionManager
1111import android.media.session.PlaybackState
12+ import android.view.KeyEvent
1213import androidx.core.content.getSystemService
1314import androidx.core.net.toUri
1415import dagger.hilt.android.qualifiers.ApplicationContext
@@ -87,7 +88,7 @@ class AndroidMediaAdapter @Inject constructor(
8788 session.transportControls.fastForward()
8889 return Success (Unit )
8990 } else {
90- return KMError . MediaActionUnsupported
91+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_FAST_FORWARD , packageName)
9192 }
9293 }
9394
@@ -98,7 +99,7 @@ class AndroidMediaAdapter @Inject constructor(
9899 session.transportControls.rewind()
99100 return Success (Unit )
100101 } else {
101- return KMError . MediaActionUnsupported
102+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_REWIND , packageName)
102103 }
103104 }
104105
@@ -109,7 +110,7 @@ class AndroidMediaAdapter @Inject constructor(
109110 session.transportControls.play()
110111 return Success (Unit )
111112 } else {
112- return KMError . MediaActionUnsupported
113+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_PLAY , packageName)
113114 }
114115 }
115116
@@ -120,7 +121,7 @@ class AndroidMediaAdapter @Inject constructor(
120121 session.transportControls.pause()
121122 return Success (Unit )
122123 } else {
123- return KMError . MediaActionUnsupported
124+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_PAUSE , packageName)
124125 }
125126 }
126127
@@ -135,7 +136,7 @@ class AndroidMediaAdapter @Inject constructor(
135136 }
136137 return Success (Unit )
137138 } else {
138- return KMError . MediaActionUnsupported
139+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_PLAY_PAUSE , packageName)
139140 }
140141 }
141142
@@ -146,7 +147,7 @@ class AndroidMediaAdapter @Inject constructor(
146147 session.transportControls.skipToPrevious()
147148 return Success (Unit )
148149 } else {
149- return KMError . MediaActionUnsupported
150+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_PREVIOUS , packageName)
150151 }
151152 }
152153
@@ -157,7 +158,7 @@ class AndroidMediaAdapter @Inject constructor(
157158 session.transportControls.skipToNext()
158159 return Success (Unit )
159160 } else {
160- return KMError . MediaActionUnsupported
161+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_NEXT , packageName)
161162 }
162163 }
163164
@@ -168,7 +169,7 @@ class AndroidMediaAdapter @Inject constructor(
168169 session.transportControls.stop()
169170 return Success (Unit )
170171 } else {
171- return KMError . MediaActionUnsupported
172+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_STOP , packageName)
172173 }
173174 }
174175
@@ -180,7 +181,7 @@ class AndroidMediaAdapter @Inject constructor(
180181 session.transportControls.seekTo(position + SEEK_AMOUNT )
181182 return Success (Unit )
182183 } else {
183- return KMError . MediaActionUnsupported
184+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_STEP_FORWARD , packageName)
184185 }
185186 }
186187
@@ -192,7 +193,7 @@ class AndroidMediaAdapter @Inject constructor(
192193 session.transportControls.seekTo(max(0 , position - SEEK_AMOUNT ))
193194 return Success (Unit )
194195 } else {
195- return KMError . MediaActionUnsupported
196+ return sendMediaKeyEvent( KeyEvent . KEYCODE_MEDIA_STEP_BACKWARD , packageName)
196197 }
197198 }
198199
@@ -277,6 +278,21 @@ class AndroidMediaAdapter @Inject constructor(
277278 activeMediaSessions.update { mediaSessions }
278279 }
279280
281+ // Important! See issue #1971. Some apps do not expose media controls or say they support
282+ // media control actions but they still respond to key events.
283+ private fun sendMediaKeyEvent (keyCode : Int , packageName : String? ): KMResult <* > {
284+ if (packageName == null ) {
285+ audioManager.dispatchMediaKeyEvent(KeyEvent (KeyEvent .ACTION_DOWN , keyCode))
286+ audioManager.dispatchMediaKeyEvent(KeyEvent (KeyEvent .ACTION_UP , keyCode))
287+ } else {
288+ val session = getPackageMediaSession(packageName) ? : return KMError .NoMediaSessions
289+ session.dispatchMediaButtonEvent(KeyEvent (KeyEvent .ACTION_DOWN , keyCode))
290+ session.dispatchMediaButtonEvent(KeyEvent (KeyEvent .ACTION_UP , keyCode))
291+ }
292+
293+ return Success (Unit )
294+ }
295+
280296 private fun MediaController.isPlaybackActionSupported (action : Long ): Boolean =
281297 (playbackState?.actions ? : 0 ) and action != 0L
282298
0 commit comments