@javascriptcommon/react-native-track-player 1.2.9 → 1.2.23

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.
Files changed (131) hide show
  1. package/android/build.gradle +61 -4
  2. package/android/src/main/AndroidManifest.xml +2 -4
  3. package/android/src/main/ic_home-playstore.png +0 -0
  4. package/android/src/main/ic_repeat-playstore.png +0 -0
  5. package/android/src/main/ic_repeat_50-playstore.png +0 -0
  6. package/android/src/main/ic_shuffle-playstore.png +0 -0
  7. package/android/src/main/ic_shuffle_50-playstore.png +0 -0
  8. package/android/src/main/ic_shuffle_sm-playstore.png +0 -0
  9. package/android/src/main/ic_stop-playstore.png +0 -0
  10. package/android/src/main/ic_test-playstore.png +0 -0
  11. package/android/src/main/java/com/guichaguri/trackplayer/{service/HeadlessJsMediaService.java → HeadlessJsMediaService.java} +84 -33
  12. package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.kt +25 -0
  13. package/android/src/main/java/com/guichaguri/trackplayer/extensions/AudioPlayerStateExt.kt +19 -0
  14. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/EventHolder.kt +30 -0
  15. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/NotificationEventHolder.kt +20 -0
  16. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/PlayerEventHolder.kt +111 -0
  17. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AAMediaSessionCallback.kt +10 -0
  18. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioContentType.kt +10 -0
  19. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItem.kt +66 -0
  20. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItemTransitionReason.kt +33 -0
  21. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioPlayerState.kt +30 -0
  22. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/BufferConfig.kt +8 -0
  23. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/CacheConfig.kt +17 -0
  24. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/Capability.kt +19 -0
  25. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/FocusChangeData.kt +3 -0
  26. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/MediaSessionCallback.kt +17 -0
  27. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationConfig.kt +43 -0
  28. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationMetadata.kt +8 -0
  29. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationState.kt +8 -0
  30. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayWhenReadyChangeData.kt +5 -0
  31. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackEndedReason.kt +5 -0
  32. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackError.kt +6 -0
  33. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackMetadata.kt +200 -0
  34. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerConfig.kt +33 -0
  35. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerOptions.kt +9 -0
  36. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PositionChangedReason.kt +39 -0
  37. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/QueuedPlayerOptions.kt +49 -0
  38. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/notification/NotificationManager.kt +678 -0
  39. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/AudioPlayer.kt +10 -0
  40. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/BaseAudioPlayer.kt +864 -0
  41. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/QueuedAudioPlayer.kt +269 -0
  42. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/MediaSourceExt.kt +35 -0
  43. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/PlayerCache.kt +26 -0
  44. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/utils/Utils.kt +12 -0
  45. package/android/src/main/java/com/guichaguri/trackplayer/model/MetadataAdapter.kt +224 -0
  46. package/android/src/main/java/com/guichaguri/trackplayer/model/State.kt +13 -0
  47. package/android/src/main/java/com/guichaguri/trackplayer/model/Track.kt +120 -0
  48. package/android/src/main/java/com/guichaguri/trackplayer/model/TrackAudioItem.kt +19 -0
  49. package/android/src/main/java/com/guichaguri/trackplayer/model/TrackType.kt +11 -0
  50. package/android/src/main/java/com/guichaguri/trackplayer/module/AutoConnectionDetector.kt +151 -0
  51. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.kt +66 -0
  52. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.kt +1177 -0
  53. package/android/src/main/java/com/guichaguri/trackplayer/service/BundleUtils.kt +117 -0
  54. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.kt +31 -0
  55. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.kt +347 -0
  56. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.kt +1254 -0
  57. package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.kt +228 -0
  58. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.kt +141 -0
  59. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.kt +396 -0
  60. package/android/src/main/res/drawable-hdpi/ic_home.png +0 -0
  61. package/android/src/main/res/drawable-mdpi/ic_home.png +0 -0
  62. package/android/src/main/res/drawable-xhdpi/ic_home.png +0 -0
  63. package/android/src/main/res/drawable-xxhdpi/ic_home.png +0 -0
  64. package/android/src/main/res/drawable-xxxhdpi/ic_home.png +0 -0
  65. package/android/src/main/res/mipmap-hdpi/ic_arrow_down_circle_foreground.png +0 -0
  66. package/android/src/main/res/mipmap-hdpi/ic_clock_now_foreground.png +0 -0
  67. package/android/src/main/res/mipmap-hdpi/ic_close_foreground.png +0 -0
  68. package/android/src/main/res/mipmap-hdpi/ic_heart_foreground.png +0 -0
  69. package/android/src/main/res/mipmap-hdpi/ic_heart_outlined_foreground.png +0 -0
  70. package/android/src/main/res/mipmap-hdpi/ic_repeat_off_foreground.png +0 -0
  71. package/android/src/main/res/mipmap-hdpi/ic_repeat_on_foreground.png +0 -0
  72. package/android/src/main/res/mipmap-hdpi/ic_shuffle_off_foreground.png +0 -0
  73. package/android/src/main/res/mipmap-hdpi/ic_shuffle_on_foreground.png +0 -0
  74. package/android/src/main/res/mipmap-mdpi/ic_arrow_down_circle_foreground.png +0 -0
  75. package/android/src/main/res/mipmap-mdpi/ic_clock_now_foreground.png +0 -0
  76. package/android/src/main/res/mipmap-mdpi/ic_close_foreground.png +0 -0
  77. package/android/src/main/res/mipmap-mdpi/ic_heart_foreground.png +0 -0
  78. package/android/src/main/res/mipmap-mdpi/ic_heart_outlined_foreground.png +0 -0
  79. package/android/src/main/res/mipmap-mdpi/ic_repeat_off_foreground.png +0 -0
  80. package/android/src/main/res/mipmap-mdpi/ic_repeat_on_foreground.png +0 -0
  81. package/android/src/main/res/mipmap-mdpi/ic_shuffle_off_foreground.png +0 -0
  82. package/android/src/main/res/mipmap-mdpi/ic_shuffle_on_foreground.png +0 -0
  83. package/android/src/main/res/mipmap-xhdpi/ic_arrow_down_circle_foreground.png +0 -0
  84. package/android/src/main/res/mipmap-xhdpi/ic_clock_now_foreground.png +0 -0
  85. package/android/src/main/res/mipmap-xhdpi/ic_close_foreground.png +0 -0
  86. package/android/src/main/res/mipmap-xhdpi/ic_heart_foreground.png +0 -0
  87. package/android/src/main/res/mipmap-xhdpi/ic_heart_outlined_foreground.png +0 -0
  88. package/android/src/main/res/mipmap-xhdpi/ic_repeat_off_foreground.png +0 -0
  89. package/android/src/main/res/mipmap-xhdpi/ic_repeat_on_foreground.png +0 -0
  90. package/android/src/main/res/mipmap-xhdpi/ic_shuffle_off_foreground.png +0 -0
  91. package/android/src/main/res/mipmap-xhdpi/ic_shuffle_on_foreground.png +0 -0
  92. package/android/src/main/res/mipmap-xxhdpi/ic_arrow_down_circle_foreground.png +0 -0
  93. package/android/src/main/res/mipmap-xxhdpi/ic_clock_now_foreground.png +0 -0
  94. package/android/src/main/res/mipmap-xxhdpi/ic_close_foreground.png +0 -0
  95. package/android/src/main/res/mipmap-xxhdpi/ic_heart_foreground.png +0 -0
  96. package/android/src/main/res/mipmap-xxhdpi/ic_heart_outlined_foreground.png +0 -0
  97. package/android/src/main/res/mipmap-xxhdpi/ic_repeat_off_foreground.png +0 -0
  98. package/android/src/main/res/mipmap-xxhdpi/ic_repeat_on_foreground.png +0 -0
  99. package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_off_foreground.png +0 -0
  100. package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_on_foreground.png +0 -0
  101. package/android/src/main/res/mipmap-xxxhdpi/ic_arrow_down_circle_foreground.png +0 -0
  102. package/android/src/main/res/mipmap-xxxhdpi/ic_clock_now_foreground.png +0 -0
  103. package/android/src/main/res/mipmap-xxxhdpi/ic_close_foreground.png +0 -0
  104. package/android/src/main/res/mipmap-xxxhdpi/ic_heart_foreground.png +0 -0
  105. package/android/src/main/res/mipmap-xxxhdpi/ic_heart_outlined_foreground.png +0 -0
  106. package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_off_foreground.png +0 -0
  107. package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_on_foreground.png +0 -0
  108. package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_off_foreground.png +0 -0
  109. package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_on_foreground.png +0 -0
  110. package/android/src/main/res/raw/silent_5_seconds.mp3 +0 -0
  111. package/android/src/main/res/strings.xml +6 -0
  112. package/android/src/main/res/values/strings.xml +6 -0
  113. package/index.d.ts +62 -1
  114. package/lib/index.js +10 -9
  115. package/package.json +1 -1
  116. package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +0 -28
  117. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +0 -55
  118. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +0 -298
  119. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +0 -47
  120. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +0 -383
  121. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +0 -271
  122. package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +0 -243
  123. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +0 -148
  124. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +0 -379
  125. package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +0 -141
  126. package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +0 -35
  127. package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
  128. package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
  129. package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
  130. package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
  131. 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
+ }
@@ -0,0 +1,6 @@
1
+ <resources>
2
+ <string name="play">Play</string>
3
+ <string name="playback_channel_name">Now Playing</string>
4
+ <string name="pause">Pause</string>
5
+ </resources>
6
+
@@ -0,0 +1,6 @@
1
+ <resources>
2
+ <string name="play">Play</string>
3
+ <string name="playback_channel_name">Now Playing</string>
4
+ <string name="pause">Pause</string>
5
+ </resources>
6
+
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 {