funkwhale-android/app/src/main/java/audio/funkwhale/ffa/playback/MediaSession.kt

97 wiersze
3.0 KiB
Kotlin
Czysty Zwykły widok Historia

package audio.funkwhale.ffa.playback
import android.content.Context
import android.content.Intent
Fix Bluetooth control button unresponsiveness. With Oreo and later, Bluetooth control buttons may kill FFA if it is not the foreground application. Once this happens to resume playback, one needs to restart playback from the phone, rather than the play/pause action of Bluetooth headset. For example: D MediaSessionService: Sending KeyEvent { action=ACTION_UP, keyCode=KEYCODE_MEDIA_PLAY, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=0, downTime=0, deviceId=-1, source=0x0 } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.dev ( W ActivityManager: Background start not allowed: service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.play 549 uid=10149 pkg=audio.funkwhale.ffa.dev startFg?=false D AndroidRuntime: Shutting down VM --------- beginning of crash E AndroidRuntime: FATAL EXCEPTION: main E AndroidRuntime: Process: audio.funkwhale.ffa.dev, PID: 14549 E AndroidRuntime: java.lang.IllegalStateException: Not allowed to start service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) }: app is in background uid UidRecord{72fa8f8 u0a149 CAC bg:+11m56s597ms idle change:cached procs:1 seq(0,0,0)} E AndroidRuntime: at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577) E AndroidRuntime: at android.app.ContextImpl.startService(ContextImpl.java:1532) E AndroidRuntime: at android.content.ContextWrapper.startService(ContextWrapper.java:664) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.invoke$lambda-3$lambda-2(MediaSession.kt:47) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.$r8$lambda$jU84j_zRyeYuvwLrRY0b6XyQBMs(Unknown Source:0) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2$$ExternalSyntheticLambda0.onMediaButtonEvent(Unknown Source:2) E AndroidRuntime: at com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector$ComponentListener.onMediaButtonEvent(MediaSessionConnector.java:1396) E AndroidRuntime: at android.support.v4.media.session.MediaSessionCompat$Callback$MediaSessionCallbackApi21.onMediaButtonEvent(MediaSessionCompat.java:1602) E AndroidRuntime: at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1471) E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) E AndroidRuntime: at android.os.Looper.loop(Looper.java:193) E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6718) E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491) E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) W ActivityManager: Force finishing activity audio.funkwhale.ffa.dev/audio.funkwhale.ffa.activities.MainActivity xref: https://stackoverflow.com/questions/46445265/android-8-0-java-lang-illegalstateexception-not-allowed-to-start-service-inten
2022-06-04 00:10:03 +00:00
import android.os.Build
import android.os.Bundle
import android.os.ResultReceiver
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
class MediaSession(private val context: Context) {
2021-08-09 05:03:20 +00:00
var active = false
private val playbackStateBuilder = PlaybackStateCompat.Builder().apply {
setActions(
PlaybackStateCompat.ACTION_PLAY_PAUSE or
PlaybackStateCompat.ACTION_PLAY or
PlaybackStateCompat.ACTION_PAUSE or
PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
PlaybackStateCompat.ACTION_SEEK_TO or
PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM
)
}
val session: MediaSessionCompat by lazy {
MediaSessionCompat(context, context.packageName).apply {
setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)
setPlaybackState(playbackStateBuilder.build())
isActive = true
active = true
}
}
val connector: MediaSessionConnector by lazy {
MediaSessionConnector(session).also {
it.setQueueNavigator(FFAQueueNavigator())
2022-12-05 13:11:45 +00:00
it.setMediaButtonEventHandler { _, intent ->
if (!active) {
Fix Bluetooth control button unresponsiveness. With Oreo and later, Bluetooth control buttons may kill FFA if it is not the foreground application. Once this happens to resume playback, one needs to restart playback from the phone, rather than the play/pause action of Bluetooth headset. For example: D MediaSessionService: Sending KeyEvent { action=ACTION_UP, keyCode=KEYCODE_MEDIA_PLAY, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=0, downTime=0, deviceId=-1, source=0x0 } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.dev ( W ActivityManager: Background start not allowed: service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.play 549 uid=10149 pkg=audio.funkwhale.ffa.dev startFg?=false D AndroidRuntime: Shutting down VM --------- beginning of crash E AndroidRuntime: FATAL EXCEPTION: main E AndroidRuntime: Process: audio.funkwhale.ffa.dev, PID: 14549 E AndroidRuntime: java.lang.IllegalStateException: Not allowed to start service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) }: app is in background uid UidRecord{72fa8f8 u0a149 CAC bg:+11m56s597ms idle change:cached procs:1 seq(0,0,0)} E AndroidRuntime: at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577) E AndroidRuntime: at android.app.ContextImpl.startService(ContextImpl.java:1532) E AndroidRuntime: at android.content.ContextWrapper.startService(ContextWrapper.java:664) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.invoke$lambda-3$lambda-2(MediaSession.kt:47) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.$r8$lambda$jU84j_zRyeYuvwLrRY0b6XyQBMs(Unknown Source:0) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2$$ExternalSyntheticLambda0.onMediaButtonEvent(Unknown Source:2) E AndroidRuntime: at com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector$ComponentListener.onMediaButtonEvent(MediaSessionConnector.java:1396) E AndroidRuntime: at android.support.v4.media.session.MediaSessionCompat$Callback$MediaSessionCallbackApi21.onMediaButtonEvent(MediaSessionCompat.java:1602) E AndroidRuntime: at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1471) E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) E AndroidRuntime: at android.os.Looper.loop(Looper.java:193) E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6718) E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491) E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) W ActivityManager: Force finishing activity audio.funkwhale.ffa.dev/audio.funkwhale.ffa.activities.MainActivity xref: https://stackoverflow.com/questions/46445265/android-8-0-java-lang-illegalstateexception-not-allowed-to-start-service-inten
2022-06-04 00:10:03 +00:00
Intent(context, PlayerService::class.java).let { player ->
player.action = intent.action
Fix Bluetooth control button unresponsiveness. With Oreo and later, Bluetooth control buttons may kill FFA if it is not the foreground application. Once this happens to resume playback, one needs to restart playback from the phone, rather than the play/pause action of Bluetooth headset. For example: D MediaSessionService: Sending KeyEvent { action=ACTION_UP, keyCode=KEYCODE_MEDIA_PLAY, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=0, downTime=0, deviceId=-1, source=0x0 } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.dev ( W ActivityManager: Background start not allowed: service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.play 549 uid=10149 pkg=audio.funkwhale.ffa.dev startFg?=false D AndroidRuntime: Shutting down VM --------- beginning of crash E AndroidRuntime: FATAL EXCEPTION: main E AndroidRuntime: Process: audio.funkwhale.ffa.dev, PID: 14549 E AndroidRuntime: java.lang.IllegalStateException: Not allowed to start service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) }: app is in background uid UidRecord{72fa8f8 u0a149 CAC bg:+11m56s597ms idle change:cached procs:1 seq(0,0,0)} E AndroidRuntime: at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577) E AndroidRuntime: at android.app.ContextImpl.startService(ContextImpl.java:1532) E AndroidRuntime: at android.content.ContextWrapper.startService(ContextWrapper.java:664) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.invoke$lambda-3$lambda-2(MediaSession.kt:47) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.$r8$lambda$jU84j_zRyeYuvwLrRY0b6XyQBMs(Unknown Source:0) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2$$ExternalSyntheticLambda0.onMediaButtonEvent(Unknown Source:2) E AndroidRuntime: at com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector$ComponentListener.onMediaButtonEvent(MediaSessionConnector.java:1396) E AndroidRuntime: at android.support.v4.media.session.MediaSessionCompat$Callback$MediaSessionCallbackApi21.onMediaButtonEvent(MediaSessionCompat.java:1602) E AndroidRuntime: at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1471) E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) E AndroidRuntime: at android.os.Looper.loop(Looper.java:193) E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6718) E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491) E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) W ActivityManager: Force finishing activity audio.funkwhale.ffa.dev/audio.funkwhale.ffa.activities.MainActivity xref: https://stackoverflow.com/questions/46445265/android-8-0-java-lang-illegalstateexception-not-allowed-to-start-service-inten
2022-06-04 00:10:03 +00:00
intent.extras?.let { extras -> player.putExtras(extras) }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(player)
} else {
context.startService(player)
2021-09-09 07:56:15 +00:00
}
Fix Bluetooth control button unresponsiveness. With Oreo and later, Bluetooth control buttons may kill FFA if it is not the foreground application. Once this happens to resume playback, one needs to restart playback from the phone, rather than the play/pause action of Bluetooth headset. For example: D MediaSessionService: Sending KeyEvent { action=ACTION_UP, keyCode=KEYCODE_MEDIA_PLAY, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=0, downTime=0, deviceId=-1, source=0x0 } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.dev ( W ActivityManager: Background start not allowed: service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) } to audio.funkwhale.ffa.dev/audio.funkwhale.ffa.play 549 uid=10149 pkg=audio.funkwhale.ffa.dev startFg?=false D AndroidRuntime: Shutting down VM --------- beginning of crash E AndroidRuntime: FATAL EXCEPTION: main E AndroidRuntime: Process: audio.funkwhale.ffa.dev, PID: 14549 E AndroidRuntime: java.lang.IllegalStateException: Not allowed to start service Intent { act=android.intent.action.MEDIA_BUTTON cmp=audio.funkwhale.ffa.dev/audio.funkwhale.ffa.playback.PlayerService (has extras) }: app is in background uid UidRecord{72fa8f8 u0a149 CAC bg:+11m56s597ms idle change:cached procs:1 seq(0,0,0)} E AndroidRuntime: at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1577) E AndroidRuntime: at android.app.ContextImpl.startService(ContextImpl.java:1532) E AndroidRuntime: at android.content.ContextWrapper.startService(ContextWrapper.java:664) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.invoke$lambda-3$lambda-2(MediaSession.kt:47) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2.$r8$lambda$jU84j_zRyeYuvwLrRY0b6XyQBMs(Unknown Source:0) E AndroidRuntime: at audio.funkwhale.ffa.playback.MediaSession$connector$2$$ExternalSyntheticLambda0.onMediaButtonEvent(Unknown Source:2) E AndroidRuntime: at com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector$ComponentListener.onMediaButtonEvent(MediaSessionConnector.java:1396) E AndroidRuntime: at android.support.v4.media.session.MediaSessionCompat$Callback$MediaSessionCallbackApi21.onMediaButtonEvent(MediaSessionCompat.java:1602) E AndroidRuntime: at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1471) E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) E AndroidRuntime: at android.os.Looper.loop(Looper.java:193) E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6718) E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491) E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) W ActivityManager: Force finishing activity audio.funkwhale.ffa.dev/audio.funkwhale.ffa.activities.MainActivity xref: https://stackoverflow.com/questions/46445265/android-8-0-java-lang-illegalstateexception-not-allowed-to-start-service-inten
2022-06-04 00:10:03 +00:00
}
return@setMediaButtonEventHandler true
}
false
}
}
}
}
class FFAQueueNavigator : MediaSessionConnector.QueueNavigator {
2022-12-05 13:11:45 +00:00
override fun onSkipToQueueItem(player: Player, id: Long) {
CommandBus.send(Command.PlayTrack(id.toInt()))
}
2022-12-05 13:11:45 +00:00
override fun onCurrentMediaItemIndexChanged(player: Player) {}
2022-12-05 13:11:45 +00:00
override fun onCommand(player: Player, command: String, extras: Bundle?, cb: ResultReceiver?) =
true
override fun getSupportedQueueNavigatorActions(player: Player): Long {
return PlaybackStateCompat.ACTION_PLAY_PAUSE or
PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM
}
2022-12-05 13:11:45 +00:00
override fun onSkipToNext(player: Player) {
CommandBus.send(Command.NextTrack)
}
override fun getActiveQueueItemId(player: Player?) = player?.currentWindowIndex?.toLong() ?: 0
2022-12-05 13:11:45 +00:00
override fun onSkipToPrevious(player: Player) {
CommandBus.send(Command.PreviousTrack)
}
override fun onTimelineChanged(player: Player) {}
}