Gain temporary audio focus during voice memo recording.

This commit is contained in:
Nicholas 2022-11-09 11:02:23 -05:00 committed by Cody Henthorne
parent fca412b47d
commit f1fafa6516
2 changed files with 71 additions and 1 deletions

View file

@ -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;
@ -26,12 +27,14 @@ public class AudioRecorder {
private static final ExecutorService executor = SignalExecutors.newCachedSingleThreadExecutor("signal-AudioRecorder");
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 {

View file

@ -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)
}
}