Add notification settings
Add some notification settings to change the action & the colorization.
This commit is contained in:
parent
b8b6e8421b
commit
0a0828684c
8 changed files with 143 additions and 22 deletions
|
@ -8,6 +8,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.media.app.NotificationCompat.MediaStyle
|
||||
import org.oxycblt.auxio.MainActivity
|
||||
|
@ -17,6 +18,7 @@ import org.oxycblt.auxio.music.coil.getBitmap
|
|||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
|
||||
object NotificationUtils {
|
||||
const val CHANNEL_ID = "CHANNEL_AUXIO_PLAYBACK"
|
||||
|
@ -24,6 +26,7 @@ object NotificationUtils {
|
|||
const val REQUEST_CODE = 0xA0C0
|
||||
|
||||
const val ACTION_LOOP = "ACTION_AUXIO_LOOP"
|
||||
const val ACTION_SHUFFLE = "ACTION_AUXIO_SHUFFLE"
|
||||
const val ACTION_SKIP_PREV = "ACTION_AUXIO_SKIP_PREV"
|
||||
const val ACTION_PLAY_PAUSE = "ACTION_AUXIO_PLAY_PAUSE"
|
||||
const val ACTION_SKIP_NEXT = "ACTION_AUXIO_SKIP_NEXT"
|
||||
|
@ -96,10 +99,17 @@ fun NotificationCompat.Builder.setMetadata(song: Song, context: Context, onDone:
|
|||
setSubText(song.album.name)
|
||||
}
|
||||
|
||||
// getBitmap() is concurrent, so only call back to the object calling this function when
|
||||
// the loading is over.
|
||||
getBitmap(song, context) {
|
||||
setLargeIcon(it)
|
||||
// Also set the cover art [If reasonable]
|
||||
if (SettingsManager.getInstance().colorizeNotif) {
|
||||
// getBitmap() is concurrent, so only call back to the object calling this function when
|
||||
// the loading is over.
|
||||
getBitmap(song, context) {
|
||||
setLargeIcon(it)
|
||||
|
||||
onDone()
|
||||
}
|
||||
} else {
|
||||
setLargeIcon(null)
|
||||
|
||||
onDone()
|
||||
}
|
||||
|
@ -115,12 +125,16 @@ fun NotificationCompat.Builder.updatePlaying(context: Context) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Update the loop button on the media notification
|
||||
* Update the loop/shuffle button on the media notification
|
||||
* @param context The context required to refresh the action
|
||||
*/
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun NotificationCompat.Builder.updateLoop(context: Context) {
|
||||
mActions[0] = newAction(NotificationUtils.ACTION_LOOP, context)
|
||||
fun NotificationCompat.Builder.updateExtraAction(context: Context) {
|
||||
mActions[0] = if (SettingsManager.getInstance().useAltNotifAction) {
|
||||
newAction(NotificationUtils.ACTION_SHUFFLE, context)
|
||||
} else {
|
||||
newAction(NotificationUtils.ACTION_LOOP, context)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,12 +165,22 @@ private fun newAction(action: String, context: Context): NotificationCompat.Acti
|
|||
val drawable = when (action) {
|
||||
NotificationUtils.ACTION_LOOP -> {
|
||||
when (playbackManager.loopMode) {
|
||||
LoopMode.NONE -> R.drawable.ic_loop_disabled
|
||||
LoopMode.NONE -> R.drawable.ic_loop_inactive
|
||||
LoopMode.ONCE -> R.drawable.ic_loop_one
|
||||
LoopMode.INFINITE -> R.drawable.ic_loop
|
||||
}
|
||||
}
|
||||
|
||||
NotificationUtils.ACTION_SHUFFLE -> {
|
||||
Log.d("A function", "Jesus christ does this even call???")
|
||||
|
||||
if (playbackManager.isShuffling) {
|
||||
R.drawable.ic_shuffle
|
||||
} else {
|
||||
R.drawable.ic_shuffle_inactive
|
||||
}
|
||||
}
|
||||
|
||||
NotificationUtils.ACTION_SKIP_PREV -> R.drawable.ic_skip_prev
|
||||
|
||||
NotificationUtils.ACTION_PLAY_PAUSE -> {
|
||||
|
@ -170,7 +194,6 @@ private fun newAction(action: String, context: Context): NotificationCompat.Acti
|
|||
NotificationUtils.ACTION_SKIP_NEXT -> R.drawable.ic_skip_next
|
||||
|
||||
NotificationUtils.ACTION_EXIT -> R.drawable.ic_exit
|
||||
|
||||
else -> R.drawable.ic_error
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.oxycblt.auxio.music.toURI
|
|||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
|
||||
/**
|
||||
* A service that manages the system-side aspects of playback, such as:
|
||||
|
@ -52,12 +53,14 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
|||
* to it to deliver commands.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Callback {
|
||||
class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Callback, SettingsManager.Callback {
|
||||
private val player: SimpleExoPlayer by lazy {
|
||||
SimpleExoPlayer.Builder(applicationContext).build()
|
||||
}
|
||||
|
||||
private val playbackManager = PlaybackStateManager.getInstance()
|
||||
private val settingsManager = SettingsManager.getInstance()
|
||||
|
||||
private lateinit var mediaSession: MediaSessionCompat
|
||||
private lateinit var systemReceiver: SystemEventReceiver
|
||||
|
||||
|
@ -121,6 +124,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
systemReceiver = SystemEventReceiver()
|
||||
IntentFilter().apply {
|
||||
addAction(NotificationUtils.ACTION_LOOP)
|
||||
addAction(NotificationUtils.ACTION_SHUFFLE)
|
||||
addAction(NotificationUtils.ACTION_SKIP_PREV)
|
||||
addAction(NotificationUtils.ACTION_PLAY_PAUSE)
|
||||
addAction(NotificationUtils.ACTION_SKIP_NEXT)
|
||||
|
@ -150,6 +154,10 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
restorePlayer()
|
||||
restoreNotification()
|
||||
}
|
||||
|
||||
// --- SETTINGSMANAGER SETUP ---
|
||||
|
||||
settingsManager.addCallback(this)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
@ -162,6 +170,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
player.release()
|
||||
mediaSession.release()
|
||||
playbackManager.removeCallback(this)
|
||||
settingsManager.removeCallback(this)
|
||||
|
||||
serviceScope.launch {
|
||||
playbackManager.saveStateToDatabase(this@PlaybackService)
|
||||
|
@ -274,10 +283,18 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
}
|
||||
}
|
||||
|
||||
notification.updateLoop(this)
|
||||
notification.updateExtraAction(this)
|
||||
startForegroundOrNotify("Loop")
|
||||
}
|
||||
|
||||
override fun onShuffleUpdate(isShuffling: Boolean) {
|
||||
if (settingsManager.useAltNotifAction) {
|
||||
notification.updateExtraAction(this)
|
||||
|
||||
startForegroundOrNotify("Shuffle update")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSeekConfirm(position: Long) {
|
||||
changeIsFromAudioFocus = false
|
||||
|
||||
|
@ -290,6 +307,22 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
restorePlayer()
|
||||
}
|
||||
|
||||
// --- SETTINGSMANAGER OVERRIDES ---
|
||||
|
||||
override fun onColorizeNotifUpdate(doColorize: Boolean) {
|
||||
playbackManager.song?.let {
|
||||
notification.setMetadata(it, this) {
|
||||
startForegroundOrNotify("Colorize update")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNotifActionUpdate(useAltAction: Boolean) {
|
||||
notification.updateExtraAction(this)
|
||||
|
||||
startForegroundOrNotify("Notif action update")
|
||||
}
|
||||
|
||||
// --- OTHER FUNCTIONS ---
|
||||
|
||||
private fun restorePlayer() {
|
||||
|
@ -311,7 +344,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
}
|
||||
|
||||
private fun restoreNotification() {
|
||||
notification.updateLoop(this)
|
||||
notification.updateExtraAction(this)
|
||||
notification.updateMode(this)
|
||||
notification.updatePlaying(this)
|
||||
|
||||
|
@ -436,6 +469,8 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
|||
when (it) {
|
||||
NotificationUtils.ACTION_LOOP ->
|
||||
playbackManager.setLoopMode(playbackManager.loopMode.increment())
|
||||
NotificationUtils.ACTION_SHUFFLE ->
|
||||
playbackManager.setShuffleStatus(!playbackManager.isShuffling)
|
||||
NotificationUtils.ACTION_SKIP_PREV -> playbackManager.prev()
|
||||
NotificationUtils.ACTION_PLAY_PAUSE -> {
|
||||
playbackManager.setPlayingStatus(!playbackManager.isPlaying)
|
||||
|
|
|
@ -18,6 +18,9 @@ fun String.toThemeInt(): Int {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an theme integer into an icon that can be used.
|
||||
*/
|
||||
@DrawableRes
|
||||
fun Int.toThemeIcon(): Int {
|
||||
return when (this) {
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.oxycblt.auxio.settings
|
|||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.ui.ACCENTS
|
||||
|
@ -19,10 +18,11 @@ class SettingsManager private constructor(context: Context) :
|
|||
sharedPrefs.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
// --- VALUES ---
|
||||
|
||||
val theme: Int
|
||||
get() {
|
||||
return sharedPrefs.getString(Keys.KEY_THEME, EntryNames.THEME_AUTO)?.toThemeInt()
|
||||
?: AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
return sharedPrefs.getString(Keys.KEY_THEME, EntryNames.THEME_AUTO)!!.toThemeInt()
|
||||
}
|
||||
|
||||
var accent: Pair<Int, Int>
|
||||
|
@ -47,6 +47,16 @@ class SettingsManager private constructor(context: Context) :
|
|||
return sharedPrefs.getBoolean(Keys.KEY_EDGE_TO_EDGE, false)
|
||||
}
|
||||
|
||||
val colorizeNotif: Boolean
|
||||
get() {
|
||||
return sharedPrefs.getBoolean(Keys.KEY_COLORIZE_NOTIFICATION, true)
|
||||
}
|
||||
|
||||
val useAltNotifAction: Boolean
|
||||
get() {
|
||||
return sharedPrefs.getBoolean(Keys.KEY_USE_ALT_NOTIFICATION_ACTION, false)
|
||||
}
|
||||
|
||||
var librarySortMode: SortMode
|
||||
get() {
|
||||
return SortMode.fromInt(
|
||||
|
@ -77,6 +87,15 @@ class SettingsManager private constructor(context: Context) :
|
|||
// --- OVERRIDES ---
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
when (key) {
|
||||
Keys.KEY_COLORIZE_NOTIFICATION -> callbacks.forEach {
|
||||
it.onColorizeNotifUpdate(colorizeNotif)
|
||||
}
|
||||
|
||||
Keys.KEY_USE_ALT_NOTIFICATION_ACTION -> callbacks.forEach {
|
||||
it.onNotifActionUpdate(useAltNotifAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -113,6 +132,8 @@ class SettingsManager private constructor(context: Context) :
|
|||
const val KEY_THEME = "KEY_THEME"
|
||||
const val KEY_ACCENT = "KEY_ACCENT"
|
||||
const val KEY_EDGE_TO_EDGE = "KEY_EDGE"
|
||||
const val KEY_COLORIZE_NOTIFICATION = "KEY_COLOR_NOTIF"
|
||||
const val KEY_USE_ALT_NOTIFICATION_ACTION = "KEY_ALT_NOTIF_ACTION"
|
||||
}
|
||||
|
||||
object EntryNames {
|
||||
|
@ -121,9 +142,8 @@ class SettingsManager private constructor(context: Context) :
|
|||
const val THEME_DARK = "DARK"
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for receiving some settings updates.
|
||||
* [SharedPreferences.OnSharedPreferenceChangeListener].
|
||||
*/
|
||||
interface Callback
|
||||
interface Callback {
|
||||
fun onColorizeNotifUpdate(doColorize: Boolean) {}
|
||||
fun onNotifActionUpdate(useAltAction: Boolean) {}
|
||||
}
|
||||
}
|
||||
|
|
10
app/src/main/res/drawable/ic_shuffle_inactive.xml
Normal file
10
app/src/main/res/drawable/ic_shuffle_inactive.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#80ffffff"
|
||||
android:pathData="M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z" />
|
||||
</vector>
|
|
@ -44,8 +44,15 @@
|
|||
<string name="setting_theme_night">Dark</string>
|
||||
<string name="setting_accent">Accent</string>
|
||||
<string name="setting_edge">Edge-To-Edge</string>
|
||||
<string name="setting_edge_desc_on">Disable edge-to-edge</string>
|
||||
<string name="setting_edge_desc_off">Enable edge-to-edge</string>
|
||||
<string name="setting_edge_desc_on">Edge-to-edge is enabled</string>
|
||||
<string name="setting_edge_desc_off">Edge-to-edge is disabled</string>
|
||||
<string name="setting_display">Display</string>
|
||||
<string name="setting_color_notif">Colorize notification</string>]
|
||||
<string name="setting_color_desc_on">Show album art on notification</string>
|
||||
<string name="setting_color_desc_off">Hide album art on notification</string>
|
||||
<string name="setting_use_alt_action">Use alternate notification action</string>
|
||||
<string name="setting_use_alt_loop">Prefer repeat mode action</string>
|
||||
<string name="setting_use_alt_shuffle">Prefer shuffle action</string>
|
||||
|
||||
<!-- Debug Namespace | Debug labels -->
|
||||
<string name="debug_state_saved">State saved</string>
|
||||
|
|
|
@ -25,6 +25,29 @@
|
|||
app:summaryOn="@string/setting_edge_desc_on"
|
||||
app:summaryOff="@string/setting_edge_desc_off"
|
||||
app:iconSpaceReserved="false"
|
||||
app:allowDividerBelow="false"
|
||||
android:defaultValue="false" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/setting_display"
|
||||
android:layout="@layout/item_header">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:key="KEY_COLOR_NOTIF"
|
||||
android:title="@string/setting_color_notif"
|
||||
app:summaryOn="@string/setting_color_desc_on"
|
||||
app:summaryOff="@string/setting_color_desc_off"
|
||||
app:iconSpaceReserved="false"
|
||||
android:defaultValue="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:key="KEY_ALT_NOTIF_ACTION"
|
||||
android:title="@string/setting_use_alt_action"
|
||||
app:iconSpaceReserved="false"
|
||||
app:summaryOn="@string/setting_use_alt_shuffle"
|
||||
app:summaryOff="@string/setting_use_alt_loop"
|
||||
android:defaultValue="false"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
Loading…
Reference in a new issue