Clean up PlaybackService
Clean up the code in PlaybackService.
This commit is contained in:
parent
7524589969
commit
7a4b654222
3 changed files with 104 additions and 123 deletions
|
@ -41,10 +41,9 @@ class AudioReactor(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy this object and abandon its audio focus request, should be ran on destruction to
|
* Abandon the current focus request, functionally "Destroying it".
|
||||||
* prevent memory leaks.
|
|
||||||
*/
|
*/
|
||||||
fun destroy() {
|
fun release() {
|
||||||
AudioManagerCompat.abandonAudioFocusRequest(audioManager, request)
|
AudioManagerCompat.abandonAudioFocusRequest(audioManager, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,8 +186,8 @@ class PlaybackNotification private constructor(
|
||||||
const val NOTIFICATION_ID = 0xA0A0
|
const val NOTIFICATION_ID = 0xA0A0
|
||||||
const val REQUEST_CODE = 0xA0C0
|
const val REQUEST_CODE = 0xA0C0
|
||||||
|
|
||||||
// Build type is added to the codes so that dual installations dont conflict
|
// Build type is added to the codes so that dual release/debug installations dont conflict
|
||||||
// with eachother.
|
// with each other.
|
||||||
const val ACTION_LOOP = "ACTION_AUXIO_LOOP_" + BuildConfig.BUILD_TYPE
|
const val ACTION_LOOP = "ACTION_AUXIO_LOOP_" + BuildConfig.BUILD_TYPE
|
||||||
const val ACTION_SHUFFLE = "ACTION_AUXIO_SHUFFLE_" + BuildConfig.BUILD_TYPE
|
const val ACTION_SHUFFLE = "ACTION_AUXIO_SHUFFLE_" + BuildConfig.BUILD_TYPE
|
||||||
const val ACTION_SKIP_PREV = "ACTION_AUXIO_SKIP_PREV_" + BuildConfig.BUILD_TYPE
|
const val ACTION_SKIP_PREV = "ACTION_AUXIO_SKIP_PREV_" + BuildConfig.BUILD_TYPE
|
||||||
|
|
|
@ -19,7 +19,6 @@ import com.google.android.exoplayer2.C
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException
|
import com.google.android.exoplayer2.ExoPlaybackException
|
||||||
import com.google.android.exoplayer2.MediaItem
|
import com.google.android.exoplayer2.MediaItem
|
||||||
import com.google.android.exoplayer2.Player
|
import com.google.android.exoplayer2.Player
|
||||||
import com.google.android.exoplayer2.Renderer
|
|
||||||
import com.google.android.exoplayer2.RenderersFactory
|
import com.google.android.exoplayer2.RenderersFactory
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes
|
import com.google.android.exoplayer2.audio.AudioAttributes
|
||||||
|
@ -65,16 +64,12 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
private val settingsManager = SettingsManager.getInstance()
|
private val settingsManager = SettingsManager.getInstance()
|
||||||
|
|
||||||
private lateinit var mediaSession: MediaSessionCompat
|
private lateinit var mediaSession: MediaSessionCompat
|
||||||
private lateinit var systemReceiver: SystemEventReceiver
|
|
||||||
private val playerAttributes = AudioAttributes.Builder()
|
|
||||||
.setUsage(C.USAGE_MEDIA)
|
|
||||||
.setContentType(C.CONTENT_TYPE_MUSIC)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
private lateinit var notificationManager: NotificationManager
|
private lateinit var notificationManager: NotificationManager
|
||||||
private lateinit var notification: PlaybackNotification
|
private lateinit var notification: PlaybackNotification
|
||||||
|
|
||||||
private lateinit var audioReactor: AudioReactor
|
private lateinit var audioReactor: AudioReactor
|
||||||
|
private lateinit var systemReceiver: SystemEventReceiver
|
||||||
|
|
||||||
private var isForeground = false
|
private var isForeground = false
|
||||||
|
|
||||||
private val serviceJob = Job()
|
private val serviceJob = Job()
|
||||||
|
@ -90,7 +85,8 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
return START_NOT_STICKY
|
return START_NOT_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
// No binding, service is headless. Deliver updates through PlaybackStateManager/SettingsManager instead.
|
// No binding, service is headless.
|
||||||
|
// Deliver updates through PlaybackStateManager/SettingsManager instead.
|
||||||
override fun onBind(intent: Intent): IBinder? = null
|
override fun onBind(intent: Intent): IBinder? = null
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
|
@ -98,15 +94,21 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
|
|
||||||
// --- PLAYER SETUP ---
|
// --- PLAYER SETUP ---
|
||||||
|
|
||||||
player.apply {
|
player.addListener(this@PlaybackService)
|
||||||
addListener(this@PlaybackService)
|
player.setAudioAttributes(
|
||||||
setAudioAttributes(playerAttributes, false)
|
AudioAttributes.Builder()
|
||||||
}
|
.setUsage(C.USAGE_MEDIA)
|
||||||
|
.setContentType(C.CONTENT_TYPE_MUSIC)
|
||||||
|
.build(),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
audioReactor = AudioReactor(this, player)
|
audioReactor = AudioReactor(this, player)
|
||||||
|
|
||||||
// --- SYSTEM RECEIVER SETUP ---
|
// --- SYSTEM RECEIVER SETUP ---
|
||||||
|
|
||||||
|
systemReceiver = SystemEventReceiver()
|
||||||
|
|
||||||
// Set up the media button callbacks
|
// Set up the media button callbacks
|
||||||
mediaSession = MediaSessionCompat(this, packageName).apply {
|
mediaSession = MediaSessionCompat(this, packageName).apply {
|
||||||
isActive = true
|
isActive = true
|
||||||
|
@ -119,9 +121,6 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up callback for system events
|
|
||||||
systemReceiver = SystemEventReceiver()
|
|
||||||
|
|
||||||
IntentFilter().apply {
|
IntentFilter().apply {
|
||||||
addAction(PlaybackNotification.ACTION_LOOP)
|
addAction(PlaybackNotification.ACTION_LOOP)
|
||||||
addAction(PlaybackNotification.ACTION_SHUFFLE)
|
addAction(PlaybackNotification.ACTION_SHUFFLE)
|
||||||
|
@ -149,8 +148,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
playbackManager.addCallback(this)
|
playbackManager.addCallback(this)
|
||||||
|
|
||||||
if (playbackManager.song != null || playbackManager.isRestored) {
|
if (playbackManager.song != null || playbackManager.isRestored) {
|
||||||
restorePlayer()
|
restore()
|
||||||
restoreNotification()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- SETTINGSMANAGER SETUP ---
|
// --- SETTINGSMANAGER SETUP ---
|
||||||
|
@ -164,14 +162,14 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
stopForegroundAndNotification()
|
stopForegroundAndNotification()
|
||||||
unregisterReceiver(systemReceiver)
|
unregisterReceiver(systemReceiver)
|
||||||
|
|
||||||
// Release everything that could cause a memory leak if left around
|
|
||||||
player.release()
|
player.release()
|
||||||
mediaSession.release()
|
mediaSession.release()
|
||||||
audioReactor.destroy()
|
audioReactor.release()
|
||||||
|
|
||||||
playbackManager.removeCallback(this)
|
playbackManager.removeCallback(this)
|
||||||
settingsManager.removeCallback(this)
|
settingsManager.removeCallback(this)
|
||||||
|
|
||||||
// The service coroutines last job is to save the state to the DB, before terminating itself.
|
// The service coroutines last job is to save the state to the DB, before terminating itself
|
||||||
serviceScope.launch {
|
serviceScope.launch {
|
||||||
playbackManager.saveStateToDatabase(this@PlaybackService)
|
playbackManager.saveStateToDatabase(this@PlaybackService)
|
||||||
serviceJob.cancel()
|
serviceJob.cancel()
|
||||||
|
@ -191,13 +189,14 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
||||||
|
// Reset the loop mode from LOOP_ONE (if it is LOOP_ONE) on each repeat
|
||||||
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT) {
|
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT) {
|
||||||
playbackManager.clearLoopMode()
|
playbackManager.clearLoopMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayerError(error: ExoPlaybackException) {
|
override fun onPlayerError(error: ExoPlaybackException) {
|
||||||
// If there's any issue, just go to the next song. I don't really care.
|
// If there's any issue, just go to the next song.
|
||||||
playbackManager.next()
|
playbackManager.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,21 +209,15 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
// --- PLAYBACK STATE CALLBACK OVERRIDES ---
|
// --- PLAYBACK STATE CALLBACK OVERRIDES ---
|
||||||
|
|
||||||
override fun onSongUpdate(song: Song?) {
|
override fun onSongUpdate(song: Song?) {
|
||||||
song?.let {
|
if (song != null) {
|
||||||
val item = MediaItem.fromUri(it.id.toURI())
|
player.setMediaItem(MediaItem.fromUri(song.id.toURI()))
|
||||||
|
|
||||||
player.setMediaItem(item)
|
|
||||||
player.prepare()
|
player.prepare()
|
||||||
|
|
||||||
if (playbackManager.isPlaying) {
|
pushMetadataToSession(song)
|
||||||
player.play()
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadMetadataToSession(it)
|
notification.setMetadata(
|
||||||
|
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
|
||||||
notification.setMetadata(this, it, settingsManager.colorizeNotif) {
|
)
|
||||||
startForegroundOrNotify()
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -254,11 +247,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoopUpdate(loopMode: LoopMode) {
|
override fun onLoopUpdate(loopMode: LoopMode) {
|
||||||
player.repeatMode = if (loopMode == LoopMode.NONE) {
|
player.setLoopMode(loopMode)
|
||||||
Player.REPEAT_MODE_OFF
|
|
||||||
} else {
|
|
||||||
Player.REPEAT_MODE_ONE
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!settingsManager.useAltNotifAction) {
|
if (!settingsManager.useAltNotifAction) {
|
||||||
notification.setLoop(this, loopMode)
|
notification.setLoop(this, loopMode)
|
||||||
|
@ -284,10 +273,10 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
// --- SETTINGSMANAGER OVERRIDES ---
|
// --- SETTINGSMANAGER OVERRIDES ---
|
||||||
|
|
||||||
override fun onColorizeNotifUpdate(doColorize: Boolean) {
|
override fun onColorizeNotifUpdate(doColorize: Boolean) {
|
||||||
playbackManager.song?.let {
|
playbackManager.song?.let { song ->
|
||||||
notification.setMetadata(this, it, settingsManager.colorizeNotif) {
|
notification.setMetadata(
|
||||||
startForegroundOrNotify()
|
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,18 +291,18 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onShowCoverUpdate(showCovers: Boolean) {
|
override fun onShowCoverUpdate(showCovers: Boolean) {
|
||||||
playbackManager.song?.let {
|
playbackManager.song?.let { song ->
|
||||||
notification.setMetadata(this, it, settingsManager.colorizeNotif) {
|
notification.setMetadata(
|
||||||
startForegroundOrNotify()
|
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQualityCoverUpdate(doQualityCovers: Boolean) {
|
override fun onQualityCoverUpdate(doQualityCovers: Boolean) {
|
||||||
playbackManager.song?.let { song ->
|
playbackManager.song?.let { song ->
|
||||||
notification.setMetadata(this, song, settingsManager.colorizeNotif) {
|
notification.setMetadata(
|
||||||
startForegroundOrNotify()
|
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,11 +314,14 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
private fun newPlayer(): SimpleExoPlayer {
|
private fun newPlayer(): SimpleExoPlayer {
|
||||||
// Since Auxio is a music player, only specify an audio renderer to save battery/apk size/cache size.
|
// Since Auxio is a music player, only specify an audio renderer to save battery/apk size/cache size.
|
||||||
val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ ->
|
val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ ->
|
||||||
arrayOf<Renderer>(
|
arrayOf(
|
||||||
MediaCodecAudioRenderer(this, MediaCodecSelector.DEFAULT, handler, audioListener)
|
MediaCodecAudioRenderer(
|
||||||
|
this, MediaCodecSelector.DEFAULT, handler, audioListener
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable constant bitrate seeking so that certain MP3s/AACs are seekable
|
||||||
val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)
|
val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)
|
||||||
|
|
||||||
return SimpleExoPlayer.Builder(this, audioRenderer)
|
return SimpleExoPlayer.Builder(this, audioRenderer)
|
||||||
|
@ -338,30 +330,17 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore the [SimpleExoPlayer] state, if the service was destroyed while [PlaybackStateManager] persisted.
|
* Fully restore the notification and playback state
|
||||||
*/
|
*/
|
||||||
private fun restorePlayer() {
|
private fun restore() {
|
||||||
playbackManager.song?.let {
|
playbackManager.song?.let { song ->
|
||||||
val item = MediaItem.fromUri(it.id.toURI())
|
notification.setMetadata(this, song, settingsManager.colorizeNotif) {}
|
||||||
player.setMediaItem(item)
|
|
||||||
player.prepare()
|
player.setMediaItem(MediaItem.fromUri(song.id.toURI()))
|
||||||
player.seekTo(playbackManager.position)
|
player.seekTo(playbackManager.position)
|
||||||
|
player.prepare()
|
||||||
}
|
}
|
||||||
|
|
||||||
when (playbackManager.loopMode) {
|
|
||||||
LoopMode.NONE -> {
|
|
||||||
player.repeatMode = Player.REPEAT_MODE_OFF
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
player.repeatMode = Player.REPEAT_MODE_ONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restore the notification, if the service was destroyed while [PlaybackStateManager] persisted.
|
|
||||||
*/
|
|
||||||
private fun restoreNotification() {
|
|
||||||
notification.setParent(this, playbackManager.parent)
|
notification.setParent(this, playbackManager.parent)
|
||||||
notification.setPlaying(this, playbackManager.isPlaying)
|
notification.setPlaying(this, playbackManager.isPlaying)
|
||||||
|
|
||||||
|
@ -371,22 +350,14 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
notification.setLoop(this, playbackManager.loopMode)
|
notification.setLoop(this, playbackManager.loopMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackManager.song?.let { song ->
|
player.setLoopMode(playbackManager.loopMode)
|
||||||
notification.setMetadata(this, song, settingsManager.colorizeNotif) {
|
|
||||||
if (playbackManager.isPlaying) {
|
|
||||||
startForegroundOrNotify()
|
|
||||||
} else {
|
|
||||||
stopForegroundAndNotification()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload the song metadata to the [MediaSessionCompat], so that things such as album art
|
* Upload the song metadata to the [MediaSessionCompat], so that things such as album art
|
||||||
* show up on the lock screen.
|
* show up on the lock screen.
|
||||||
*/
|
*/
|
||||||
private fun uploadMetadataToSession(song: Song) {
|
private fun pushMetadataToSession(song: Song) {
|
||||||
val builder = MediaMetadataCompat.Builder()
|
val builder = MediaMetadataCompat.Builder()
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, song.name)
|
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, song.name)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, song.name)
|
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, song.name)
|
||||||
|
@ -404,35 +375,43 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start polling the position on a co-routine.
|
* Start polling the position on a coroutine.
|
||||||
*/
|
*/
|
||||||
private fun startPollingPosition() {
|
private fun startPollingPosition() {
|
||||||
fun pollCurrentPosition() = flow {
|
val pollFlow = flow {
|
||||||
while (player.isPlaying) {
|
while (true) {
|
||||||
emit(player.currentPosition)
|
emit(player.currentPosition)
|
||||||
delay(250)
|
delay(500)
|
||||||
}
|
}
|
||||||
}.conflate()
|
}.conflate()
|
||||||
|
|
||||||
serviceScope.launch {
|
serviceScope.launch {
|
||||||
pollCurrentPosition().takeWhile { player.isPlaying }.collect {
|
pollFlow.takeWhile { player.isPlaying }.collect {
|
||||||
playbackManager.setPosition(it)
|
playbackManager.setPosition(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut to transform a [LoopMode] into a player repeat mode
|
||||||
|
*/
|
||||||
|
private fun Player.setLoopMode(mode: LoopMode) {
|
||||||
|
repeatMode = if (mode == LoopMode.NONE) {
|
||||||
|
Player.REPEAT_MODE_OFF
|
||||||
|
} else {
|
||||||
|
Player.REPEAT_MODE_ALL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bring the service into the foreground and show the notification, or refresh the notification.
|
* Bring the service into the foreground and show the notification, or refresh the notification.
|
||||||
*/
|
*/
|
||||||
private fun startForegroundOrNotify() {
|
private fun startForegroundOrNotify() {
|
||||||
// Don't start foreground if:
|
|
||||||
// - The playback hasnt even started
|
|
||||||
// - The playback hasnt been restored
|
|
||||||
// - There is nothing to play
|
|
||||||
if (playbackManager.hasPlayed && playbackManager.isRestored && playbackManager.song != null) {
|
if (playbackManager.hasPlayed && playbackManager.isRestored && playbackManager.song != null) {
|
||||||
logD("Starting foreground/notifying")
|
logD("Starting foreground/notifying")
|
||||||
|
|
||||||
if (!isForeground) {
|
if (!isForeground) {
|
||||||
|
// Specify that this is a media service, if supported.
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
startForeground(
|
startForeground(
|
||||||
PlaybackNotification.NOTIFICATION_ID, notification.build(),
|
PlaybackNotification.NOTIFICATION_ID, notification.build(),
|
||||||
|
@ -444,6 +423,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// If we are already in foreground just update the notification
|
||||||
notificationManager.notify(
|
notificationManager.notify(
|
||||||
PlaybackNotification.NOTIFICATION_ID, notification.build()
|
PlaybackNotification.NOTIFICATION_ID, notification.build()
|
||||||
)
|
)
|
||||||
|
@ -516,36 +496,46 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
|
|
||||||
action?.let {
|
action?.let {
|
||||||
when (it) {
|
when (it) {
|
||||||
PlaybackNotification.ACTION_LOOP ->
|
// --- NOTIFICATION CASES ---
|
||||||
playbackManager.setLoopMode(playbackManager.loopMode.increment())
|
|
||||||
|
|
||||||
PlaybackNotification.ACTION_SHUFFLE ->
|
PlaybackNotification.ACTION_PLAY_PAUSE -> playbackManager.setPlaying(
|
||||||
playbackManager.setShuffling(!playbackManager.isShuffling, keepSong = true)
|
!playbackManager.isPlaying
|
||||||
|
)
|
||||||
|
|
||||||
|
PlaybackNotification.ACTION_LOOP -> playbackManager.setLoopMode(
|
||||||
|
playbackManager.loopMode.increment()
|
||||||
|
)
|
||||||
|
|
||||||
|
PlaybackNotification.ACTION_SHUFFLE -> playbackManager.setShuffling(
|
||||||
|
!playbackManager.isShuffling, keepSong = true
|
||||||
|
)
|
||||||
|
|
||||||
PlaybackNotification.ACTION_SKIP_PREV -> playbackManager.prev()
|
PlaybackNotification.ACTION_SKIP_PREV -> playbackManager.prev()
|
||||||
|
|
||||||
PlaybackNotification.ACTION_PLAY_PAUSE ->
|
|
||||||
playbackManager.setPlaying(!playbackManager.isPlaying)
|
|
||||||
|
|
||||||
PlaybackNotification.ACTION_SKIP_NEXT -> playbackManager.next()
|
PlaybackNotification.ACTION_SKIP_NEXT -> playbackManager.next()
|
||||||
PlaybackNotification.ACTION_EXIT -> stop()
|
|
||||||
|
|
||||||
BluetoothDevice.ACTION_ACL_CONNECTED -> resume()
|
PlaybackNotification.ACTION_EXIT -> {
|
||||||
BluetoothDevice.ACTION_ACL_DISCONNECTED -> pause()
|
playbackManager.setPlaying(false)
|
||||||
|
stopForegroundAndNotification()
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- HEADSET CASES ---
|
||||||
|
|
||||||
|
BluetoothDevice.ACTION_ACL_CONNECTED -> resumeFromPlug()
|
||||||
|
BluetoothDevice.ACTION_ACL_DISCONNECTED -> pauseFromPlug()
|
||||||
|
|
||||||
AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED -> {
|
AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED -> {
|
||||||
when (intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1)) {
|
when (intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1)) {
|
||||||
AudioManager.SCO_AUDIO_STATE_CONNECTED -> resume()
|
AudioManager.SCO_AUDIO_STATE_CONNECTED -> resumeFromPlug()
|
||||||
AudioManager.SCO_AUDIO_STATE_DISCONNECTED -> pause()
|
AudioManager.SCO_AUDIO_STATE_DISCONNECTED -> pauseFromPlug()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioManager.ACTION_AUDIO_BECOMING_NOISY -> pause()
|
AudioManager.ACTION_AUDIO_BECOMING_NOISY -> pauseFromPlug()
|
||||||
|
|
||||||
Intent.ACTION_HEADSET_PLUG -> {
|
Intent.ACTION_HEADSET_PLUG -> {
|
||||||
when (intent.getIntExtra("state", -1)) {
|
when (intent.getIntExtra("state", -1)) {
|
||||||
CONNECTED -> resume()
|
CONNECTED -> resumeFromPlug()
|
||||||
DISCONNECTED -> pause()
|
DISCONNECTED -> pauseFromPlug()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,9 +543,9 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume, as long as its allowed.
|
* Resume from a headset plug event, as long as its allowed.
|
||||||
*/
|
*/
|
||||||
private fun resume() {
|
private fun resumeFromPlug() {
|
||||||
if (playbackManager.song != null && settingsManager.doPlugMgt) {
|
if (playbackManager.song != null && settingsManager.doPlugMgt) {
|
||||||
logD("Device connected, resuming...")
|
logD("Device connected, resuming...")
|
||||||
|
|
||||||
|
@ -564,23 +554,15 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause, as long as its allowed.
|
* Pause from a headset plug, as long as its allowed.
|
||||||
*/
|
*/
|
||||||
private fun pause() {
|
private fun pauseFromPlug() {
|
||||||
if (playbackManager.song != null && settingsManager.doPlugMgt) {
|
if (playbackManager.song != null && settingsManager.doPlugMgt) {
|
||||||
logD("Device disconnected, pausing...")
|
logD("Device disconnected, pausing...")
|
||||||
|
|
||||||
playbackManager.setPlaying(false)
|
playbackManager.setPlaying(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop if the X button was clicked from the notification
|
|
||||||
*/
|
|
||||||
private fun stop() {
|
|
||||||
playbackManager.setPlaying(false)
|
|
||||||
stopForegroundAndNotification()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
Loading…
Reference in a new issue