react-native-nitro-player 0.3.0-alpha.6 → 0.3.0-alpha.8

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/README.md CHANGED
@@ -1 +1,719 @@
1
- Refer Root readme
1
+ # React Native Nitro Player
2
+
3
+ A powerful audio player library for React Native with playlist management, playback controls, and support for Android Auto and CarPlay.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install react-native-nitro-player
9
+ # or
10
+ yarn add react-native-nitro-player
11
+ ```
12
+
13
+ ### Peer Dependencies
14
+
15
+ Make sure you have these installed:
16
+
17
+ ```bash
18
+ npm install react-native-nitro-modules
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### 1. Configure the Player
24
+
25
+ Configure the player before using it in your app:
26
+
27
+ ```typescript
28
+ import { TrackPlayer } from 'react-native-nitro-player'
29
+
30
+ TrackPlayer.configure({
31
+ androidAutoEnabled: true,
32
+ carPlayEnabled: false,
33
+ showInNotification: true,
34
+ })
35
+ ```
36
+
37
+ ### 2. Create Playlists
38
+
39
+ ```typescript
40
+ import { PlayerQueue } from 'react-native-nitro-player'
41
+ import type { TrackItem } from 'react-native-nitro-player'
42
+
43
+ const tracks: TrackItem[] = [
44
+ {
45
+ id: '1',
46
+ title: 'Song Title',
47
+ artist: 'Artist Name',
48
+ album: 'Album Name',
49
+ duration: 180.0, // in seconds
50
+ url: 'https://example.com/song.mp3',
51
+ artwork: 'https://example.com/artwork.jpg',
52
+ },
53
+ ]
54
+
55
+ // Create a playlist
56
+ const playlistId = PlayerQueue.createPlaylist(
57
+ 'My Playlist',
58
+ 'Playlist description',
59
+ 'https://example.com/playlist-artwork.jpg'
60
+ )
61
+
62
+ // Add tracks to the playlist
63
+ PlayerQueue.addTracksToPlaylist(playlistId, tracks)
64
+ ```
65
+
66
+ ### 3. Play Music
67
+
68
+ ```typescript
69
+ import { TrackPlayer, PlayerQueue } from 'react-native-nitro-player'
70
+
71
+ // Load and play a playlist
72
+ PlayerQueue.loadPlaylist(playlistId)
73
+
74
+ // Or play a specific song
75
+ TrackPlayer.playSong('song-id', playlistId)
76
+
77
+ // Basic controls
78
+ TrackPlayer.play()
79
+ TrackPlayer.pause()
80
+ TrackPlayer.skipToNext()
81
+ TrackPlayer.skipToPrevious()
82
+ TrackPlayer.seek(30) // Seek to 30 seconds
83
+
84
+ // Set repeat mode
85
+ TrackPlayer.setRepeatMode('off') // No repeat
86
+ TrackPlayer.setRepeatMode('Playlist') // Repeat entire playlist
87
+ TrackPlayer.setRepeatMode('track') // Repeat current track
88
+
89
+ // Set volume (0-100)
90
+ TrackPlayer.setVolume(50) // Set volume to 50%
91
+ TrackPlayer.setVolume(0) // Mute
92
+ TrackPlayer.setVolume(100) // Maximum volume
93
+ ```
94
+
95
+ ## Core Concepts
96
+
97
+ ### PlayerQueue
98
+
99
+ Manages playlists and tracks. Use it to:
100
+
101
+ - Create, update, and delete playlists
102
+ - Add or remove tracks from playlists
103
+ - Load playlists for playback
104
+ - Listen to playlist changes
105
+
106
+ ### TrackPlayer
107
+
108
+ Controls playback. Use it to:
109
+
110
+ - Play, pause, and seek
111
+ - Skip tracks
112
+ - Control repeat mode
113
+ - Control volume
114
+ - Get current player state
115
+ - Listen to playback events
116
+
117
+ ## React Hooks
118
+
119
+ The library provides React hooks for reactive state management. These hooks automatically update your components when player state changes.
120
+
121
+ ### `useOnChangeTrack()`
122
+
123
+ Returns the current track and the reason why it changed.
124
+
125
+ **Returns:**
126
+
127
+ - `track: TrackItem | undefined` - The current track, or `undefined` if no track is playing
128
+ - `reason: Reason | undefined` - The reason for the track change (`'user_action'`, `'skip'`, `'end'`, or `'error'`)
129
+
130
+ ### `useOnPlaybackStateChange()`
131
+
132
+ Returns the current playback state and the reason for the state change.
133
+
134
+ **Returns:**
135
+
136
+ - `state: TrackPlayerState | undefined` - Current playback state (`'playing'`, `'paused'`, or `'stopped'`)
137
+ - `reason: Reason | undefined` - The reason for the state change
138
+
139
+ ### `useOnPlaybackProgressChange()`
140
+
141
+ Returns real-time playback progress updates.
142
+
143
+ **Returns:**
144
+
145
+ - `position: number` - Current playback position in seconds
146
+ - `totalDuration: number` - Total duration of the current track in seconds
147
+ - `isManuallySeeked: boolean | undefined` - `true` if the user manually seeked, `undefined` otherwise
148
+
149
+ ### `useOnSeek()`
150
+
151
+ Returns information about the last seek event.
152
+
153
+ **Returns:**
154
+
155
+ - `position: number | undefined` - The position where the user seeked to, or `undefined` if no seek has occurred
156
+ - `totalDuration: number | undefined` - The total duration at the time of seek, or `undefined` if no seek has occurred
157
+
158
+ ### `useAndroidAutoConnection()`
159
+
160
+ Monitors Android Auto connection status.
161
+
162
+ **Returns:**
163
+
164
+ - `isConnected: boolean` - `true` if connected to Android Auto, `false` otherwise
165
+
166
+ ### `useAudioDevices()` (Android only)
167
+
168
+ Automatically polls for audio device changes every 2 seconds.
169
+
170
+ **Returns:**
171
+
172
+ - `devices: TAudioDevice[]` - Array of available audio devices
173
+
174
+ ### `useNowPlaying()`
175
+
176
+ Returns the complete current player state (same as `TrackPlayer.getState()`). This hook provides all player information in a single object and automatically updates when the player state changes.
177
+
178
+ **Returns:**
179
+
180
+ - `PlayerState` object containing:
181
+ - `currentTrack: TrackItem | null` - The current track being played, or `null` if no track is playing
182
+ - `totalDuration: number` - Total duration of the current track in seconds
183
+ - `currentState: TrackPlayerState` - Current playback state (`'playing'`, `'paused'`, or `'stopped'`)
184
+ - `currentPlaylistId: string | null` - ID of the currently loaded playlist, or `null` if no playlist is loaded
185
+ - `currentIndex: number` - Index of the current track in the playlist (-1 if no track is playing)
186
+
187
+ **Note:** This hook is equivalent to calling `TrackPlayer.getState()` but provides reactive updates. It listens to track changes and playback state changes to update automatically. Also dont rely on progress from this hook
188
+
189
+ ## Audio Device APIs
190
+
191
+ ### `AudioDevices` (Android only)
192
+
193
+ Android-specific API for managing audio output devices.
194
+
195
+ #### `getAudioDevices(): TAudioDevice[]`
196
+
197
+ Returns the list of available audio output devices.
198
+
199
+ **Returns:** Array of `TAudioDevice` objects with:
200
+
201
+ - `id: number` - Unique device ID
202
+ - `name: string` - Device name (e.g., "Built-in Speaker", "Bluetooth")
203
+ - `type: number` - Device type constant
204
+ - `isActive: boolean` - Whether this device is currently active
205
+
206
+ **Example:**
207
+
208
+ ```typescript
209
+ import { AudioDevices } from 'react-native-nitro-player'
210
+
211
+ if (AudioDevices) {
212
+ const devices = AudioDevices.getAudioDevices()
213
+ devices.forEach(device => {
214
+ console.log(`${device.name} - Active: ${device.isActive}`)
215
+ })
216
+ }
217
+ ```
218
+
219
+ #### `setAudioDevice(deviceId: number): boolean`
220
+
221
+ Sets the active audio output device.
222
+
223
+ **Parameters:**
224
+
225
+ - `deviceId: number` - The ID of the device to activate
226
+
227
+ **Returns:** `true` if successful, `false` otherwise
228
+
229
+ **Example:**
230
+
231
+ ```typescript
232
+ import { AudioDevices } from 'react-native-nitro-player'
233
+
234
+ if (AudioDevices) {
235
+ const success = AudioDevices.setAudioDevice(deviceId)
236
+ console.log(`Device switch: ${success ? 'success' : 'failed'}`)
237
+ }
238
+ ```
239
+
240
+ ### `AudioRoutePicker` (iOS only)
241
+
242
+ iOS-specific API for displaying the native audio route picker (AirPlay menu).
243
+
244
+ #### `showRoutePicker(): void`
245
+
246
+ Shows the native AVRoutePickerView for selecting audio output routes like AirPlay, Bluetooth, etc.
247
+
248
+ **Example:**
249
+
250
+ ```typescript
251
+ import { AudioRoutePicker } from 'react-native-nitro-player'
252
+
253
+ if (AudioRoutePicker) {
254
+ AudioRoutePicker.showRoutePicker()
255
+ }
256
+ ```
257
+
258
+ ## Repeat Mode
259
+
260
+ Control how tracks repeat during playback.
261
+
262
+ ### `setRepeatMode(mode: RepeatMode): boolean`
263
+
264
+ Sets the repeat mode for the player.
265
+
266
+ **Parameters:**
267
+
268
+ - `mode: 'off' | 'Playlist' | 'track'` - The repeat mode to set
269
+ - `'off'` - No repeat, playlist stops at the end
270
+ - `'Playlist'` - Repeat the entire playlist
271
+ - `'track'` - Repeat the current track only
272
+
273
+ **Returns:** `true` if successful, `false` otherwise
274
+
275
+ **Example:**
276
+
277
+ ```typescript
278
+ import { TrackPlayer } from 'react-native-nitro-player'
279
+
280
+ // Turn off repeat
281
+ TrackPlayer.setRepeatMode('off')
282
+
283
+ // Repeat entire playlist
284
+ TrackPlayer.setRepeatMode('Playlist')
285
+
286
+ // Repeat current track
287
+ TrackPlayer.setRepeatMode('track')
288
+ ```
289
+
290
+ ## Volume Control
291
+
292
+ Control the playback volume level.
293
+
294
+ ### `setVolume(volume: number): boolean`
295
+
296
+ Sets the playback volume level.
297
+
298
+ **Parameters:**
299
+
300
+ - `volume: number` - Volume level between 0 and 100
301
+ - `0` - Mute (no sound)
302
+ - `50` - Half volume
303
+ - `100` - Maximum volume
304
+
305
+ **Returns:** `true` if successful, `false` otherwise (e.g., if player is not initialized)
306
+
307
+ **Example:**
308
+
309
+ ```typescript
310
+ import { TrackPlayer } from 'react-native-nitro-player'
311
+
312
+ // Set volume to 50%
313
+ const success = TrackPlayer.setVolume(50)
314
+ if (success) {
315
+ console.log('Volume set successfully')
316
+ } else {
317
+ console.warn('Failed to set volume')
318
+ }
319
+
320
+ // Mute the player
321
+ TrackPlayer.setVolume(0)
322
+
323
+ // Set to maximum volume
324
+ TrackPlayer.setVolume(100)
325
+
326
+ // Incremental volume control
327
+ const currentVolume = 50
328
+ TrackPlayer.setVolume(currentVolume + 10) // Increase by 10%
329
+ TrackPlayer.setVolume(currentVolume - 10) // Decrease by 10%
330
+ ```
331
+
332
+ **Note:** The volume value is automatically clamped to the 0-100 range. Values outside this range will be clamped to the nearest valid value.
333
+
334
+ ## Usage Examples
335
+
336
+ ### Using React Hooks
337
+
338
+ The library provides convenient React hooks for reactive state management:
339
+
340
+ ```typescript
341
+ import {
342
+ useOnChangeTrack,
343
+ useOnPlaybackStateChange,
344
+ useOnPlaybackProgressChange,
345
+ useOnSeek,
346
+ useAndroidAutoConnection,
347
+ } from 'react-native-nitro-player'
348
+
349
+ function PlayerComponent() {
350
+ // Get current track
351
+ const { track, reason } = useOnChangeTrack()
352
+
353
+ // Get playback state (playing, paused, stopped)
354
+ const { state, reason: stateReason } = useOnPlaybackStateChange()
355
+
356
+ // Get playback progress
357
+ const { position, totalDuration, isManuallySeeked } = useOnPlaybackProgressChange()
358
+
359
+ // Get seek events
360
+ const { position: seekPosition, totalDuration: seekDuration } = useOnSeek()
361
+
362
+ // Check Android Auto connection
363
+ const { isConnected } = useAndroidAutoConnection()
364
+
365
+ // Get complete player state (alternative to individual hooks)
366
+ const nowPlaying = useNowPlaying()
367
+
368
+ return (
369
+ <View>
370
+ {track && (
371
+ <Text>Now Playing: {track.title} by {track.artist}</Text>
372
+ )}
373
+ <Text>State: {state}</Text>
374
+ <Text>Progress: {position} / {totalDuration}</Text>
375
+ {/* Or use useNowPlaying for all state at once */}
376
+ <Text>Now Playing State: {nowPlaying.currentState}</Text>
377
+ </View>
378
+ )
379
+ }
380
+ ```
381
+
382
+ ### Managing Playlists
383
+
384
+ ```typescript
385
+ import { PlayerQueue } from 'react-native-nitro-player'
386
+ import type { TrackItem, Playlist } from 'react-native-nitro-player'
387
+
388
+ // Get all playlists
389
+ const playlists = PlayerQueue.getAllPlaylists()
390
+
391
+ // Get a specific playlist
392
+ const playlist = PlayerQueue.getPlaylist(playlistId)
393
+
394
+ // Get current playing playlist
395
+ const currentPlaylistId = PlayerQueue.getCurrentPlaylistId()
396
+
397
+ // Update playlist metadata
398
+ PlayerQueue.updatePlaylist(playlistId, {
399
+ name: 'Updated Name',
400
+ description: 'New description',
401
+ artwork: 'https://example.com/new-artwork.jpg',
402
+ })
403
+
404
+ // Add a single track
405
+ PlayerQueue.addTrackToPlaylist(playlistId, newTrack)
406
+
407
+ // Add multiple tracks
408
+ PlayerQueue.addTracksToPlaylist(playlistId, [track1, track2, track3])
409
+
410
+ // Remove a track
411
+ PlayerQueue.removeTrackFromPlaylist(playlistId, trackId)
412
+
413
+ // Reorder tracks
414
+ PlayerQueue.reorderTrackInPlaylist(playlistId, trackId, newIndex)
415
+
416
+ // Delete a playlist
417
+ PlayerQueue.deletePlaylist(playlistId)
418
+ ```
419
+
420
+ ### Listening to Events
421
+
422
+ ```typescript
423
+ import { PlayerQueue, TrackPlayer } from 'react-native-nitro-player'
424
+
425
+ // Listen to playlist changes
426
+ PlayerQueue.onPlaylistsChanged((playlists, operation) => {
427
+ console.log('Playlists updated:', operation)
428
+ // operation can be: 'add', 'remove', 'clear', 'update'
429
+ })
430
+
431
+ // Listen to specific playlist changes
432
+ PlayerQueue.onPlaylistChanged((playlistId, playlist, operation) => {
433
+ console.log('Playlist changed:', playlistId, operation)
434
+ })
435
+
436
+ // Listen to track changes
437
+ TrackPlayer.onChangeTrack((track, reason) => {
438
+ console.log('Track changed:', track.title, reason)
439
+ // reason can be: 'user_action', 'skip', 'end', 'error'
440
+ })
441
+
442
+ // Listen to playback state changes
443
+ TrackPlayer.onPlaybackStateChange((state, reason) => {
444
+ console.log('State changed:', state, reason)
445
+ })
446
+
447
+ // Listen to seek events
448
+ TrackPlayer.onSeek((position, totalDuration) => {
449
+ console.log('Seeked to:', position)
450
+ })
451
+
452
+ // Listen to playback progress
453
+ TrackPlayer.onPlaybackProgressChange(
454
+ (position, totalDuration, isManuallySeeked) => {
455
+ console.log('Progress:', position, '/', totalDuration)
456
+ }
457
+ )
458
+
459
+ // Listen to Android Auto connection changes
460
+ TrackPlayer.onAndroidAutoConnectionChange(connected => {
461
+ console.log('Android Auto:', connected ? 'Connected' : 'Disconnected')
462
+ })
463
+ ```
464
+
465
+ ### Getting Player State
466
+
467
+ ```typescript
468
+ import { TrackPlayer } from 'react-native-nitro-player'
469
+
470
+ const state = TrackPlayer.getState()
471
+
472
+ console.log(state.currentState) // 'playing' | 'paused' | 'stopped'
473
+ console.log(state.currentPosition) // current position in seconds
474
+ console.log(state.totalDuration) // total duration in seconds
475
+ console.log(state.currentTrack) // current TrackItem or null
476
+ console.log(state.currentPlaylistId) // current playlist ID or null
477
+ console.log(state.currentIndex) // current track index in playlist
478
+ ```
479
+
480
+ ## Track Item Structure
481
+
482
+ Each track must follow this structure:
483
+
484
+ ```typescript
485
+ interface TrackItem {
486
+ id: string // Unique identifier
487
+ title: string // Track title
488
+ artist: string // Artist name
489
+ album: string // Album name
490
+ duration: number // Duration in seconds
491
+ url: string // Audio file URL
492
+ artwork?: string | null // Optional artwork URL
493
+ }
494
+ ```
495
+
496
+ ## Playlist Structure
497
+
498
+ ```typescript
499
+ interface Playlist {
500
+ id: string // Unique identifier
501
+ name: string // Playlist name
502
+ description?: string | null // Optional description
503
+ artwork?: string | null // Optional artwork URL
504
+ tracks: TrackItem[] // Array of tracks
505
+ }
506
+ ```
507
+
508
+ ## Android Auto Customization
509
+
510
+ Customize how your music library appears in Android Auto with a custom folder structure.
511
+
512
+ ### Basic Setup
513
+
514
+ By default, all playlists are shown in Android Auto. You can create a custom structure:
515
+
516
+ ```typescript
517
+ import { AndroidAutoMediaLibraryHelper } from 'react-native-nitro-player'
518
+ import type { MediaLibrary } from 'react-native-nitro-player'
519
+
520
+ // Check if available (Android only)
521
+ if (AndroidAutoMediaLibraryHelper.isAvailable()) {
522
+ const mediaLibrary: MediaLibrary = {
523
+ layoutType: 'grid', // 'grid' or 'list'
524
+ rootItems: [
525
+ {
526
+ id: 'my_music',
527
+ title: '🎵 My Music',
528
+ subtitle: 'Your music collection',
529
+ mediaType: 'folder',
530
+ isPlayable: false,
531
+ layoutType: 'grid',
532
+ children: [
533
+ {
534
+ id: 'favorites',
535
+ title: 'Favorites',
536
+ subtitle: '10 tracks',
537
+ mediaType: 'playlist',
538
+ playlistId: 'my-playlist-id', // References a playlist created with PlayerQueue
539
+ isPlayable: false,
540
+ },
541
+ ],
542
+ },
543
+ {
544
+ id: 'recent',
545
+ title: '🕐 Recently Played',
546
+ mediaType: 'folder',
547
+ isPlayable: false,
548
+ children: [
549
+ // More playlist references...
550
+ ],
551
+ },
552
+ ],
553
+ }
554
+
555
+ AndroidAutoMediaLibraryHelper.set(mediaLibrary)
556
+ }
557
+
558
+ // Reset to default (show all playlists)
559
+ AndroidAutoMediaLibraryHelper.clear()
560
+ ```
561
+
562
+ ### MediaLibrary Structure
563
+
564
+ ```typescript
565
+ interface MediaLibrary {
566
+ layoutType: 'grid' | 'list' // Default layout for items
567
+ rootItems: MediaItem[] // Top-level items
568
+ appName?: string // Optional app name
569
+ appIconUrl?: string // Optional app icon
570
+ }
571
+
572
+ interface MediaItem {
573
+ id: string // Unique identifier
574
+ title: string // Display title
575
+ subtitle?: string // Optional subtitle
576
+ iconUrl?: string // Optional icon/artwork URL
577
+ isPlayable: boolean // Whether item can be played
578
+ mediaType: 'folder' | 'audio' | 'playlist' // Type of item
579
+ playlistId?: string // Reference to playlist (for playlist items)
580
+ children?: MediaItem[] // Child items (for folders)
581
+ layoutType?: 'grid' | 'list' // Override default layout
582
+ }
583
+ ```
584
+
585
+ ### Example: Organizing Playlists by Genre
586
+
587
+ ```typescript
588
+ import {
589
+ PlayerQueue,
590
+ AndroidAutoMediaLibraryHelper,
591
+ } from 'react-native-nitro-player'
592
+
593
+ // Create playlists first
594
+ const rockPlaylistId = PlayerQueue.createPlaylist('Rock Classics')
595
+ const jazzPlaylistId = PlayerQueue.createPlaylist('Jazz Essentials')
596
+ const popPlaylistId = PlayerQueue.createPlaylist('Pop Hits')
597
+
598
+ // Add tracks to playlists...
599
+ PlayerQueue.addTracksToPlaylist(rockPlaylistId, rockTracks)
600
+ PlayerQueue.addTracksToPlaylist(jazzPlaylistId, jazzTracks)
601
+ PlayerQueue.addTracksToPlaylist(popPlaylistId, popTracks)
602
+
603
+ // Create custom Android Auto structure
604
+ AndroidAutoMediaLibraryHelper.set({
605
+ layoutType: 'list',
606
+ rootItems: [
607
+ {
608
+ id: 'genres',
609
+ title: '🎸 By Genre',
610
+ mediaType: 'folder',
611
+ isPlayable: false,
612
+ layoutType: 'grid',
613
+ children: [
614
+ {
615
+ id: 'rock',
616
+ title: 'Rock',
617
+ mediaType: 'playlist',
618
+ playlistId: rockPlaylistId,
619
+ isPlayable: false,
620
+ },
621
+ {
622
+ id: 'jazz',
623
+ title: 'Jazz',
624
+ mediaType: 'playlist',
625
+ playlistId: jazzPlaylistId,
626
+ isPlayable: false,
627
+ },
628
+ {
629
+ id: 'pop',
630
+ title: 'Pop',
631
+ mediaType: 'playlist',
632
+ playlistId: popPlaylistId,
633
+ isPlayable: false,
634
+ },
635
+ ],
636
+ },
637
+ {
638
+ id: 'all_music',
639
+ title: '📀 All Music',
640
+ mediaType: 'folder',
641
+ isPlayable: false,
642
+ children: [
643
+ {
644
+ id: 'all_rock',
645
+ title: 'Rock Classics',
646
+ mediaType: 'playlist',
647
+ playlistId: rockPlaylistId,
648
+ isPlayable: false,
649
+ },
650
+ {
651
+ id: 'all_jazz',
652
+ title: 'Jazz Essentials',
653
+ mediaType: 'playlist',
654
+ playlistId: jazzPlaylistId,
655
+ isPlayable: false,
656
+ },
657
+ {
658
+ id: 'all_pop',
659
+ title: 'Pop Hits',
660
+ mediaType: 'playlist',
661
+ playlistId: popPlaylistId,
662
+ isPlayable: false,
663
+ },
664
+ ],
665
+ },
666
+ ],
667
+ })
668
+ ```
669
+
670
+ ### Notes
671
+
672
+ - The `playlistId` field must reference a playlist created with `PlayerQueue.createPlaylist()`
673
+ - Changes are immediately reflected in Android Auto
674
+ - Use folders to organize playlists hierarchically
675
+ - Grid layout is best for album/playlist browsing
676
+ - List layout is best for song lists
677
+ - Only available on Android (use `isAvailable()` to check)
678
+
679
+ ## Features
680
+
681
+ - ✅ **Playlist Management**: Create, update, and manage multiple playlists
682
+ - ✅ **Playback Controls**: Play, pause, seek, skip tracks
683
+ - ✅ **Volume Control**: Adjust playback volume (0-100)
684
+ - ✅ **React Hooks**: Built-in hooks for reactive state management
685
+ - ✅ **Event Listeners**: Listen to track changes, state changes, and more
686
+ - ✅ **Android Auto Support**: Control playback from Android Auto with customizable UI
687
+ - ✅ **CarPlay Support**: Control playback from CarPlay (iOS)
688
+ - ✅ **Notification Controls**: Show playback controls in notifications
689
+ - ✅ **Progress Tracking**: Real-time playback progress updates
690
+
691
+ ## TypeScript Support
692
+
693
+ The library is written in TypeScript and includes full type definitions. All types are exported for your convenience:
694
+
695
+ ```typescript
696
+ import type {
697
+ TrackItem,
698
+ Playlist,
699
+ PlayerState,
700
+ TrackPlayerState,
701
+ QueueOperation,
702
+ Reason,
703
+ PlayerConfig,
704
+ MediaLibrary,
705
+ MediaItem,
706
+ LayoutType,
707
+ MediaType,
708
+ } from 'react-native-nitro-player'
709
+ ```
710
+
711
+ ## Platform Support
712
+
713
+ - ✅ **iOS**: Full support with CarPlay integration
714
+ - ✅ **Android**: Full support with Android Auto integration
715
+ - 🎯 **Android Auto Media Library**: Android-only feature for customizing the Android Auto UI
716
+
717
+ ## License
718
+
719
+ MIT