Skip to content

Commit

Permalink
[expo-av] Fix Audio.stopAndUnloadAsync not handling no-data on Android (
Browse files Browse the repository at this point in the history
#9877)

* [expo-av] Fix Audio.stopAndUnloadAsync not handling no-data on Android

* [expo-av] Update changelog

* [expo-av] Update build files

* Update build files

* Update packages/expo-av/src/Audio/Recording.ts

Co-authored-by: Bartłomiej Bukowski <bartlomiej.bukowski@swmansion.com>

* update build files

Co-authored-by: Bartłomiej Bukowski <bartlomiej.bukowski@swmansion.com>
  • Loading branch information
IjzerenHein and bbarthec committed Oct 9, 2020
1 parent ef941d8 commit 704103f
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 12 deletions.
2 changes: 2 additions & 0 deletions docs/pages/versions/unversioned/sdk/audio.md
Expand Up @@ -338,6 +338,8 @@ try {

Stops the recording and deallocates the recorder from memory. This reverts the `Recording` instance to an unprepared state, and another `Recording` instance must be created in order to record again. This method can only be called if the `Recording` has been prepared.

NOTE: On Android this method may fail with `E_AUDIO_NODATA` when called too soon after `startAsync` and no audio data has been recorded yet. In that case the recorded file will be invalid and should be discarded.

#### Returns

A `Promise` that is fulfilled when recording has stopped, or rejects if recording could not be stopped. The promise is resolved with the `status` of the recording (see `getStatusAsync()` for details).
Expand Down
1 change: 1 addition & 0 deletions packages/expo-av/CHANGELOG.md
Expand Up @@ -10,6 +10,7 @@

- Fix orientation being returned incorrectly for videos in portrait mode in onReadyForDisplay on iOS. ([#10449](https://github.com/expo/expo/pull/10449) by [@lachenmayer](https://github.com/lachenmayer))
- Fix looping stops after 3 times on iOS. ([#10602](https://github.com/expo/expo/pull/10602) by [@IjzerenHein](https://github.com/IjzerenHein))
- Fix Audio.stopAndUnloadAsync not handling no-data on Android. ([#9877](https://github.com/expo/expo/pull/9877) by [@IjzerenHein](https://github.com/IjzerenHein))

## 8.6.0 — 2020-08-18

Expand Down
Expand Up @@ -693,7 +693,13 @@ public void stopAudioRecording(final Promise promise) {
try {
mAudioRecorder.stop();
} catch (final RuntimeException e) {
promise.reject("E_AUDIO_RECORDINGSTOP", "Stop encountered an error: recording not stopped", e);
mAudioRecorderIsPaused = false;
if (!mAudioRecorderIsRecording) {
promise.reject("E_AUDIO_RECORDINGSTOP", "Stop encountered an error: recording not started", e);
} else {
mAudioRecorderIsRecording = false;
promise.reject("E_AUDIO_NODATA", "Stop encountered an error: no valid audio data has been received", e);
}
return;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/expo-av/build/Audio/Recording.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions packages/expo-av/build/Audio/Recording.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/expo-av/build/Audio/Recording.js.map

Large diffs are not rendered by default.

18 changes: 13 additions & 5 deletions packages/expo-av/src/Audio/Recording.ts
Expand Up @@ -179,11 +179,10 @@ export class Recording {

// Internal methods

_cleanupForUnloadedRecorder = async (finalStatus: RecordingStatus) => {
_cleanupForUnloadedRecorder = async (finalStatus?: RecordingStatus) => {
this._canRecord = false;
this._isDoneRecording = true;
// $FlowFixMe(greg): durationMillis is not always defined
this._finalDurationMillis = finalStatus.durationMillis;
this._finalDurationMillis = finalStatus?.durationMillis ?? 0;
_recorderExists = false;
if (this._subscription) {
this._subscription.remove();
Expand Down Expand Up @@ -354,9 +353,18 @@ export class Recording {
}
// We perform a separate native API call so that the state of the Recording can be updated with
// the final duration of the recording. (We cast stopStatus as Object to appease Flow)
const finalStatus = await ExponentAV.stopAudioRecording();
let stopResult: RecordingStatus | undefined;
let stopError: Error | undefined;
try {
stopResult = await ExponentAV.stopAudioRecording();
} catch (err) {
stopError = err;
}

// Clean-up and return status
await ExponentAV.unloadAudioRecorder();
return this._cleanupForUnloadedRecorder(finalStatus);
const status = await this._cleanupForUnloadedRecorder(stopResult);
return stopError ? Promise.reject(stopError) : status;
}

// Read API
Expand Down

0 comments on commit 704103f

Please sign in to comment.