mirror of
https://github.com/oxen-io/session-android.git
synced 2025-06-08 22:58:33 +00:00
Fix bluetooth behavior.
This commit is contained in:
parent
6b47618351
commit
cd1bad0718
@ -55,7 +55,7 @@ public class WebRtcAudioOutputToggleButton extends AppCompatImageView {
|
||||
List<WebRtcAudioOutput> availableModes = buildOutputModeList(isHeadsetAvailable, isHandsetAvailable);
|
||||
|
||||
if (availableModes.size() > 2 || !isHandsetAvailable) showPicker(availableModes);
|
||||
else setAudioOutput(OUTPUT_MODES.get((outputIndex + 1) % OUTPUT_MODES.size()));
|
||||
else setAudioOutput(OUTPUT_MODES.get((outputIndex + 1) % OUTPUT_MODES.size()), true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -83,13 +83,16 @@ public class WebRtcAudioOutputToggleButton extends AppCompatImageView {
|
||||
this.isHeadsetAvailable = isHeadsetAvailable;
|
||||
}
|
||||
|
||||
public void setAudioOutput(@NonNull WebRtcAudioOutput audioOutput) {
|
||||
public void setAudioOutput(@NonNull WebRtcAudioOutput audioOutput, boolean notifyListener) {
|
||||
int oldIndex = outputIndex;
|
||||
outputIndex = resolveAudioOutputIndex(OUTPUT_MODES.lastIndexOf(audioOutput));
|
||||
|
||||
if (oldIndex != outputIndex) {
|
||||
refreshDrawableState();
|
||||
notifyListener();
|
||||
|
||||
if (notifyListener) {
|
||||
notifyListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,7 +103,7 @@ public class WebRtcAudioOutputToggleButton extends AppCompatImageView {
|
||||
private void showPicker(@NonNull List<WebRtcAudioOutput> availableModes) {
|
||||
RecyclerView rv = new RecyclerView(getContext());
|
||||
AudioOutputAdapter adapter = new AudioOutputAdapter(audioOutput -> {
|
||||
setAudioOutput(audioOutput);
|
||||
setAudioOutput(audioOutput, true);
|
||||
hidePicker();
|
||||
},
|
||||
availableModes);
|
||||
@ -138,7 +141,8 @@ public class WebRtcAudioOutputToggleButton extends AppCompatImageView {
|
||||
isHandsetAvailable = savedState.getBoolean(STATE_HANDSET_ENABLED);
|
||||
|
||||
setAudioOutput(OUTPUT_MODES.get(
|
||||
resolveAudioOutputIndex(savedState.getInt(STATE_OUTPUT_INDEX)))
|
||||
resolveAudioOutputIndex(savedState.getInt(STATE_OUTPUT_INDEX))),
|
||||
false
|
||||
);
|
||||
|
||||
super.onRestoreInstanceState(savedState.getParcelable(STATE_PARENT));
|
||||
|
@ -196,10 +196,6 @@ public class WebRtcCallView extends FrameLayout {
|
||||
micToggle.setChecked(isMicEnabled, false);
|
||||
}
|
||||
|
||||
public void setAudioOutput(WebRtcAudioOutput output) {
|
||||
audioToggle.setAudioOutput(output);
|
||||
}
|
||||
|
||||
public void setRemoteVideoEnabled(boolean isRemoteVideoEnabled) {
|
||||
if (isRemoteVideoEnabled) {
|
||||
remoteRenderContainer.setVisibility(View.VISIBLE);
|
||||
@ -333,7 +329,7 @@ public class WebRtcCallView extends FrameLayout {
|
||||
audioToggle.setControlAvailability(webRtcControls.enableHandsetInAudioToggle(),
|
||||
webRtcControls.enableHeadsetInAudioToggle());
|
||||
|
||||
audioToggle.setAudioOutput(webRtcControls.getAudioOutput());
|
||||
audioToggle.setAudioOutput(webRtcControls.getAudioOutput(), false);
|
||||
}
|
||||
|
||||
if (webRtcControls.displayCameraToggle()) {
|
||||
|
@ -482,10 +482,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
boolean isSpeaker = intent.getBooleanExtra(EXTRA_SPEAKER, false);
|
||||
AudioManager audioManager = ServiceUtil.getAudioManager(this);
|
||||
|
||||
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
audioManager.stopBluetoothSco();
|
||||
audioManager.setBluetoothScoOn(false);
|
||||
audioManager.setSpeakerphoneOn(true);
|
||||
bluetoothStateManager.setWantsConnection(false);
|
||||
audioManager.setSpeakerphoneOn(isSpeaker);
|
||||
|
||||
if (!localCameraState.isEnabled()) {
|
||||
@ -499,15 +496,8 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
||||
|
||||
private void handleSetBluetoothAudio(Intent intent) {
|
||||
boolean isBluetooth = intent.getBooleanExtra(EXTRA_BLUETOOTH, false);
|
||||
AudioManager audioManager = ServiceUtil.getAudioManager(this);
|
||||
|
||||
if (isBluetooth) {
|
||||
audioManager.startBluetoothSco();
|
||||
audioManager.setBluetoothScoOn(true);
|
||||
} else {
|
||||
audioManager.stopBluetoothSco();
|
||||
audioManager.setBluetoothScoOn(false);
|
||||
}
|
||||
bluetoothStateManager.setWantsConnection(isBluetooth);
|
||||
|
||||
if (!localCameraState.isEnabled()) {
|
||||
lockManager.updatePhoneState(getInCallPhoneState());
|
||||
|
@ -0,0 +1,143 @@
|
||||
package org.thoughtcrime.securesms.webrtc.audio;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioFocusRequest;
|
||||
import android.media.AudioManager;
|
||||
import android.media.SoundPool;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
|
||||
public abstract class AudioManagerCompat {
|
||||
|
||||
protected final AudioManager audioManager;
|
||||
|
||||
private AudioManagerCompat(@NonNull Context context) {
|
||||
audioManager = ServiceUtil.getAudioManager(context);
|
||||
}
|
||||
|
||||
abstract public SoundPool createSoundPool();
|
||||
abstract public void requestCallAudioFocus();
|
||||
abstract public void abandonCallAudioFocus();
|
||||
|
||||
public static AudioManagerCompat create(@NonNull Context context) {
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return new Api26AudioManagerCompat(context);
|
||||
} else if (Build.VERSION.SDK_INT >= 21) {
|
||||
return new Api21AudioManagerCompat(context);
|
||||
} else {
|
||||
return new Api19AudioManagerCompat(context);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(26)
|
||||
private static class Api26AudioManagerCompat extends AudioManagerCompat {
|
||||
|
||||
private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||
.build();
|
||||
|
||||
private AudioFocusRequest audioFocusRequest;
|
||||
|
||||
private Api26AudioManagerCompat(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundPool createSoundPool() {
|
||||
return new SoundPool.Builder()
|
||||
.setAudioAttributes(AUDIO_ATTRIBUTES)
|
||||
.setMaxStreams(1)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestCallAudioFocus() {
|
||||
if (audioFocusRequest != null) {
|
||||
throw new IllegalStateException("Already focused.");
|
||||
}
|
||||
|
||||
audioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
|
||||
.setAudioAttributes(AUDIO_ATTRIBUTES)
|
||||
.build();
|
||||
|
||||
int result = audioManager.requestAudioFocus(audioFocusRequest);
|
||||
|
||||
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
throw new IllegalStateException("Got " + result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abandonCallAudioFocus() {
|
||||
if (audioFocusRequest == null) {
|
||||
throw new IllegalStateException("Not focused.");
|
||||
}
|
||||
|
||||
int result = audioManager.abandonAudioFocusRequest(audioFocusRequest);
|
||||
|
||||
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
throw new IllegalStateException("Got " + result);
|
||||
}
|
||||
|
||||
audioFocusRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(21)
|
||||
private static class Api21AudioManagerCompat extends Api19AudioManagerCompat {
|
||||
|
||||
private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||
.setLegacyStreamType(AudioManager.STREAM_VOICE_CALL)
|
||||
.build();
|
||||
|
||||
private Api21AudioManagerCompat(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundPool createSoundPool() {
|
||||
return new SoundPool.Builder()
|
||||
.setAudioAttributes(AUDIO_ATTRIBUTES)
|
||||
.setMaxStreams(1)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Api19AudioManagerCompat extends AudioManagerCompat {
|
||||
|
||||
private Api19AudioManagerCompat(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundPool createSoundPool() {
|
||||
return new SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestCallAudioFocus() {
|
||||
int result = audioManager.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
|
||||
|
||||
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
throw new IllegalStateException("Got " + result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abandonCallAudioFocus() {
|
||||
int result = audioManager.abandonAudioFocus(null);
|
||||
|
||||
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
throw new IllegalStateException("Got " + result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class BluetoothStateManager {
|
||||
|
||||
private static final String TAG = BluetoothStateManager.class.getSimpleName();
|
||||
private static final String TAG = Log.tag(BluetoothStateManager.class);
|
||||
|
||||
private enum ScoConnection {
|
||||
DISCONNECTED,
|
||||
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.webrtc.audio;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
@ -109,7 +110,15 @@ public class IncomingRinger {
|
||||
mediaPlayer.setOnErrorListener(new MediaPlayerErrorListener());
|
||||
mediaPlayer.setDataSource(context, ringtoneUri);
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
|
||||
|
||||
if (Build.VERSION.SDK_INT <= 21) {
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
|
||||
} else {
|
||||
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING)
|
||||
.build());
|
||||
}
|
||||
|
||||
return mediaPlayer;
|
||||
} catch (IOException e) {
|
||||
|
@ -1,9 +1,12 @@
|
||||
package org.thoughtcrime.securesms.webrtc.audio;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
@ -40,7 +43,15 @@ public class OutgoingRinger {
|
||||
}
|
||||
|
||||
mediaPlayer = new MediaPlayer();
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
|
||||
|
||||
if (Build.VERSION.SDK_INT <= 21) {
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
|
||||
} else {
|
||||
mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||
.build());
|
||||
}
|
||||
mediaPlayer.setLooping(true);
|
||||
|
||||
String packageName = context.getPackageName();
|
||||
|
@ -25,19 +25,21 @@ public class SignalAudioManager {
|
||||
private final int connectedSoundId;
|
||||
private final int disconnectedSoundId;
|
||||
|
||||
private final AudioManagerCompat audioManagerCompat;
|
||||
|
||||
public SignalAudioManager(@NonNull Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
this.incomingRinger = new IncomingRinger(context);
|
||||
this.outgoingRinger = new OutgoingRinger(context);
|
||||
this.soundPool = new SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0);
|
||||
this.context = context.getApplicationContext();
|
||||
this.incomingRinger = new IncomingRinger(context);
|
||||
this.outgoingRinger = new OutgoingRinger(context);
|
||||
this.audioManagerCompat = AudioManagerCompat.create(context);
|
||||
this.soundPool = audioManagerCompat.createSoundPool();
|
||||
|
||||
this.connectedSoundId = this.soundPool.load(context, R.raw.webrtc_completed, 1);
|
||||
this.disconnectedSoundId = this.soundPool.load(context, R.raw.webrtc_disconnected, 1);
|
||||
}
|
||||
|
||||
public void initializeAudioForCall() {
|
||||
AudioManager audioManager = ServiceUtil.getAudioManager(context);
|
||||
audioManager.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE);
|
||||
audioManagerCompat.requestCallAudioFocus();
|
||||
}
|
||||
|
||||
public void startIncomingRinger(@Nullable Uri ringtoneUri, boolean vibrate) {
|
||||
@ -89,14 +91,8 @@ public class SignalAudioManager {
|
||||
soundPool.play(disconnectedSoundId, 1.0f, 1.0f, 0, 0, 1.0f);
|
||||
}
|
||||
|
||||
if (audioManager.isBluetoothScoOn()) {
|
||||
audioManager.setBluetoothScoOn(false);
|
||||
audioManager.stopBluetoothSco();
|
||||
}
|
||||
|
||||
audioManager.setSpeakerphoneOn(false);
|
||||
audioManager.setMicrophoneMute(false);
|
||||
audioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
audioManager.abandonAudioFocus(null);
|
||||
|
||||
audioManagerCompat.abandonCallAudioFocus();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user