Make PlaybackService perpetually foreground
Make PlaybackService never leave the foreground unless forced to, will add an option to close the service later.
This commit is contained in:
parent
afa50ad531
commit
09971afb42
6 changed files with 37 additions and 13 deletions
|
@ -27,6 +27,9 @@
|
|||
<service
|
||||
android:name=".playback.PlaybackService"
|
||||
android:icon="@drawable/ic_launcher_foreground"
|
||||
android:foregroundServiceType="mediaPlayback"
|
||||
android:exported="false"
|
||||
android:enabled="true"
|
||||
android:description="@string/label_service_playback"
|
||||
android:stopWithTask="false" />
|
||||
</application>
|
||||
|
|
|
@ -23,7 +23,7 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) {
|
|||
super.onStart()
|
||||
|
||||
Intent(this, PlaybackService::class.java).also {
|
||||
this.startService(it)
|
||||
startService(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Notification
|
|||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
|
@ -12,12 +13,16 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.music.coil.getBitmap
|
||||
|
||||
// Manager for the playback notification
|
||||
// TODO: Implement some ability
|
||||
internal class PlaybackNotificationHolder {
|
||||
private lateinit var mNotification: Notification
|
||||
|
||||
private lateinit var notificationManager: NotificationManager
|
||||
private lateinit var baseNotification: NotificationCompat.Builder
|
||||
|
||||
private var isForeground = false
|
||||
|
||||
fun init(context: Context, session: MediaSessionCompat) {
|
||||
// Never run if the notification has already been created
|
||||
if (!::mNotification.isInitialized) {
|
||||
|
@ -28,7 +33,7 @@ internal class PlaybackNotificationHolder {
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
context.getString(R.string.label_notif_playback),
|
||||
context.getString(R.string.label_notification_playback),
|
||||
NotificationManager.IMPORTANCE_DEFAULT
|
||||
)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
|
@ -37,6 +42,7 @@ internal class PlaybackNotificationHolder {
|
|||
baseNotification = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_song)
|
||||
.setStyle(MediaStyle().setMediaSession(session.sessionToken))
|
||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
.setChannelId(CHANNEL_ID)
|
||||
.setShowWhen(false)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
|
@ -48,7 +54,7 @@ internal class PlaybackNotificationHolder {
|
|||
fun setMetadata(song: Song, playbackService: PlaybackService) {
|
||||
// Set the basic metadata since MediaStyle wont do it yourself.
|
||||
// Fun Fact: The documentation still says that MediaStyle will handle metadata changes
|
||||
// from MediaSession, even though it doesn't. After 6 years.
|
||||
// from MediaSession, even though it doesn't. Its been 6 years. Fun.
|
||||
baseNotification
|
||||
.setContentTitle(song.name)
|
||||
.setContentText(
|
||||
|
@ -62,10 +68,29 @@ internal class PlaybackNotificationHolder {
|
|||
getBitmap(song, playbackService) {
|
||||
baseNotification.setLargeIcon(it)
|
||||
mNotification = baseNotification.build()
|
||||
playbackService.startForeground(NOTIFICATION_ID, mNotification)
|
||||
|
||||
if (!isForeground) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
playbackService.startForeground(
|
||||
NOTIFICATION_ID, mNotification,
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
|
||||
)
|
||||
} else {
|
||||
playbackService.startForeground(NOTIFICATION_ID, mNotification)
|
||||
}
|
||||
} else {
|
||||
notificationManager.notify(NOTIFICATION_ID, mNotification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stop(playbackService: PlaybackService) {
|
||||
playbackService.stopForeground(true)
|
||||
notificationManager.cancel(NOTIFICATION_ID)
|
||||
|
||||
isForeground = false
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "CHANNEL_AUXIO_PLAYBACK"
|
||||
const val NOTIFICATION_ID = 0xA0A0
|
||||
|
|
|
@ -129,7 +129,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
stopForeground(true)
|
||||
notificationHolder.stop(this)
|
||||
unregisterReceiver(systemReceiver)
|
||||
|
||||
// Release everything that could cause a memory leak if left around
|
||||
|
@ -202,7 +202,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
|
||||
// Stop playing/the notification if there's nothing to play.
|
||||
player.stop()
|
||||
stopForeground(true)
|
||||
notificationHolder.stop(this)
|
||||
}
|
||||
|
||||
override fun onPlayingUpdate(isPlaying: Boolean) {
|
||||
|
@ -214,9 +214,6 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
startPollingPosition()
|
||||
} else {
|
||||
player.pause()
|
||||
|
||||
// Be a polite service and stop being foreground if nothing is playing.
|
||||
stopForeground(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ internal class PlaybackStateManager {
|
|||
field = value
|
||||
callbacks.forEach { it.onSongUpdate(value) }
|
||||
}
|
||||
private var mPosition: Long = 0 // TODO: Consider using millis instead of seconds?
|
||||
private var mPosition: Long = 0
|
||||
set(value) {
|
||||
field = value
|
||||
callbacks.forEach { it.onPositionUpdate(value) }
|
||||
|
|
|
@ -27,9 +27,8 @@
|
|||
<string name="label_play">Play</string>
|
||||
<string name="label_queue">Queue</string>
|
||||
<string name="label_queue_add">Add to queue</string>
|
||||
<string name="label_notif_playback">Music Playback</string>
|
||||
<string name="label_notification_playback">Music Playback</string>
|
||||
<string name="label_service_playback">The music playback service for Auxio.</string>
|
||||
<string name="label_is_playing">Auxio is playing music</string>
|
||||
|
||||
<!-- Hint Namespace | EditText Hints -->
|
||||
<string name="hint_search_library">Search Library…</string>
|
||||
|
@ -50,7 +49,7 @@
|
|||
<string name="description_skip_prev">Skip to last song</string>
|
||||
<string name="description_shuffle_on">Turn shuffle on</string>
|
||||
<string name="description_shuffle_off">Turn shuffle off</string>
|
||||
<string name="description_loop">Change Loop Mode</string>
|
||||
<string name="description_loop">Loop</string>
|
||||
|
||||
<!-- Placeholder Namespace | Placeholder values -->
|
||||
<string name="placeholder_genre">Unknown Genre</string>
|
||||
|
|
Loading…
Reference in a new issue