Otter-App-Android-Funkwhale/app/src/main/java/com/github/apognu/otter/playback/MediaControlsManager.kt

117 lines
3.9 KiB
Kotlin

package com.github.apognu.otter.playback
import android.app.Notification
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.media.app.NotificationCompat.MediaStyle
import androidx.media.session.MediaButtonReceiver
import com.github.apognu.otter.Otter
import com.github.apognu.otter.R
import com.github.apognu.otter.activities.MainActivity
import com.github.apognu.otter.utils.AppContext
import com.github.apognu.otter.utils.maybeNormalizeUrl
import com.github.apognu.otter.models.domain.Track
import com.squareup.picasso.Picasso
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.launch
class MediaControlsManager(val context: Service, private val scope: CoroutineScope, private val mediaSession: MediaSessionCompat) {
companion object {
const val NOTIFICATION_ACTION_OPEN_QUEUE = 0
}
private var notification: Notification? = null
fun updateNotification(track: Track?, playing: Boolean) {
if (notification == null && !playing) return
track?.let {
val stateIcon = when (playing) {
true -> R.drawable.pause
false -> R.drawable.play
}
scope.launch(Default) {
val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() }
val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, 0)
val coverUrl = maybeNormalizeUrl(track.album?.cover())
notification = NotificationCompat.Builder(
context,
AppContext.NOTIFICATION_CHANNEL_MEDIA_CONTROL
)
.setShowWhen(false)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setStyle(
MediaStyle()
.setMediaSession(mediaSession.sessionToken)
.setShowActionsInCompactView(0, 1, 2)
)
.setSmallIcon(R.drawable.ottershape)
.run {
coverUrl?.let {
try {
setLargeIcon(Picasso.get().load(coverUrl).get())
} catch (_: Exception) {
}
return@run this
}
this
}
.setContentTitle(track.title)
.setContentText(track.artist?.name)
.setContentIntent(openPendingIntent)
.setChannelId(AppContext.NOTIFICATION_CHANNEL_MEDIA_CONTROL)
.addAction(
action(
R.drawable.previous, context.getString(R.string.control_previous),
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
)
)
.addAction(
action(
stateIcon, context.getString(R.string.control_toggle),
PlaybackStateCompat.ACTION_PLAY_PAUSE
)
)
.addAction(
action(
R.drawable.next, context.getString(R.string.control_next),
PlaybackStateCompat.ACTION_SKIP_TO_NEXT
)
)
.build()
notification?.let {
if (playing) {
context.startForeground(AppContext.NOTIFICATION_MEDIA_CONTROL, it)
} else {
NotificationManagerCompat.from(context).notify(AppContext.NOTIFICATION_MEDIA_CONTROL, it)
}
}
Otter.get().mediaSession.connector.invalidateMediaSessionMetadata()
}
}
}
fun remove() {
NotificationManagerCompat.from(context).cancel(AppContext.NOTIFICATION_MEDIA_CONTROL)
}
private fun action(icon: Int, title: String, id: Long): NotificationCompat.Action {
return MediaButtonReceiver.buildMediaButtonPendingIntent(context, id).run {
NotificationCompat.Action.Builder(icon, title, this).build()
}
}
}