react-native-nitro-player 1.7.0-alpha.3 → 1.7.0-alpha.5

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 (98) hide show
  1. package/README.md +9 -0
  2. package/android/src/main/AndroidManifest.xml +8 -0
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrary.kt +51 -0
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridPlayerQueue.kt +45 -7
  5. package/android/src/main/java/com/margelo/nitro/nitroplayer/connection/AndroidAutoConnectionDetector.kt +2 -2
  6. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/ExoPlayerCore.kt +17 -2
  7. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/NitroPlayerLogger.kt +2 -2
  8. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerAndroidAuto.kt +41 -31
  9. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerAudioFocus.kt +65 -0
  10. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCast.kt +1 -1
  11. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +92 -15
  12. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerListener.kt +12 -17
  13. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerNotify.kt +5 -0
  14. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerPlayback.kt +39 -13
  15. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueue.kt +1 -1
  16. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueueBuild.kt +25 -4
  17. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerRecovery.kt +97 -0
  18. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerSetup.kt +0 -5
  19. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerUrlLoader.kt +22 -5
  20. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +3 -0
  21. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/TrackItemJson.kt +6 -0
  22. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/AudioFocusController.kt +87 -0
  23. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/CastSessionController.kt +2 -0
  24. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/ExoPlayerBuilder.kt +3 -0
  25. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaBrowserService.kt +96 -45
  26. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaLibrary.kt +2 -0
  27. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaLibraryManager.kt +147 -0
  28. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaLibraryParser.kt +3 -0
  29. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionCallbackFactory.kt +102 -24
  30. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +51 -3
  31. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/PlaybackService.kt +82 -1
  32. package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +75 -0
  33. package/ios/cast/CastQueueDiff.swift +58 -0
  34. package/ios/cast/CastQueueReconciler.swift +228 -0
  35. package/ios/core/CastSessionManager.swift +215 -31
  36. package/ios/core/TrackPlayerCast.swift +96 -65
  37. package/ios/core/TrackPlayerCore.swift +31 -0
  38. package/ios/core/TrackPlayerListener.swift +19 -3
  39. package/ios/core/TrackPlayerPlayback.swift +12 -10
  40. package/ios/core/TrackPlayerQueue.swift +10 -2
  41. package/ios/core/TrackPlayerQueueBuild.swift +21 -9
  42. package/ios/core/TrackPlayerTempQueue.swift +27 -15
  43. package/ios/core/TrackPlayerUrlLoader.swift +6 -2
  44. package/ios/playlist/PlaylistManager.swift +60 -1
  45. package/ios/queue/HybridPlayerQueue.swift +40 -13
  46. package/lib/hooks/callbackManager.d.ts +2 -0
  47. package/lib/hooks/callbackManager.js +23 -8
  48. package/lib/index.js +5 -1
  49. package/lib/specs/AndroidAutoMediaLibrary.nitro.d.ts +12 -0
  50. package/lib/specs/TrackPlayer.nitro.d.ts +5 -1
  51. package/lib/types/AndroidAutoMediaLibrary.d.ts +11 -0
  52. package/lib/types/PlayerQueue.d.ts +14 -0
  53. package/lib/utils/androidAutoMediaLibrary.d.ts +13 -1
  54. package/lib/utils/androidAutoMediaLibrary.js +23 -0
  55. package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +6 -0
  56. package/nitrogen/generated/android/c++/JAndroidAudioFocusMode.hpp +61 -0
  57. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  58. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
  59. package/nitrogen/generated/android/c++/JFunc_void_std__string_std__string.hpp +76 -0
  60. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.cpp +29 -0
  61. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.hpp +6 -0
  62. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +43 -0
  63. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.hpp +2 -0
  64. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +4 -0
  65. package/nitrogen/generated/android/c++/JPlayerConfig.hpp +9 -3
  66. package/nitrogen/generated/android/c++/JShufflePlaylistOptions.hpp +57 -0
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/AndroidAudioFocusMode.kt +24 -0
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void.kt +80 -0
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string.kt +80 -0
  70. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string_std__string.kt +80 -0
  71. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrarySpec.kt +44 -0
  72. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridPlayerQueueSpec.kt +8 -0
  73. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerConfig.kt +6 -3
  74. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/ShufflePlaylistOptions.kt +38 -0
  75. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +36 -0
  76. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +6 -0
  77. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +19 -0
  78. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +3 -0
  79. package/nitrogen/generated/ios/swift/AndroidAudioFocusMode.swift +44 -0
  80. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec.swift +2 -0
  81. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec_cxx.swift +38 -0
  82. package/nitrogen/generated/ios/swift/PlayerConfig.swift +12 -1
  83. package/nitrogen/generated/ios/swift/ShufflePlaylistOptions.swift +42 -0
  84. package/nitrogen/generated/shared/c++/AndroidAudioFocusMode.hpp +80 -0
  85. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.cpp +6 -0
  86. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.hpp +7 -0
  87. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.cpp +2 -0
  88. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.hpp +5 -0
  89. package/nitrogen/generated/shared/c++/PlayerConfig.hpp +9 -3
  90. package/nitrogen/generated/shared/c++/ShufflePlaylistOptions.hpp +83 -0
  91. package/package.json +1 -1
  92. package/src/hooks/callbackManager.ts +25 -10
  93. package/src/index.ts +9 -1
  94. package/src/specs/AndroidAutoMediaLibrary.nitro.ts +18 -0
  95. package/src/specs/TrackPlayer.nitro.ts +11 -0
  96. package/src/types/AndroidAutoMediaLibrary.ts +24 -0
  97. package/src/types/PlayerQueue.ts +17 -0
  98. package/src/utils/androidAutoMediaLibrary.ts +48 -1
