diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java index ff600ef862..74d39c1a59 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorder.java @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.audio; import android.content.Context; +import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.os.ParcelFileDescriptor; @@ -25,13 +26,15 @@ public class AudioRecorder { private static final ExecutorService executor = SignalExecutors.newCachedSingleThreadExecutor("signal-AudioRecorder"); - private final Context context; + private final Context context; + private final AudioRecorderFocusManager audioFocusManager; private Recorder recorder; private Uri captureUri; public AudioRecorder(@NonNull Context context) { this.context = context; + audioFocusManager = AudioRecorderFocusManager.create(context, focusChange -> stopRecording()); } public void startRecording() { @@ -52,6 +55,10 @@ public class AudioRecorder { .createForDraftAttachmentAsync(context, () -> Log.i(TAG, "Write successful."), e -> Log.w(TAG, "Error during recording", e)); recorder = Build.VERSION.SDK_INT >= 26 ? new MediaRecorderWrapper() : new AudioCodec(); + int focusResult = audioFocusManager.requestAudioFocus(); + if (focusResult != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { + Log.w(TAG, "Could not gain audio focus. Received result code " + focusResult); + } recorder.start(fds[1]); } catch (IOException e) { Log.w(TAG, e); @@ -70,6 +77,7 @@ public class AudioRecorder { return; } + audioFocusManager.abandonAudioFocus(); recorder.stop(); try { diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorderFocusManager.kt b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorderFocusManager.kt new file mode 100644 index 0000000000..6ff3c2c57f --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioRecorderFocusManager.kt @@ -0,0 +1,62 @@ +package org.thoughtcrime.securesms.audio + +import android.content.Context +import android.media.AudioAttributes +import android.media.AudioFocusRequest +import android.media.AudioManager +import android.media.AudioManager.OnAudioFocusChangeListener +import android.os.Build +import androidx.annotation.RequiresApi +import org.thoughtcrime.securesms.util.ServiceUtil + +abstract class AudioRecorderFocusManager(val context: Context) { + protected val audioManager: AudioManager = ServiceUtil.getAudioManager(context) + + abstract fun requestAudioFocus(): Int + abstract fun abandonAudioFocus(): Int + + companion object { + @JvmStatic + fun create(context: Context, changeListener: OnAudioFocusChangeListener): AudioRecorderFocusManager { + return if (Build.VERSION.SDK_INT >= 26) { + AudioRecorderFocusManager26(context, changeListener) + } else { + AudioRecorderFocusManagerLegacy(context, changeListener) + } + } + } +} + +@RequiresApi(26) +private class AudioRecorderFocusManager26(context: Context, changeListener: OnAudioFocusChangeListener) : AudioRecorderFocusManager(context) { + val audioFocusRequest: AudioFocusRequest + + init { + val audioAttributes = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .build() + audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) + .setAudioAttributes(audioAttributes) + .setOnAudioFocusChangeListener(changeListener) + .build() + } + + override fun requestAudioFocus(): Int { + return audioManager.requestAudioFocus(audioFocusRequest) + } + + override fun abandonAudioFocus(): Int { + return audioManager.abandonAudioFocusRequest(audioFocusRequest) + } +} + +private class AudioRecorderFocusManagerLegacy(context: Context, val changeListener: OnAudioFocusChangeListener) : AudioRecorderFocusManager(context) { + override fun requestAudioFocus(): Int { + return audioManager.requestAudioFocus(changeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) + } + + override fun abandonAudioFocus(): Int { + return audioManager.abandonAudioFocus(changeListener) + } +}