@javascriptcommon/react-native-track-player 1.2.9 → 1.2.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +61 -4
- package/android/src/main/AndroidManifest.xml +2 -4
- package/android/src/main/ic_home-playstore.png +0 -0
- package/android/src/main/ic_repeat-playstore.png +0 -0
- package/android/src/main/ic_repeat_50-playstore.png +0 -0
- package/android/src/main/ic_shuffle-playstore.png +0 -0
- package/android/src/main/ic_shuffle_50-playstore.png +0 -0
- package/android/src/main/ic_shuffle_sm-playstore.png +0 -0
- package/android/src/main/ic_stop-playstore.png +0 -0
- package/android/src/main/ic_test-playstore.png +0 -0
- package/android/src/main/java/com/guichaguri/trackplayer/{service/HeadlessJsMediaService.java → HeadlessJsMediaService.java} +83 -32
- package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.kt +25 -0
- package/android/src/main/java/com/guichaguri/trackplayer/extensions/AudioPlayerStateExt.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/EventHolder.kt +30 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/NotificationEventHolder.kt +20 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/PlayerEventHolder.kt +111 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AAMediaSessionCallback.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioContentType.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItem.kt +66 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItemTransitionReason.kt +33 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioPlayerState.kt +30 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/BufferConfig.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/CacheConfig.kt +17 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/Capability.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/FocusChangeData.kt +3 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/MediaSessionCallback.kt +17 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationConfig.kt +43 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationMetadata.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationState.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayWhenReadyChangeData.kt +5 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackEndedReason.kt +5 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackError.kt +6 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackMetadata.kt +200 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerConfig.kt +33 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerOptions.kt +9 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PositionChangedReason.kt +39 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/QueuedPlayerOptions.kt +49 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/notification/NotificationManager.kt +678 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/AudioPlayer.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/BaseAudioPlayer.kt +864 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/QueuedAudioPlayer.kt +269 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/MediaSourceExt.kt +35 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/PlayerCache.kt +26 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/utils/Utils.kt +12 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/MetadataAdapter.kt +224 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/State.kt +13 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/Track.kt +120 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/TrackAudioItem.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/TrackType.kt +11 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/AutoConnectionDetector.kt +151 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.kt +66 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.kt +1192 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/BundleUtils.kt +117 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.kt +31 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.kt +347 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.kt +1268 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.kt +228 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.kt +141 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.kt +396 -0
- package/android/src/main/res/drawable-hdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_home.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/raw/silent_5_seconds.mp3 +0 -0
- package/android/src/main/res/strings.xml +6 -0
- package/android/src/main/res/values/strings.xml +6 -0
- package/index.d.ts +62 -1
- package/lib/index.js +10 -9
- package/package.json +1 -1
- package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +0 -28
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +0 -55
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +0 -298
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +0 -47
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +0 -383
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +0 -271
- package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +0 -243
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +0 -148
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +0 -379
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +0 -141
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +0 -35
- package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_logo.png +0 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
package com.guichaguri.trackplayer.service.metadata
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.app.AlarmManager
|
|
5
|
+
import android.app.Notification
|
|
6
|
+
import android.app.NotificationManager
|
|
7
|
+
import android.app.PendingIntent
|
|
8
|
+
import android.content.Context
|
|
9
|
+
import android.content.Intent
|
|
10
|
+
import android.content.pm.ServiceInfo
|
|
11
|
+
import android.graphics.Bitmap
|
|
12
|
+
import android.net.Uri
|
|
13
|
+
import android.os.Build
|
|
14
|
+
import android.os.Bundle
|
|
15
|
+
import android.support.v4.media.MediaMetadataCompat
|
|
16
|
+
import android.support.v4.media.RatingCompat
|
|
17
|
+
import android.support.v4.media.session.MediaSessionCompat
|
|
18
|
+
import android.support.v4.media.session.PlaybackStateCompat
|
|
19
|
+
import androidx.core.app.NotificationCompat
|
|
20
|
+
import androidx.media.session.MediaButtonReceiver
|
|
21
|
+
import com.bumptech.glide.Glide
|
|
22
|
+
import com.bumptech.glide.request.target.SimpleTarget
|
|
23
|
+
import com.bumptech.glide.request.transition.Transition
|
|
24
|
+
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper
|
|
25
|
+
import com.guichaguri.trackplayer.R
|
|
26
|
+
import com.guichaguri.trackplayer.service.MusicManager
|
|
27
|
+
import com.guichaguri.trackplayer.service.MusicService
|
|
28
|
+
import com.guichaguri.trackplayer.service.Utils
|
|
29
|
+
import com.guichaguri.trackplayer.model.Track
|
|
30
|
+
import java.util.*
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @author Guichaguri
|
|
34
|
+
*/
|
|
35
|
+
class MetadataManager(service: MusicService, manager: MusicManager) {
|
|
36
|
+
private val service: MusicService
|
|
37
|
+
private val manager: MusicManager
|
|
38
|
+
val session: MediaSessionCompat
|
|
39
|
+
var ratingType = RatingCompat.RATING_NONE
|
|
40
|
+
private set
|
|
41
|
+
var jumpInterval = 15
|
|
42
|
+
private set
|
|
43
|
+
private var actions: Long = 0
|
|
44
|
+
private var compactActions: Long = 0
|
|
45
|
+
private var artworkTarget: SimpleTarget<Bitmap>? = null
|
|
46
|
+
private val builder: NotificationCompat.Builder
|
|
47
|
+
var optionsBundle: Bundle? = null
|
|
48
|
+
private set
|
|
49
|
+
private var hideArtworkLockScreenBackground = false
|
|
50
|
+
private var previousAction: NotificationCompat.Action? = null
|
|
51
|
+
private var rewindAction: NotificationCompat.Action? = null
|
|
52
|
+
private var playAction: NotificationCompat.Action? = null
|
|
53
|
+
private var pauseAction: NotificationCompat.Action? = null
|
|
54
|
+
private var stopAction: NotificationCompat.Action? = null
|
|
55
|
+
private var forwardAction: NotificationCompat.Action? = null
|
|
56
|
+
private var nextAction: NotificationCompat.Action? = null
|
|
57
|
+
|
|
58
|
+
init {
|
|
59
|
+
this.service = service
|
|
60
|
+
this.manager = manager
|
|
61
|
+
val channel: String = Utils.getNotificationChannel(service as Context)
|
|
62
|
+
builder = NotificationCompat.Builder(service, channel)
|
|
63
|
+
session = MediaSessionCompat(service, "TrackPlayer", null, null)
|
|
64
|
+
session.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS or MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS)
|
|
65
|
+
session.setCallback(ButtonEvents(service, manager))
|
|
66
|
+
val context: Context = service.getApplicationContext()
|
|
67
|
+
val packageName = context.packageName
|
|
68
|
+
var openApp = context.packageManager.getLaunchIntentForPackage(packageName)
|
|
69
|
+
if (openApp == null) {
|
|
70
|
+
openApp = Intent()
|
|
71
|
+
openApp.setPackage(packageName)
|
|
72
|
+
openApp.addCategory(Intent.CATEGORY_LAUNCHER)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Prevent the app from launching a new instance
|
|
76
|
+
openApp.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
|
77
|
+
|
|
78
|
+
// Add the Uri data so apps can identify that it was a notification click
|
|
79
|
+
openApp.action = Intent.ACTION_VIEW
|
|
80
|
+
openApp.data = Uri.parse("trackplayer://notification.click")
|
|
81
|
+
val flags =
|
|
82
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE else PendingIntent.FLAG_UPDATE_CURRENT
|
|
83
|
+
builder.setContentIntent(PendingIntent.getActivity(context, 0, openApp, flags))
|
|
84
|
+
|
|
85
|
+
val resId = context.resources.getIdentifier("track_player_logo", "drawable", context.packageName)
|
|
86
|
+
val logo = if (resId != 0) resId else R.drawable.ic_play
|
|
87
|
+
builder.setSmallIcon(logo)
|
|
88
|
+
|
|
89
|
+
builder.setCategory(NotificationCompat.CATEGORY_TRANSPORT)
|
|
90
|
+
|
|
91
|
+
// Stops the playback when the notification is swiped away
|
|
92
|
+
builder.setDeleteIntent(
|
|
93
|
+
MediaButtonReceiver.buildMediaButtonPendingIntent(
|
|
94
|
+
service,
|
|
95
|
+
PlaybackStateCompat.ACTION_STOP
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// Make it visible in the lockscreen
|
|
100
|
+
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Updates the metadata options
|
|
105
|
+
* @param options The options
|
|
106
|
+
*/
|
|
107
|
+
fun updateOptions(options: Bundle) {
|
|
108
|
+
optionsBundle = options
|
|
109
|
+
val capabilities: List<Int>? = options.getIntegerArrayList("capabilities")
|
|
110
|
+
var notification: List<Int>? = options.getIntegerArrayList("notificationCapabilities")
|
|
111
|
+
val compact: List<Int>? = options.getIntegerArrayList("compactCapabilities")
|
|
112
|
+
hideArtworkLockScreenBackground = options.getBoolean("hideArtworkLockScreenBackground")
|
|
113
|
+
actions = 0
|
|
114
|
+
compactActions = 0
|
|
115
|
+
if (capabilities != null) {
|
|
116
|
+
// Create the actions mask
|
|
117
|
+
for (cap in capabilities) actions = actions or cap.toLong()
|
|
118
|
+
|
|
119
|
+
// If there is no notification capabilities defined, we'll show all capabilities available
|
|
120
|
+
if (notification == null) notification = capabilities
|
|
121
|
+
|
|
122
|
+
// Initialize all actions based on the options
|
|
123
|
+
previousAction = createAction(
|
|
124
|
+
notification, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS, "Previous",
|
|
125
|
+
getIcon(options, "previousIcon", R.drawable.ic_previous)
|
|
126
|
+
)
|
|
127
|
+
rewindAction = createAction(
|
|
128
|
+
notification, PlaybackStateCompat.ACTION_REWIND, "Rewind",
|
|
129
|
+
getIcon(options, "rewindIcon", R.drawable.ic_rewind)
|
|
130
|
+
)
|
|
131
|
+
playAction = createAction(
|
|
132
|
+
notification, PlaybackStateCompat.ACTION_PLAY, "Play",
|
|
133
|
+
getIcon(options, "playIcon", R.drawable.ic_play)
|
|
134
|
+
)
|
|
135
|
+
pauseAction = createAction(
|
|
136
|
+
notification, PlaybackStateCompat.ACTION_PAUSE, "Pause",
|
|
137
|
+
getIcon(options, "pauseIcon", R.drawable.ic_pause)
|
|
138
|
+
)
|
|
139
|
+
stopAction = createAction(
|
|
140
|
+
notification, PlaybackStateCompat.ACTION_STOP, "Stop",
|
|
141
|
+
getIcon(options, "stopIcon", R.drawable.ic_stop)
|
|
142
|
+
)
|
|
143
|
+
forwardAction = createAction(
|
|
144
|
+
notification, PlaybackStateCompat.ACTION_FAST_FORWARD, "Forward",
|
|
145
|
+
getIcon(options, "forwardIcon", R.drawable.ic_forward)
|
|
146
|
+
)
|
|
147
|
+
nextAction = createAction(
|
|
148
|
+
notification, PlaybackStateCompat.ACTION_SKIP_TO_NEXT, "Next",
|
|
149
|
+
getIcon(options, "nextIcon", R.drawable.ic_next)
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
// Update the action mask for the compact view
|
|
153
|
+
if (compact != null) {
|
|
154
|
+
for (cap in compact) compactActions = compactActions or cap.toLong()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Update the color
|
|
159
|
+
builder.color = Utils.getInt(options, "color", NotificationCompat.COLOR_DEFAULT)
|
|
160
|
+
|
|
161
|
+
// Update the icon
|
|
162
|
+
val resId = service.applicationContext.resources.getIdentifier("track_player_logo", "drawable", service.applicationContext.packageName)
|
|
163
|
+
val logo = if (resId != 0) resId else R.drawable.ic_play
|
|
164
|
+
builder.setSmallIcon(getIcon(options, "icon", logo))
|
|
165
|
+
|
|
166
|
+
// Update the jump interval
|
|
167
|
+
jumpInterval = Utils.getInt(options, "jumpInterval", 15)
|
|
168
|
+
|
|
169
|
+
// Update the rating type
|
|
170
|
+
ratingType = Utils.getInt(options, "ratingType", RatingCompat.RATING_NONE)
|
|
171
|
+
session.setRatingType(ratingType)
|
|
172
|
+
updateNotification()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
fun removeNotifications() {
|
|
176
|
+
val ns = Context.NOTIFICATION_SERVICE
|
|
177
|
+
val context: Context = service.getApplicationContext()
|
|
178
|
+
val manager = context.getSystemService(ns) as NotificationManager
|
|
179
|
+
manager.cancelAll()
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Updates the artwork
|
|
184
|
+
* @param bitmap The new artwork
|
|
185
|
+
*/
|
|
186
|
+
protected fun updateArtwork(bitmap: Bitmap?) {
|
|
187
|
+
val track: Track =
|
|
188
|
+
manager.currentTrack ?: return
|
|
189
|
+
val metadata = track.toMediaMetadata()
|
|
190
|
+
metadata.putBitmap(
|
|
191
|
+
if (hideArtworkLockScreenBackground) MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON else MediaMetadataCompat.METADATA_KEY_ART,
|
|
192
|
+
bitmap
|
|
193
|
+
)
|
|
194
|
+
builder.setLargeIcon(bitmap)
|
|
195
|
+
session.setMetadata(metadata.build())
|
|
196
|
+
updateNotification()
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private fun getCroppedBitmap(bitmap: Bitmap): Bitmap {
|
|
200
|
+
val output = if (bitmap.width >= bitmap.height) {
|
|
201
|
+
Bitmap.createBitmap(bitmap, (bitmap.width - bitmap.height) / 2, 0, bitmap.height, bitmap.height)
|
|
202
|
+
} else {
|
|
203
|
+
Bitmap.createBitmap(bitmap, 0, (bitmap.height - bitmap.width) / 2, bitmap.width, bitmap.width)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return output
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Updates the current track
|
|
211
|
+
* @param track The new track
|
|
212
|
+
*/
|
|
213
|
+
fun updateMetadata(track: Track) {
|
|
214
|
+
val metadata = track.toMediaMetadata()
|
|
215
|
+
|
|
216
|
+
val rm = Glide.with(service.applicationContext)
|
|
217
|
+
artworkTarget?.let { rm.clear(it) }
|
|
218
|
+
|
|
219
|
+
if (track.artwork != null) {
|
|
220
|
+
artworkTarget = rm.asBitmap()
|
|
221
|
+
.load(track.artwork)
|
|
222
|
+
.into(object : SimpleTarget<Bitmap>() {
|
|
223
|
+
override fun onResourceReady(
|
|
224
|
+
resource: Bitmap,
|
|
225
|
+
transition: Transition<in Bitmap>?
|
|
226
|
+
) {
|
|
227
|
+
try {
|
|
228
|
+
try {
|
|
229
|
+
val bitmap = getCroppedBitmap(resource)
|
|
230
|
+
metadata.putBitmap(
|
|
231
|
+
if (hideArtworkLockScreenBackground)
|
|
232
|
+
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON
|
|
233
|
+
else MediaMetadataCompat.METADATA_KEY_ART, bitmap
|
|
234
|
+
)
|
|
235
|
+
builder.setLargeIcon(bitmap)
|
|
236
|
+
|
|
237
|
+
session.setMetadata(metadata.build())
|
|
238
|
+
updateNotification()
|
|
239
|
+
} catch (_: OutOfMemoryError) {}
|
|
240
|
+
} catch (_: Exception) {}
|
|
241
|
+
artworkTarget = null
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
builder.setContentTitle(track.title)
|
|
247
|
+
builder.setContentText(track.artist)
|
|
248
|
+
builder.setSubText(track.album)
|
|
249
|
+
|
|
250
|
+
session.setMetadata(metadata.build())
|
|
251
|
+
updateNotification()
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Updates the playback state
|
|
257
|
+
* @param state The player
|
|
258
|
+
*/
|
|
259
|
+
@SuppressLint("RestrictedApi")
|
|
260
|
+
fun updatePlayback(state: Int, position: Long, bufferedPosition: Long, rate: Int) {
|
|
261
|
+
val playing: Boolean = Utils.isPlaying(state)
|
|
262
|
+
val compact: MutableList<Int> = ArrayList()
|
|
263
|
+
builder.mActions.clear()
|
|
264
|
+
|
|
265
|
+
// Adds the media buttons to the notification
|
|
266
|
+
addAction(previousAction, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS, compact)
|
|
267
|
+
addAction(rewindAction, PlaybackStateCompat.ACTION_REWIND, compact)
|
|
268
|
+
if (playing) {
|
|
269
|
+
addAction(pauseAction, PlaybackStateCompat.ACTION_PAUSE, compact)
|
|
270
|
+
} else {
|
|
271
|
+
addAction(playAction, PlaybackStateCompat.ACTION_PLAY, compact)
|
|
272
|
+
}
|
|
273
|
+
addAction(stopAction, PlaybackStateCompat.ACTION_STOP, compact)
|
|
274
|
+
addAction(forwardAction, PlaybackStateCompat.ACTION_FAST_FORWARD, compact)
|
|
275
|
+
addAction(nextAction, PlaybackStateCompat.ACTION_SKIP_TO_NEXT, compact)
|
|
276
|
+
|
|
277
|
+
// Prevent the media style from being used in older Huawei devices that don't support custom styles
|
|
278
|
+
if (!Build.MANUFACTURER.lowercase(Locale.getDefault())
|
|
279
|
+
.contains("huawei") || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
|
280
|
+
) {
|
|
281
|
+
val style = androidx.media.app.NotificationCompat.MediaStyle()
|
|
282
|
+
if (playing) {
|
|
283
|
+
style.setShowCancelButton(false)
|
|
284
|
+
} else {
|
|
285
|
+
// Shows the cancel button on pre-lollipop versions due to a bug
|
|
286
|
+
style.setShowCancelButton(true)
|
|
287
|
+
style.setCancelButtonIntent(
|
|
288
|
+
MediaButtonReceiver.buildMediaButtonPendingIntent(
|
|
289
|
+
service,
|
|
290
|
+
PlaybackStateCompat.ACTION_STOP
|
|
291
|
+
)
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Links the media session
|
|
296
|
+
style.setMediaSession(session.sessionToken)
|
|
297
|
+
|
|
298
|
+
// Updates the compact media buttons for the notification
|
|
299
|
+
if (!compact.isEmpty()) {
|
|
300
|
+
val compactIndexes = IntArray(compact.size)
|
|
301
|
+
for (i in compact.indices) compactIndexes[i] = compact[i]
|
|
302
|
+
style.setShowActionsInCompactView(*compactIndexes)
|
|
303
|
+
}
|
|
304
|
+
builder.setStyle(style)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Updates the media session state
|
|
308
|
+
val pb = PlaybackStateCompat.Builder()
|
|
309
|
+
pb.setActions(actions)
|
|
310
|
+
pb.setState(state, position, rate.toFloat())
|
|
311
|
+
pb.setBufferedPosition(bufferedPosition)
|
|
312
|
+
session.setPlaybackState(pb.build())
|
|
313
|
+
updateNotification()
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
fun setActive(active: Boolean) {
|
|
317
|
+
session.isActive = active
|
|
318
|
+
updateNotification()
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fun destroy(intentToStop: Boolean?) {
|
|
322
|
+
service.stopForeground(false)
|
|
323
|
+
if (!intentToStop!!) {
|
|
324
|
+
updateNotification()
|
|
325
|
+
} else {
|
|
326
|
+
session.isActive = false
|
|
327
|
+
session.release()
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private fun updateNotification() {
|
|
332
|
+
try {
|
|
333
|
+
if (session.isActive) {
|
|
334
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
335
|
+
service.startForeground(
|
|
336
|
+
1, builder
|
|
337
|
+
.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
|
|
338
|
+
.setPriority(NotificationCompat.PRIORITY_MAX)
|
|
339
|
+
.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
|
|
340
|
+
)
|
|
341
|
+
} else {
|
|
342
|
+
service.startForeground(
|
|
343
|
+
1, builder
|
|
344
|
+
.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
|
|
345
|
+
.setPriority(NotificationCompat.PRIORITY_MAX)
|
|
346
|
+
.build()
|
|
347
|
+
)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
} catch (ex: Exception) {
|
|
351
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
352
|
+
val context: Context = service.getApplicationContext()
|
|
353
|
+
val mgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
|
354
|
+
val i = Intent(context, MusicService::class.java)
|
|
355
|
+
val pi = PendingIntent.getForegroundService(
|
|
356
|
+
context,
|
|
357
|
+
0,
|
|
358
|
+
i,
|
|
359
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
360
|
+
)
|
|
361
|
+
val calendar = Calendar.getInstance()
|
|
362
|
+
calendar.timeInMillis = System.currentTimeMillis()
|
|
363
|
+
calendar.add(Calendar.MILLISECOND, 200)
|
|
364
|
+
mgr[AlarmManager.RTC_WAKEUP, calendar.timeInMillis] = pi
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
private fun getIcon(options: Bundle, propertyName: String, defaultIcon: Int): Int {
|
|
370
|
+
if (!options.containsKey(propertyName)) return defaultIcon
|
|
371
|
+
val bundle = options.getBundle(propertyName) ?: return defaultIcon
|
|
372
|
+
val helper = ResourceDrawableIdHelper.getInstance()
|
|
373
|
+
val icon = helper.getResourceDrawableId(service, bundle.getString("uri"))
|
|
374
|
+
return if (icon == 0) defaultIcon else icon
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
private fun createAction(
|
|
378
|
+
caps: List<Int>,
|
|
379
|
+
action: Long,
|
|
380
|
+
title: String,
|
|
381
|
+
icon: Int
|
|
382
|
+
): NotificationCompat.Action? {
|
|
383
|
+
return if (!caps.contains(action.toInt())) null else NotificationCompat.Action(
|
|
384
|
+
icon,
|
|
385
|
+
title,
|
|
386
|
+
MediaButtonReceiver.buildMediaButtonPendingIntent(service, action)
|
|
387
|
+
)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
@SuppressLint("RestrictedApi")
|
|
391
|
+
private fun addAction(action: NotificationCompat.Action?, id: Long, compact: MutableList<Int>) {
|
|
392
|
+
if (action == null) return
|
|
393
|
+
if (compactActions and id != 0L) compact.add(builder.mActions.size)
|
|
394
|
+
builder.mActions.add(action)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -25,7 +25,14 @@ declare namespace RNTrackPlayer {
|
|
|
25
25
|
| "remote-like"
|
|
26
26
|
| "remote-dislike"
|
|
27
27
|
| "remote-bookmark"
|
|
28
|
-
| "remote-play-pause"
|
|
28
|
+
| "remote-play-pause"
|
|
29
|
+
| "car-connection-update"
|
|
30
|
+
| "remote-play-queue"
|
|
31
|
+
| "remote-shuffle"
|
|
32
|
+
| "remote-repeat"
|
|
33
|
+
| "remote-track-status"
|
|
34
|
+
| "remote-browse"
|
|
35
|
+
| "remote-search";
|
|
29
36
|
|
|
30
37
|
export type TrackType =
|
|
31
38
|
| "default"
|
|
@@ -39,6 +46,17 @@ declare namespace RNTrackPlayer {
|
|
|
39
46
|
type RatingType = string | number;
|
|
40
47
|
type Capability = string | number;
|
|
41
48
|
|
|
49
|
+
type AndroidAutoAction =
|
|
50
|
+
| "shuffle-on"
|
|
51
|
+
| "shuffle-off"
|
|
52
|
+
| "repeat-on"
|
|
53
|
+
| "repeat-off"
|
|
54
|
+
| "heart"
|
|
55
|
+
| "heart-outlined"
|
|
56
|
+
| "clock"
|
|
57
|
+
| "arrow-down-circle"
|
|
58
|
+
| "md-close";
|
|
59
|
+
|
|
42
60
|
type EventHandler = (type: EventType, ...args: any[]) => void;
|
|
43
61
|
export function registerEventHandler(handler: EventHandler): void;
|
|
44
62
|
|
|
@@ -100,6 +118,8 @@ declare namespace RNTrackPlayer {
|
|
|
100
118
|
notificationCapabilities?: Capability[];
|
|
101
119
|
compactCapabilities?: Capability[];
|
|
102
120
|
|
|
121
|
+
customActions?: AndroidAutoAction[]
|
|
122
|
+
|
|
103
123
|
icon?: ResourceObject;
|
|
104
124
|
playIcon?: ResourceObject;
|
|
105
125
|
pauseIcon?: ResourceObject;
|
|
@@ -113,19 +133,60 @@ declare namespace RNTrackPlayer {
|
|
|
113
133
|
placeholderImage?: ResourceObject;
|
|
114
134
|
}
|
|
115
135
|
|
|
136
|
+
export interface MediaItem {
|
|
137
|
+
mediaId: string;
|
|
138
|
+
title: string;
|
|
139
|
+
subtitle?: string;
|
|
140
|
+
/**mediaUri doesn't seem to work. use Event.RemotePlayId to handle playback instead. */
|
|
141
|
+
// mediaUri?: string | ResourceObject;
|
|
142
|
+
iconUri?: string;
|
|
143
|
+
iconName?: string
|
|
144
|
+
/** playable has 2 states: 1 as browsable, or any other as playable. */
|
|
145
|
+
// playable: MediaItemPlayable.MediaBrowsable | string;
|
|
146
|
+
groupTitle?: string;
|
|
147
|
+
//contentStyle?: string;
|
|
148
|
+
cropThumbnail?: 'true' | 'false'
|
|
149
|
+
childrenBrowsableContentStyle?: '1' | '2'
|
|
150
|
+
childrenPlayableContentStyle?: '1' | '2'
|
|
151
|
+
/** playbackProgress should contain a string representation of a number between 0 and 1 if present */
|
|
152
|
+
//playbackProgress?: string;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface AndroidAutoBrowseTree {
|
|
156
|
+
'/': MediaItem[];
|
|
157
|
+
[key: string]: MediaItem[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface UpdateAndroidAutoBrowseTree {
|
|
161
|
+
[key: string]: MediaItem[];
|
|
162
|
+
}
|
|
163
|
+
|
|
116
164
|
// General
|
|
117
165
|
|
|
118
166
|
export function setupPlayer(options?: PlayerOptions): Promise<void>;
|
|
167
|
+
export function removeNotifications(): Promise<void>;
|
|
119
168
|
|
|
120
169
|
// Player Queue Commands
|
|
121
170
|
|
|
122
171
|
export function setNowPlaying(track: Track): Promise<void>;
|
|
123
172
|
export function updatePlayback(data: any): Promise<void>;
|
|
124
173
|
export function reset(): Promise<void>;
|
|
174
|
+
export function clear(): Promise<void>;
|
|
125
175
|
|
|
126
176
|
// Control Center / Notification Metadata Commands
|
|
177
|
+
|
|
127
178
|
export function updateOptions(options: MetadataOptions): Promise<void>;
|
|
128
179
|
export function updateMetadataForTrack(id: string, metadata: TrackMetadata) : Promise<void>;
|
|
180
|
+
|
|
181
|
+
// Android Auto
|
|
182
|
+
|
|
183
|
+
export function setBrowseTree(browseTree: AndroidAutoBrowseTree): Promise<void>;
|
|
184
|
+
export function updateAndroidAutoPlayerOptions(options: MetadataOptions): Promise<void>;
|
|
185
|
+
export function updateBrowseTree(tab: UpdateAndroidAutoBrowseTree): Promise<void>;
|
|
186
|
+
export function setAndroidAutoPlayerTracks(tracks: MediaItem[], options: { editQueue: boolean }): Promise<void>;
|
|
187
|
+
export function setSearchResult(tracks: MediaItem[], data: { query: string }): Promise<void>;
|
|
188
|
+
export function setIsAndroidTv(value: boolean): Promise<void>;
|
|
189
|
+
|
|
129
190
|
// Components
|
|
130
191
|
|
|
131
192
|
export interface ProgressComponentState {
|