diff --git a/API.md b/API.md index d8772410..85badf38 100644 --- a/API.md +++ b/API.md @@ -294,6 +294,7 @@ var styles = StyleSheet.create({ | [adTagUrl](#adTagUrl) | Android, iOS | | [allowsExternalPlayback](#allowsexternalplayback) | iOS | | [audioOnly](#audioonly) | All | +| [audioOutput](#audioOutput) | Android, iOS | | [automaticallyWaitsToMinimizeStalling](#automaticallyWaitsToMinimizeStalling) | iOS | | [backBufferDurationMs](#backBufferDurationMs) | Android | | [bufferConfig](#bufferconfig) | Android | @@ -418,6 +419,13 @@ For this to work, the poster prop must be set. Platforms: all +#### audioOutput +Changes the audio output. +* **speaker (default)** - plays through speaker +* **earpiece** - plays through earpiece + +Platforms: Android, iOS + #### automaticallyWaitsToMinimizeStalling A Boolean value that indicates whether the player should automatically delay playback in order to minimize stalling. For clients linked against iOS 10.0 and later * **false** - Immediately starts playback diff --git a/CHANGELOG.md b/CHANGELOG.md index ff6d367d..9fce72af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Changelog +- Feature: playing audio over earpiece [#2887](https://github.com/react-native-video/react-native-video/issues/2887) + ### Version 6.0.0-alpha.7 - All: clean JS warnings (https://github.com/react-native-video/react-native-video/pull/3183) - Android: Add shutterView color configurtion (https://github.com/react-native-video/react-native-video/pull/3179) diff --git a/Video.js b/Video.js index 86b75dae..d2502524 100644 --- a/Video.js +++ b/Video.js @@ -515,6 +515,7 @@ Video.propTypes = { disableBuffering: PropTypes.bool, controls: PropTypes.bool, audioOnly: PropTypes.bool, + audioOutput: PropTypes.oneOf(['earpiece', 'speaker']), fullscreenAutorotate: PropTypes.bool, fullscreenOrientation: PropTypes.oneOf(['all', 'landscape', 'portrait']), progressUpdateInterval: PropTypes.number, diff --git a/android/src/main/java/com/brentvatne/exoplayer/AudioOutput.java b/android/src/main/java/com/brentvatne/exoplayer/AudioOutput.java new file mode 100644 index 00000000..dc2354ae --- /dev/null +++ b/android/src/main/java/com/brentvatne/exoplayer/AudioOutput.java @@ -0,0 +1,31 @@ +package com.brentvatne.exoplayer; + +import android.annotation.SuppressLint; +import com.google.android.exoplayer2.C; + +@SuppressLint("InlinedApi") +public enum AudioOutput { + SPEAKER("speaker", C.STREAM_TYPE_MUSIC), + EARPIECE("earpiece", C.STREAM_TYPE_VOICE_CALL); + + private final int streamType; + private final String mName; + + AudioOutput(final String name, int stream) { + mName = name; + streamType = stream; + } + + public static AudioOutput get(String name) { + for (AudioOutput d : values()) { + if (d.mName.equalsIgnoreCase(name)) + return d; + } + return SPEAKER; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "(" + this.mName + ", " + streamType + ")"; + } +} \ No newline at end of file diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 544c6ac2..e908ca0a 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -28,6 +28,7 @@ import androidx.activity.OnBackPressedCallback; import com.brentvatne.common.Track; import com.brentvatne.common.VideoTrack; +import com.brentvatne.exoplayer.AudioOutput; import com.brentvatne.react.R; import com.brentvatne.receiver.AudioBecomingNoisyReceiver; import com.brentvatne.receiver.BecomingNoisyListener; @@ -48,6 +49,7 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Tracks; +import com.google.android.exoplayer2.audio.AudioAttributes; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; import com.google.android.exoplayer2.drm.DefaultDrmSessionManagerProvider; import com.google.android.exoplayer2.drm.DrmSessionEventListener; @@ -162,6 +164,7 @@ class ReactExoplayerView extends FrameLayout implements private boolean muted = false; private boolean hasAudioFocus = false; private float rate = 1f; + private AudioOutput audioOutput = AudioOutput.SPEAKER; private float audioVolume = 1f; private int minLoadRetryCount = 3; private int maxBitRate = 0; @@ -653,6 +656,7 @@ class ReactExoplayerView extends FrameLayout implements PlaybackParameters params = new PlaybackParameters(rate, 1f); player.setPlaybackParameters(params); + changeAudioOutput(this.audioOutput); } private DrmSessionManager initializePlayerDrm(ReactExoplayerView self) { @@ -1819,6 +1823,29 @@ class ReactExoplayerView extends FrameLayout implements } } + private void changeAudioOutput(AudioOutput output) { + if (player != null) { + int usage = Util.getAudioUsageForStreamType(audioOutput.streamType); + int contentType = Util.getAudioContentTypeForStreamType(audioOutput.streamType); + AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(usage) + .setContentType(contentType) + .build(); + player.setAudioAttributes(audioAttributes, false); + AudioManager audioManager = (AudioManager) themedReactContext.getSystemService(Context.AUDIO_SERVICE); + audioManager.setMode( + audioOutput == AudioOutput.SPEAKER ? AudioManager.MODE_NORMAL + : AudioManager.MODE_IN_COMMUNICATION); + audioManager.setSpeakerphoneOn(audioOutput == AudioOutput.SPEAKER); + } + } + + public void setAudioOutput(AudioOutput output) { + if (audioOutput != output) { + this.audioOutput = output; + changeAudioOutput(output); + } + } + public void setVolumeModifier(float volume) { audioVolume = volume; if (player != null) { diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java index ed810ca6..606f1504 100644 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java @@ -49,6 +49,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager