-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPillarboxMediaLibraryService.kt
125 lines (116 loc) · 4.06 KB
/
PillarboxMediaLibraryService.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
/*
* Copyright (c) SRG SSR. All rights reserved.
* License information is available from the LICENSE file.
*/
package ch.srgssr.pillarbox.player.service
import android.app.PendingIntent
import android.content.Intent
import androidx.media3.common.C
import androidx.media3.common.Player
import androidx.media3.session.MediaLibraryService
import androidx.media3.session.MediaSession
import ch.srgssr.pillarbox.player.PillarboxPlayer
import ch.srgssr.pillarbox.player.utils.PendingIntentUtils
/**
* `PillarboxMediaLibraryService` implementation of [MediaLibraryService].
* It is the recommended way to make background playback for Android and sharing content with Android Auto.
*
* It handles only one [MediaSession] with one [PillarboxPlayer].
*
* Usage:
* Add these permissions inside your manifest:
*
* ```xml
* <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
* <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
* ```
*
* And add your `PlaybackService` to the application manifest as follow:
*
* ```xml
* <meta-data android:name="com.google.android.gms.car.application" android:resource="@xml/automotive_app_desc" />
*
* <service
* android:name=".service.DemoMediaLibraryService"
* android:enabled="true"
* android:exported="true"
* android:foregroundServiceType="mediaPlayback">
* <intent-filter>
* <action android:name="androidx.media3.session.MediaLibraryService" />
* <action android:name="android.media.browse.MediaBrowserService" />
* </intent-filter>
* </service>
* ```
*
* Use [MediaBrowser.Builder][androidx.media3.session.MediaBrowser.Builder] to connect this Service to a `MediaBrowser`:
* ```kotlin
* val sessionToken = SessionToken(context, ComponentName(application, DemoMediaLibraryService::class.java))
* val listenableFuture = MediaBrowser.Builder(context, sessionToken)
* .setListener(MediaBrowser.Listener()...) // Optional
* .buildAsync()
* coroutineScope.launch(){
* val mediaBrowser = listenableFuture.await() // suspend method to retrieve MediaBrowser
* doSomethingWith(mediaBrowser)
* }
* ...
* mediaBrowser.release() // when MediaBrowser no more needed.
* ```
*/
abstract class PillarboxMediaLibraryService : MediaLibraryService() {
private var player: Player? = null
private var mediaSession: MediaLibrarySession? = null
/**
* Release on task removed
*/
var releaseOnTaskRemoved = true
/**
* Set player to use with this Service.
*/
fun setPlayer(player: PillarboxPlayer, callback: MediaLibrarySession.Callback) {
if (this.player == null) {
this.player = player
player.setWakeMode(C.WAKE_MODE_NETWORK)
player.setHandleAudioFocus(true)
val builder = MediaLibrarySession.Builder(this, player, callback)
.setId(packageName)
sessionActivity()?.let {
builder.setSessionActivity(it)
}
mediaSession = builder.build()
}
}
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaLibrarySession? {
return mediaSession
}
/**
* Session activity use with [mediaSession] called when [setPlayer]
*/
open fun sessionActivity(): PendingIntent? = PendingIntentUtils.getDefaultPendingIntent(this)
/**
* Release the player and the MediaSession.
* The [mediaSession] is set to null after this call
*
* called automatically in [onDestroy] and [onTaskRemoved] is [releaseOnTaskRemoved] = true
*/
open fun release() {
mediaSession?.run {
player.release()
release()
mediaSession = null
}
}
override fun onDestroy() {
release()
super.onDestroy()
}
/**
* We choose to stop playback when user remove application from the tasks
*/
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
if (releaseOnTaskRemoved) {
release()
stopSelf()
}
}
}