Add ability to exit notification
Add an exit button to the notification so that one can exit it.
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
|
@ -1,7 +1,10 @@
|
|||
package org.oxycblt.auxio
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
|
|
@ -33,6 +33,8 @@ class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
|||
findNavController().navigate(
|
||||
LoadingFragmentDirections.actionToMain()
|
||||
)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
val binding = FragmentLoadingBinding.inflate(inflater)
|
||||
|
|
|
@ -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
|
||||
|
@ -26,7 +27,7 @@ object NotificationUtils {
|
|||
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"
|
||||
const val ACTION_SHUFFLE = "ACTION_AUXIO_SHUFFLE"
|
||||
const val ACTION_EXIT = "ACTION_AUXIO_EXIT"
|
||||
}
|
||||
|
||||
fun NotificationManager.createMediaNotification(
|
||||
|
@ -51,7 +52,9 @@ fun NotificationManager.createMediaNotification(
|
|||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
|
||||
// TODO: It would be cool if the notification intent took you to the now playing screen.
|
||||
// TODO: Things that probably aren't possible but would be nice
|
||||
// - Swipe to close instead of a button to press
|
||||
// - Playing intent takes you to now playing screen instead of elsewhere
|
||||
return NotificationCompat.Builder(context, NotificationUtils.CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_song)
|
||||
.setStyle(
|
||||
|
@ -67,7 +70,7 @@ fun NotificationManager.createMediaNotification(
|
|||
.addAction(newAction(NotificationUtils.ACTION_SKIP_PREV, context))
|
||||
.addAction(newAction(NotificationUtils.ACTION_PLAY_PAUSE, context))
|
||||
.addAction(newAction(NotificationUtils.ACTION_SKIP_NEXT, context))
|
||||
.addAction(newAction(NotificationUtils.ACTION_SHUFFLE, context))
|
||||
.addAction(newAction(NotificationUtils.ACTION_EXIT, context))
|
||||
.setSubText(context.getString(R.string.title_playback))
|
||||
.setContentIntent(mainIntent)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
|
@ -86,19 +89,16 @@ fun NotificationCompat.Builder.setMetadata(song: Song, context: Context, onDone:
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun NotificationCompat.Builder.updateLoop(context: Context) {
|
||||
mActions[0] = newAction(NotificationUtils.ACTION_LOOP, context)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun NotificationCompat.Builder.updatePlaying(context: Context) {
|
||||
mActions[2] = newAction(NotificationUtils.ACTION_PLAY_PAUSE, context)
|
||||
|
||||
setOngoing(PlaybackStateManager.getInstance().isPlaying)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun NotificationCompat.Builder.updateShuffle(context: Context) {
|
||||
mActions[4] = newAction(NotificationUtils.ACTION_SHUFFLE, context)
|
||||
fun NotificationCompat.Builder.updateLoop(context: Context) {
|
||||
mActions[0] = newAction(NotificationUtils.ACTION_LOOP, context)
|
||||
}
|
||||
|
||||
private fun newAction(action: String, context: Context): NotificationCompat.Action {
|
||||
|
@ -113,9 +113,7 @@ private fun newAction(action: String, context: Context): NotificationCompat.Acti
|
|||
}
|
||||
}
|
||||
|
||||
NotificationUtils.ACTION_SKIP_PREV -> {
|
||||
R.drawable.ic_skip_prev
|
||||
}
|
||||
NotificationUtils.ACTION_SKIP_PREV -> R.drawable.ic_skip_prev
|
||||
|
||||
NotificationUtils.ACTION_PLAY_PAUSE -> {
|
||||
if (playbackManager.isPlaying) {
|
||||
|
@ -125,18 +123,9 @@ private fun newAction(action: String, context: Context): NotificationCompat.Acti
|
|||
}
|
||||
}
|
||||
|
||||
NotificationUtils.ACTION_SKIP_NEXT -> {
|
||||
R.drawable.ic_skip_next
|
||||
}
|
||||
|
||||
NotificationUtils.ACTION_SHUFFLE -> {
|
||||
if (playbackManager.isShuffling) {
|
||||
R.drawable.ic_shuffle
|
||||
} else {
|
||||
R.drawable.ic_shuffle_disabled
|
||||
}
|
||||
}
|
||||
NotificationUtils.ACTION_SKIP_NEXT -> R.drawable.ic_skip_next
|
||||
|
||||
NotificationUtils.ACTION_EXIT -> R.drawable.ic_exit
|
||||
else -> R.drawable.ic_play
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.content.Intent
|
|||
import android.content.IntentFilter
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.media.AudioManager
|
||||
import android.os.Binder
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.os.Parcelable
|
||||
|
@ -56,6 +57,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
|
||||
private var changeIsFromAudioFocus = true
|
||||
private var isForeground = false
|
||||
private var isDetachedFromUI = false
|
||||
|
||||
private val serviceJob = Job()
|
||||
private val serviceScope = CoroutineScope(
|
||||
|
@ -70,7 +72,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? = null
|
||||
override fun onBind(intent: Intent): IBinder? = LocalBinder()
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
@ -113,7 +115,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
addAction(NotificationUtils.ACTION_SKIP_PREV)
|
||||
addAction(NotificationUtils.ACTION_PLAY_PAUSE)
|
||||
addAction(NotificationUtils.ACTION_SKIP_NEXT)
|
||||
addAction(NotificationUtils.ACTION_SHUFFLE)
|
||||
addAction(NotificationUtils.ACTION_EXIT)
|
||||
|
||||
addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
|
||||
addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
|
||||
|
@ -229,19 +231,11 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
startPollingPosition()
|
||||
} else {
|
||||
player.pause()
|
||||
|
||||
notification.updatePlaying(this)
|
||||
startForegroundOrNotify()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onShuffleUpdate(isShuffling: Boolean) {
|
||||
changeIsFromAudioFocus = false
|
||||
|
||||
notification.updateShuffle(this)
|
||||
startForegroundOrNotify()
|
||||
}
|
||||
|
||||
override fun onLoopUpdate(mode: LoopMode) {
|
||||
changeIsFromAudioFocus = false
|
||||
|
||||
|
@ -390,8 +384,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
NotificationUtils.ACTION_PLAY_PAUSE ->
|
||||
playbackManager.setPlayingStatus(!playbackManager.isPlaying)
|
||||
NotificationUtils.ACTION_SKIP_NEXT -> playbackManager.next()
|
||||
NotificationUtils.ACTION_SHUFFLE ->
|
||||
playbackManager.setShuffleStatus(!playbackManager.isShuffling)
|
||||
NotificationUtils.ACTION_EXIT -> stop()
|
||||
|
||||
BluetoothDevice.ACTION_ACL_CONNECTED -> resume()
|
||||
BluetoothDevice.ACTION_ACL_DISCONNECTED -> pause()
|
||||
|
@ -430,6 +423,15 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
playbackManager.setPlayingStatus(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stop() {
|
||||
playbackManager.setPlayingStatus(false)
|
||||
stopForegroundAndNotification()
|
||||
}
|
||||
}
|
||||
|
||||
inner class LocalBinder : Binder() {
|
||||
fun getService() = this@PlaybackService
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -4,24 +4,29 @@
|
|||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:pathData="M 54.000004,28.557237 V 58.38181 c -1.667916,-0.96117 -3.590261,-1.554837 -5.65395,-1.554837 -6.247608,0 -11.307896,5.060283 -11.307896,11.307898 0,6.24761 5.060288,11.307892 11.307896,11.307892 6.24761,0 11.307898,-5.06028 11.307898,-11.307891 V 39.865131 H 70.961841 V 28.557237 Z"
|
||||
android:strokeWidth="0.890156"
|
||||
android:strokeColor="#ffffff">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="60"
|
||||
android:startY="61.5"
|
||||
android:endX="64.75"
|
||||
android:endY="28.5"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#2196f3"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#90caf9"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
||||
<group android:scaleX="0.95"
|
||||
android:scaleY="0.95"
|
||||
android:translateX="2.7"
|
||||
android:translateY="2.7">
|
||||
<path
|
||||
android:pathData="M 54.000004,28.557237 V 58.38181 c -1.667916,-0.96117 -3.590261,-1.554837 -5.65395,-1.554837 -6.247608,0 -11.307896,5.060283 -11.307896,11.307898 0,6.24761 5.060288,11.307892 11.307896,11.307892 6.24761,0 11.307898,-5.06028 11.307898,-11.307891 V 39.865131 H 70.961841 V 28.557237 Z"
|
||||
android:strokeWidth="0.890156"
|
||||
android:strokeColor="#ffffff">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="60"
|
||||
android:startY="61.5"
|
||||
android:endX="64.75"
|
||||
android:endY="28.5"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#2196f3"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#90caf9"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_exit.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="@android:color/white"
|
||||
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||
</vector>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1,021 B |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 8.5 KiB |