@@ -0,0 +1,83 @@
1
+ ///
2
+ /// ShufflePlaylistOptions.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
11
+ #include <NitroModules/JSIConverter.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
16
+ #include <NitroModules/NitroDefines.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/JSIHelpers.hpp>)
21
+ #include <NitroModules/JSIHelpers.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+ #if __has_include(<NitroModules/PropNameIDCache.hpp>)
26
+ #include <NitroModules/PropNameIDCache.hpp>
27
+ #else
28
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
29
+ #endif
30
+
31
+
32
+
33
+ #include <optional>
34
+
35
+ namespace margelo::nitro::nitroplayer {
36
+
37
+ /**
38
+ * A struct which can be represented as a JavaScript object (ShufflePlaylistOptions).
39
+ */
40
+ struct ShufflePlaylistOptions final {
41
+ public:
42
+ std::optional<bool> keepCurrentTrackFirst SWIFT_PRIVATE;
43
+
44
+ public:
45
+ ShufflePlaylistOptions() = default;
46
+ explicit ShufflePlaylistOptions(std::optional<bool> keepCurrentTrackFirst): keepCurrentTrackFirst(keepCurrentTrackFirst) {}
47
+
48
+ public:
49
+ friend bool operator==(const ShufflePlaylistOptions& lhs, const ShufflePlaylistOptions& rhs) = default;
50
+ };
51
+
52
+ } // namespace margelo::nitro::nitroplayer
53
+
54
+ namespace margelo::nitro {
55
+
56
+ // C++ ShufflePlaylistOptions <> JS ShufflePlaylistOptions (object)
57
+ template <>
58
+ struct JSIConverter<margelo::nitro::nitroplayer::ShufflePlaylistOptions> final {
59
+ static inline margelo::nitro::nitroplayer::ShufflePlaylistOptions fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
60
+ jsi::Object obj = arg.asObject(runtime);
61
+ return margelo::nitro::nitroplayer::ShufflePlaylistOptions(
62
+ JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "keepCurrentTrackFirst")))
63
+ );
64
+ }
65
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::nitroplayer::ShufflePlaylistOptions& arg) {
66
+ jsi::Object obj(runtime);
67
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "keepCurrentTrackFirst"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.keepCurrentTrackFirst));
68
+ return obj;
69
+ }
70
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
71
+ if (!value.isObject()) {
72
+ return false;
73
+ }
74
+ jsi::Object obj = value.getObject(runtime);
75
+ if (!nitro::isPlainObject(runtime, obj)) {
76
+ return false;
77
+ }
78
+ if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "keepCurrentTrackFirst")))) return false;
79
+ return true;
80
+ }
81
+ };
82
+
83
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-player",
3
- "version": "1.7.0-alpha.3",
3
+ "version": "1.7.0-alpha.5",
4
4
  "description": "A powerful audio player library for React Native with playlist management, playback controls, and support for Android Auto and CarPlay",
