Skip to content

Commit 0dee512

Browse files
authored
Docs/audio manager (#458)
* docs: add audio manager documentation * feat: rewrote types section * docs: better info on returning types * docs: added missing explanation and aligned with new impl * fix: small typos * fix: typos * feat: extended examples
1 parent 04096c3 commit 0dee512

File tree

3 files changed

+351
-0
lines changed

3 files changed

+351
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"label": "System",
3+
"position": 6,
4+
"link": {
5+
"type": "generated-index"
6+
}
7+
}
8+
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
5+
import { Optional, ReadOnly, OnlyiOS } from '@site/src/components/Badges';
6+
7+
# AudioManager
8+
9+
The `AudioManager` is a layer of an abstraction between user and a system.
10+
It provides a set of system-specific functions that are invoked directly in native code, by related system.
11+
12+
## Example
13+
14+
```tsx
15+
import { AudioManager } from 'react-native-audio-api';
16+
import { useEffect } from 'react';
17+
18+
function App() {
19+
// set AVAudioSession example options (iOS only)
20+
AudioManager.setAudioSessionOptions({
21+
iosCategory: 'playback',
22+
iosMode: 'default',
23+
iosOptions: ['allowBluetooth', 'allowAirPlay'],
24+
})
25+
26+
// set info for track to be visible while device is locked
27+
AudioManager.setLockScreenInfo({
28+
title: 'Audio file',
29+
artist: 'Software Mansion',
30+
album: 'Audio API',
31+
duration: 10,
32+
});
33+
34+
useEffect(() => {
35+
36+
// enabling emission of events
37+
AudioManager.enableRemoteCommand('remotePlay', true);
38+
AudioManager.enableRemoteCommand('remotePause', true);
39+
AudioManager.observeAudioInterruptions(true);
40+
41+
// callback to be invoked on 'remotePlay' event
42+
const remotePlaySubscription = AudioManager.addSystemEventListener(
43+
'remotePlay',
44+
(event) => {
45+
console.log('remotePlay event:', event);
46+
}
47+
);
48+
49+
// callback to be invoked on 'remotePause' event
50+
const remotePauseSubscription = AudioManager.addSystemEventListener(
51+
'remotePause',
52+
(event) => {
53+
console.log('remotePause event:', event);
54+
}
55+
);
56+
57+
// callback to be invoked on 'interruption' event
58+
const interruptionSubscription = AudioManager.addSystemEventListener(
59+
'interruption',
60+
(event) => {
61+
console.log('Interruption event:', event);
62+
}
63+
);
64+
65+
66+
return () => {
67+
remotePlaySubscription?.remove();
68+
remotePauseSubscription?.remove();
69+
interruptionSubscription?.remove();
70+
};
71+
}, []);
72+
}
73+
```
74+
75+
## Methods
76+
77+
### `setLockScreenInfo`
78+
79+
| Parameters | Type | Description |
80+
| :---: | :---: | :-----: |
81+
| `info` | [`LockScreenInfo`](/system/audio-manager#lockscreeninfo) | Information to be displayed on the lock screen |
82+
83+
#### Returns `undefined`
84+
85+
### `resetLockScreenInfo`
86+
87+
Resets all of the lock screen data.
88+
89+
#### Returns `undefined`
90+
91+
### `setAudioSessionOptions` <OnlyiOS />
92+
93+
| Parameters | Type | Description |
94+
| :---: | :---: | :---- |
95+
| options | [`SessionOptions`](/system/audio-manager#sessionoptions) | Options to be set for AVAudioSession |
96+
97+
#### Returns `undefined`
98+
99+
### `setAudioSessionActivity` <OnlyiOS />
100+
101+
| Parameters | Type | Description |
102+
| :---: | :---: | :---- |
103+
| enabled | `boolean` | It is used to set/unset AVAudioSession activity |
104+
105+
#### Returns promise of `boolean` type, which is resolved to `true` if invokation ended with success, `false` otherwise.
106+
107+
### `getDevicePreferredSampleRate`
108+
109+
#### Returns `number`.
110+
111+
### `observeAudioInterruptions`
112+
113+
| Parameters | Type | Description |
114+
| :---: | :---: | :---- |
115+
| `enabled` | `boolean` | It is used to enable/disable observing audio interruptions |
116+
117+
#### Returns `undefined`
118+
119+
### `observeVolumeChanges`
120+
121+
| Parameters | Type | Description |
122+
| :---: | :---: | :---- |
123+
| `enabled` | `boolean` | It is used to enable/disable observing volume changes |
124+
125+
#### Returns `undefined`
126+
127+
### `enableRemoteCommand`
128+
129+
Enables emition of some system events.
130+
131+
| Parameters | Type | Description |
132+
| :---: | :---: | :---- |
133+
| `name` | [`RemoteCommandEventName`](/system/audio-manager#systemeventname--remotecommandeventname) | Name of an event |
134+
| `enabled` | `boolean` | Indicates the start or the end of event emission |
135+
136+
#### Returns `undefined`
137+
138+
:::info
139+
140+
If you want to add callback upon hearing event, remember to call [`addSystemEventListener`](/system/audio-manager#addsystemeventlistener)
141+
with proper parameters.
142+
143+
:::
144+
145+
146+
### `addSystemEventListener`
147+
148+
Adds callback to be invoked upon hearing an event.
149+
150+
| Parameters | Type | Description |
151+
| :---: | :---: | :---- |
152+
| `name` | [`SystemEventName`](/system/audio-manager#systemeventname--remotecommandeventname) | Name of an event listener |
153+
| `callback` | [`SystemEventCallback`](/system/audio-manager#systemeventname--remotecommandeventname) | Callback that will be invoked upon hearing an event |
154+
155+
#### Returns [`AudioEventSubscription`](/system/audio-manager#audioeventsubscription) if `enabled` is set to true, `undefined` otherwise
156+
157+
### `requestRecordingPermissions`
158+
159+
Allows to bring up the system microphone permissions pop-up on demand. The pop-up automatically shows if microphone data
160+
is directly requested, but sometimes it is better to ask beforehand.
161+
162+
#### Returns promise of [`PermissionStatus`](/system/audio-manager#permissionstatus) type, which is resolved after receiving answer from the system.
163+
164+
### `checkRecordingPermissions`
165+
166+
Allows to check if permissions were previously granted.
167+
168+
#### Returns promise of [`PermissionStatus`](/system/audio-manager#permissionstatus) type, which is resolved after receiving answer from the system.
169+
170+
## Remarks
171+
172+
### `LockScreenInfo`
173+
174+
<details>
175+
<summary>Type definitions</summary>
176+
```typescript
177+
interface BaseLockScreenInfo {
178+
[key: string]: string | boolean | number | undefined;
179+
}
180+
181+
//state_playing if track is played, state_paused otherwise
182+
type MediaState = 'state_playing' | 'state_paused';
183+
184+
interface LockScreenInfo extends BaseLockScreenInfo {
185+
title?: string; //title of the track
186+
artwork?: string; //uri to the artwork
187+
artist?: string; //name of the artist
188+
album?: string; //name of the album
189+
duration?: number; //duration in seconds
190+
description?: string; // android only, description of the track
191+
state?: MediaState;
192+
speed?: number; //playback rate
193+
elapsedTime?: number; //elapsed time of an audio in seconds
194+
}
195+
```
196+
</details>
197+
198+
### `SessionOptions`
199+
200+
<details>
201+
<summary>Type definitions</summary>
202+
```typescript
203+
type IOSCategory =
204+
| 'record'
205+
| 'ambient'
206+
| 'playback'
207+
| 'multiRoute'
208+
| 'soloAmbient'
209+
| 'playAndRecord';
210+
211+
type IOSMode =
212+
| 'default'
213+
| 'gameChat'
214+
| 'videoChat'
215+
| 'voiceChat'
216+
| 'measurement'
217+
| 'voicePrompt'
218+
| 'spokenAudio'
219+
| 'moviePlayback'
220+
| 'videoRecording';
221+
222+
type IOSOption =
223+
| 'duckOthers'
224+
| 'allowAirPlay'
225+
| 'mixWithOthers'
226+
| 'allowBluetooth'
227+
| 'defaultToSpeaker'
228+
| 'allowBluetoothA2DP'
229+
| 'overrideMutedMicrophoneInterruption'
230+
| 'interruptSpokenAudioAndMixWithOthers';
231+
232+
interface SessionOptions {
233+
iosMode?: IOSMode;
234+
iosOptions?: IOSOption[];
235+
iosCategory?: IOSCategory;
236+
}
237+
```
238+
</details>
239+
240+
241+
### `SystemEventName` | `RemoteCommandEventName`
242+
243+
<details>
244+
<summary>Type definitions</summary>
245+
```typescript
246+
interface EventEmptyType {}
247+
248+
interface EventTypeWithValue {
249+
value: number;
250+
}
251+
252+
interface OnInterruptionEventType {
253+
type: 'ended' | 'began'; //if interruption event has started or ended
254+
shouldResume: boolean; //if we should resume playing after interruption
255+
}
256+
257+
interface OnRouteChangeEventType {
258+
reason:
259+
| 'Unknown'
260+
| 'Override'
261+
| 'CategoryChange'
262+
| 'WakeFromSleep'
263+
| 'NewDeviceAvailable'
264+
| 'OldDeviceUnavailable'
265+
| 'ConfigurationChange'
266+
| 'NoSuitableRouteForCategory';
267+
}
268+
269+
// visit https://developer.apple.com/documentation/mediaplayer/mpremotecommandcenter?language=objc
270+
// for further info
271+
interface RemoteCommandEvents {
272+
remotePlay: EventEmptyType;
273+
remotePause: EventEmptyType;
274+
remoteStop: EventEmptyType;
275+
remoteTogglePlayPause: EventEmptyType; // iOS only
276+
remoteChangePlaybackRate: EventTypeWithValue;
277+
remoteNextTrack: EventEmptyType;
278+
remotePreviousTrack: EventEmptyType;
279+
remoteSkipForward: EventTypeWithValue;
280+
remoteSkipBackward: EventTypeWithValue; // iOS only
281+
remoteSeekForward: EventEmptyType; // iOS only
282+
remoteSeekBackward: EventEmptyType;
283+
remoteChangePlaybackPosition: EventTypeWithValue;
284+
}
285+
286+
type SystemEvents = RemoteCommandEvents & {
287+
volumeChange: EventTypeWithValue; //triggered when volume level is changed
288+
interruption: OnInterruptionEventType; //triggered when f.e. some app wants to play music when we are playing
289+
routeChange: OnRouteChangeEventType; //change of output f.e. from speaker to headphones, events are always emitted!
290+
};
291+
292+
type RemoteCommandEventName = keyof RemoteCommandEvents;
293+
type SystemEventName = keyof SystemEvents;
294+
type SystemEventCallback<Name extends SystemEventName> = (
295+
event: SystemEvents[Name]
296+
) => void;
297+
```
298+
</details>
299+
300+
301+
### `AudioEventSubscription`
302+
303+
<details>
304+
<summary>Type definitions</summary>
305+
```typescript
306+
class AudioEventSubscription {
307+
private readonly audioEventEmitter: AudioEventEmitter;
308+
private readonly eventName: AudioEventName;
309+
/** @internal */
310+
public readonly subscriptionId: string;
311+
312+
constructor(
313+
subscriptionId: string,
314+
eventName: AudioEventName,
315+
audioEventEmitter: AudioEventEmitter
316+
) {
317+
this.subscriptionId = subscriptionId;
318+
this.eventName = eventName;
319+
this.audioEventEmitter = audioEventEmitter;
320+
}
321+
322+
public remove(): void {
323+
this.audioEventEmitter.removeAudioEventListener(
324+
this.eventName,
325+
this.subscriptionId
326+
);
327+
}
328+
}
329+
```
330+
</details>
331+
332+
### `PermissionStatus`
333+
334+
<details>
335+
<summary>Type definitions</summary>
336+
```typescript
337+
type PermissionStatus = 'Undetermined' | 'Denied' | 'Granted';
338+
```
339+
</details>

packages/audiodocs/src/components/Badges/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export function Overridden({ footnote }) {
1313
return <div className={styles.badge}>Overridden{footnote ? '*' : ''}</div>;
1414
}
1515

16+
export function OnlyiOS({ footnote }) {
17+
return <div className={styles.badge}>iOS only{footnote ? '*' : ''}</div>;
18+
}
19+
1620
export function Experimental({ footnote }) {
1721
return <div className={`${styles.badge} ${styles.experimental}`}>Experimental{footnote ? '*' : ''}</div>;
1822
}

0 commit comments

Comments
 (0)