-
Notifications
You must be signed in to change notification settings - Fork 1
/
PlayerService.kt
153 lines (130 loc) · 5.91 KB
/
PlayerService.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package ba.codingstoic.player
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.session.MediaControllerCompat
import android.support.v4.media.session.MediaSessionCompat
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.media.MediaBrowserServiceCompat
import ba.codingstoic.MainActivity
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import org.koin.android.ext.android.inject
class PlayerService : MediaBrowserServiceCompat() {
private lateinit var notificationManager: NotificationManagerCompat
private val exoPlayer: ExoPlayer by inject()
private val playbackPreparer: PlaybackPreparer by inject()
private val nowPlayingChannelId: String = "ba.codingstoic.NOW_PLAYING"
private val nowPlayingNotificationId: Int = 1
private lateinit var mediaSession: MediaSessionCompat
override fun onLoadChildren(
parentId: String,
result: Result<MutableList<MediaBrowserCompat.MediaItem>>
) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): BrowserRoot? {
return BrowserRoot("root", rootHints)
}
override fun onCreate() {
super.onCreate()
val sessionActivityPendingIntent =
packageManager?.getLaunchIntentForPackage(packageName)?.let { sessionIntent ->
PendingIntent.getActivity(this, 1, sessionIntent, 0)
}
mediaSession = MediaSessionCompat(this, "Player Service")
.apply {
setSessionActivity(sessionActivityPendingIntent)
isActive = true
}
sessionToken = mediaSession.sessionToken
notificationManager = NotificationManagerCompat.from(this)
if (shouldCreateNowPlayingChannel(notificationManager)) {
createNowPlayingChannel(notificationManager)
}
sessionToken?.let {
val playerNotificationManager = PlayerNotificationManager(this, nowPlayingChannelId,
nowPlayingNotificationId,
object : PlayerNotificationManager.MediaDescriptionAdapter {
val controller = MediaControllerCompat(this@PlayerService, it)
override fun getCurrentContentText(player: Player): String? {
val episode = player.currentTag as? Episode
return episode?.date
}
override fun getCurrentContentTitle(player: Player): String {
val episode = player.currentTag as? Episode
return episode?.title ?: "Buffering..."
}
override fun getCurrentLargeIcon(
player: Player,
callback: PlayerNotificationManager.BitmapCallback
): Bitmap? {
return controller.metadata?.description?.iconBitmap
}
override fun createCurrentContentIntent(player: Player): PendingIntent? {
return PendingIntent.getActivity(
this@PlayerService,
0,
Intent(this@PlayerService, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
}
}, object : PlayerNotificationManager.NotificationListener {
override fun onNotificationPosted(
notificationId: Int,
notification: Notification,
ongoing: Boolean
) {
if (ongoing) {
ContextCompat.startForegroundService(
applicationContext,
Intent(applicationContext, this@PlayerService.javaClass)
)
startForeground(nowPlayingNotificationId, notification)
} else {
stopForeground(false)
}
}
})
playerNotificationManager.setPlayer(exoPlayer)
playerNotificationManager.setMediaSessionToken(it)
}
MediaSessionConnector(mediaSession).also {
it.setPlayer(exoPlayer)
it.setPlaybackPreparer(playbackPreparer)
}
}
private fun shouldCreateNowPlayingChannel(notificationManager: NotificationManagerCompat) =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !nowPlayingChannelExists(
notificationManager
)
@RequiresApi(Build.VERSION_CODES.O)
private fun nowPlayingChannelExists(notificationManager: NotificationManagerCompat) =
notificationManager.getNotificationChannel(nowPlayingChannelId) != null
@RequiresApi(Build.VERSION_CODES.O)
private fun createNowPlayingChannel(notificationManager: NotificationManagerCompat) {
val notificationChannel = NotificationChannel(
nowPlayingChannelId,
"Now playing channel",
NotificationManager.IMPORTANCE_LOW
)
.apply {
description = "Now playing channel"
}
notificationManager.createNotificationChannel(notificationChannel)
}
}