5
5
  "main": "lib/index",
6
6
  "module": "lib/index",
@@ -37,6 +37,7 @@ class CallbackSubscriptionManager {
37
37
  private androidAutoConnectionSubscribers =
38
38
  new Set<AndroidAutoConnectionCallback>()
39
39
  private isPlaylistsChangedRegistered = false
40
+ private playlistsChangedFanOutScheduled = false
40
41
  private isAndroidAutoConnectionRegistered = false
41
42
  private isPlaybackStateRegistered = false
42
43
  private isTrackChangeRegistered = false
@@ -204,21 +205,35 @@ class CallbackSubscriptionManager {
204
205
  }
205
206
  }
206
207
 
208
+ // Task-level, not a microtask: native callbacks arrive as separate JS tasks.
209
+ private schedulePlaylistsChangedFanOut(): void {
210
+ if (this.playlistsChangedFanOutScheduled) return
211
+ this.playlistsChangedFanOutScheduled = true
212
+ setTimeout(() => {
213
+ this.playlistsChangedFanOutScheduled = false
214
+ this.playlistsChangedSubscribers.forEach((subscriber) => {
215
+ try {
216
+ subscriber()
217
+ } catch (error) {
218
+ console.error(
219
+ '[CallbackManager] Error in playlists changed subscriber:',
220
+ error
221
+ )
222
+ }
223
+ })
224
+ }, 0)
225
+ }
226
+
207
227
  private ensurePlaylistsChangedRegistered(): void {
208
228
  if (this.isPlaylistsChangedRegistered) return
209
229
 
210
230
  try {
211
231
  PlayerQueue.onPlaylistsChanged(() => {
212
- this.playlistsChangedSubscribers.forEach((subscriber) => {
213
- try {
214
- subscriber()
215
- } catch (error) {
216
- console.error(
217
- '[CallbackManager] Error in playlists changed subscriber:',
218
- error
219
- )
220
- }
221
- })
232
+ this.schedulePlaylistsChangedFanOut()
233
+ })
234
+ // Track-level mutations only fire the per-playlist event.
235
+ PlayerQueue.onPlaylistChanged(() => {
236
+ this.schedulePlaylistsChangedFanOut()
222
237
  })
223
238
  this.isPlaylistsChangedRegistered = true
224
239
  } catch (error) {
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // TODO: Export all HybridObjects here for the user
2
2
 
3
3
  import { NitroModules } from 'react-native-nitro-modules'
4
- import { Platform } from 'react-native'
4
+ import { AppRegistry, Platform } from 'react-native'
5
5
  import type {
6
6
  PlayerQueue as PlayerQueueType,
7
7
  TrackPlayer as TrackPlayerType,
@@ -13,6 +13,14 @@ import type { Cast as CastType } from './specs/Cast.nitro'
13
13
  import type { DownloadManager as DownloadManagerType } from './specs/DownloadManager.nitro'
14
14
  import type { Equalizer as EqualizerType } from './specs/Equalizer.nitro'
15
15
 
16
+ // Native runs this while it needs JS without a resumed activity (car, screen off): it keeps JS timers ticking
17
+ if (Platform.OS === 'android') {
18
+ AppRegistry.registerHeadlessTask(
19
+ 'NitroPlayerKeepAlive',
20
+ () => () => new Promise<void>(() => {})
21
+ )
22
+ }
23
+
16
24
  export const PlayerQueue =
17
25
  NitroModules.createHybridObject<PlayerQueueType>('PlayerQueue')
18
26
  export const TrackPlayer =
@@ -20,4 +20,22 @@ export interface AndroidAutoMediaLibrary extends HybridObject<{
20
20
  * Falls back to showing all playlists
21
21
  */
22
22
  clearMediaLibrary(): Promise<void>
23
+
24
+ /** Android Auto opened a folder published with `children: []`; answer with {@link resolveRequest}. */
25
+ onLoadChildren(callback: (requestId: string, parentId: string) => void): void
26
+
27
+ /** A car search, or a voice request the loaded playlists cannot match; answer with {@link resolveRequest}. */
28
+ onSearch(callback: (requestId: string, query: string) => void): void
29
+
30
+ /** Answers {@link onLoadChildren} / {@link onSearch} with a JSON array of MediaItem. */
31
+ resolveRequest(requestId: string, itemsJson: string): void
32
+
33
+ /** Replaces the session buttons with a JSON array of SessionButton. */
34
+ setSessionButtons(buttonsJson: string): void
35
+
36
+ /** Called with the button's `action` when a session button is pressed. */
37
+ onSessionButtonPress(callback: (action: string) => void): void
38
+
39
+ /** A controller asked to play with nothing loaded (car auto-play, play on connect); load the last queue now. */
40
+ onPlaybackResumption(callback: () => void): void
23
41
  }
@@ -8,6 +8,7 @@ import type {
8
8
  PlayerConfig,
9
9
  Playlist,
10
10
  TimedMetadata,
11
+ ShufflePlaylistOptions,
11
12
  } from '../types/PlayerQueue'
12
13
 
13
14
  export interface PlayerQueue extends HybridObject<{
@@ -47,6 +48,16 @@ export interface PlayerQueue extends HybridObject<{
47
48
  trackId: string,
48
49
  newIndex: number
49
50
  ): Promise<void>
51
+ /** One native pass. Unknown ids are skipped; rejects only if the playlist does not exist. */
52
+ removeTracksFromPlaylist(
53
+ playlistId: string,
54
+ trackIds: string[]
55
+ ): Promise<void>
56
+ /** Fisher-Yates shuffle of the stored playlist, persisted. Never interrupts the playing item. */
57
+ shufflePlaylist(
58
+ playlistId: string,
59
+ options?: ShufflePlaylistOptions
60
+ ): Promise<void>
50
61
 
51
62
  // Playback control
52
63
  loadPlaylist(playlistId: string, index?: number): Promise<void>
@@ -38,6 +38,9 @@ export interface MediaItem {
38
38
 
39
39
  /** Layout type for folder items (overrides library default) */
40
40
  layoutType?: LayoutType
41
+
42
+ /** Group header; contiguous items sharing one are listed under it */
43
+ groupTitle?: string
41
44
  }
42
45
 
43
46
  /**
@@ -56,3 +59,24 @@ export interface MediaLibrary {
56
59
  /** Optional app icon URL */
57
60
  appIconUrl?: string
58
61
  }
62
+
63
+ export type SessionButtonIcon =
64
+ | 'heart'
65
+ | 'heart_filled'
66
+ | 'star'
67
+ | 'star_filled'
68
+ | 'thumb_up'
69
+ | 'thumb_up_filled'
70
+ | 'plus'
71
+ | 'check'
72
+
73
+ /** App-defined button beside the transport controls in Android Auto and the notification */
74
+ export interface SessionButton {
75
+ /** Passed to the press callback */
76
+ action: string
77
+
78
+ /** Accessibility label */
79
+ title: string
80
+
81
+ icon: SessionButtonIcon
82
+ }
@@ -26,6 +26,11 @@ export interface Playlist {
26
26
 
27
27
  export type QueueOperation = 'add' | 'remove' | 'clear' | 'update'
28
28
 
29
+ export interface ShufflePlaylistOptions {
30
+ /** Move the playing track to index 0 and shuffle the rest behind it (default: true). */
31
+ keepCurrentTrackFirst?: boolean
32
+ }
33
+
29
34
  export type TrackPlayerState = 'playing' | 'paused' | 'stopped' | 'buffering'
30
35
 
31
36
  export type Reason = 'user_action' | 'skip' | 'end' | 'error' | 'repeat'
@@ -56,6 +61,15 @@ export interface TimedMetadata {
56
61
  artworkUrl?: string
57
62
  }
58
63
 
64
+ /**
65
+ * How Android reacts when another app takes audio focus.
66
+ * - 'pause': pause for any interruption and resume after it (default, today's behaviour)
67
+ * - 'duck': keep playing at a reduced volume through transient interruptions
68
+ * - 'ignore': never react to audio focus at all
69
+ * iOS ignores this option.
70
+ */
71
+ export type AndroidAudioFocusMode = 'pause' | 'duck' | 'ignore'
72
+
59
73
  export interface PlayerConfig {
60
74
  androidAutoEnabled?: boolean
61
75
  carPlayEnabled?: boolean
@@ -75,4 +89,7 @@ export interface PlayerConfig {
75
89
  lookaheadCount?: number
76
90
 
77
91
  androidNotificationIcon?: string
92
+
93
+ /** How Android reacts when another app takes audio focus (default: 'pause'). */
94
+ androidAudioFocus?: AndroidAudioFocusMode
78
95
  }
@@ -1,6 +1,24 @@
1
- import type { MediaLibrary } from '../types/AndroidAutoMediaLibrary'
1
+ import type {
2
+ MediaItem,
3
+ MediaLibrary,
4
+ SessionButton,
5
+ } from '../types/AndroidAutoMediaLibrary'
2
6
  import { AndroidAutoMediaLibrary as AndroidAutoMediaLibraryModule } from '../index'
3
7
 
8
+ type ItemsProvider = (
9
+ argument: string
10
+ ) => Promise<MediaItem[] | null | undefined>
11
+
12
+ const answer = (requestId: string, provide: () => ReturnType<ItemsProvider>) =>
13
+ provide()
14
+ .catch(() => null)
15
+ .then((items) =>
16
+ AndroidAutoMediaLibraryModule?.resolveRequest(
17
+ requestId,
18
+ JSON.stringify(items ?? [])
19
+ )
20
+ )
21
+
4
22
  /**
5
23
  * Helper utilities for Android Auto Media Library
6
24
  * Android-only functionality
@@ -57,6 +75,35 @@ export const AndroidAutoMediaLibraryHelper = {
57
75
  AndroidAutoMediaLibraryModule.clearMediaLibrary()
58
76
  },
59
77
 
78
+ /** Children of folders published with `children: []`; playable ids are `${playlistId}:${trackId}`, empty after 10s. Register at module scope: the car can start the app without UI. */
79
+ setChildrenLoader: (loader: ItemsProvider): void => {
80
+ AndroidAutoMediaLibraryModule?.onLoadChildren((requestId, parentId) =>
81
+ answer(requestId, () => loader(parentId))
82
+ )
83
+ },
84
+
85
+ /** Answers car searches and unmatched voice requests (first playable result plays); search shows from the next connection. */
86
+ setSearchHandler: (handler: ItemsProvider): void => {
87
+ AndroidAutoMediaLibraryModule?.onSearch((requestId, query) =>
88
+ answer(requestId, () => handler(query))
89
+ )
90
+ },
91
+
92
+ /** Buttons beside the transport controls in Android Auto and the notification; call again to change their state. */
93
+ setSessionButtons: (buttons: SessionButton[]): void => {
94
+ AndroidAutoMediaLibraryModule?.setSessionButtons(JSON.stringify(buttons))
95
+ },
96
+
97
+ /** Called with the pressed button's `action`. */
98
+ onSessionButtonPress: (callback: (action: string) => void): void => {
99
+ AndroidAutoMediaLibraryModule?.onSessionButtonPress(callback)
100
+ },
101
+
102
+ /** Car auto-play or play-on-connect found nothing loaded: restore your last queue (playback starts once it is loaded). */
103
+ onPlaybackResumption: (callback: () => void): void => {
104
+ AndroidAutoMediaLibraryModule?.onPlaybackResumption(callback)
105
+ },
106
+
60
107
  /**
61
108
  * Check if Android Auto Media Library is available (Android only)
62
109
  */