mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-25 05:27:42 +00:00
Improve voice note Bluetooth state handling.
This commit is contained in:
committed by
Nicholas Tinsley
parent
ecf576e9b9
commit
5cb10cd054
@@ -25,14 +25,14 @@ sealed interface BluetoothVoiceNoteUtil {
|
||||
fun destroy()
|
||||
|
||||
companion object {
|
||||
fun create(context: Context, listener: () -> Unit, bluetoothPermissionDeniedHandler: () -> Unit): BluetoothVoiceNoteUtil {
|
||||
fun create(context: Context, listener: (Boolean) -> Unit, bluetoothPermissionDeniedHandler: () -> Unit): BluetoothVoiceNoteUtil {
|
||||
return if (Build.VERSION.SDK_INT >= 31) BluetoothVoiceNoteUtil31(listener) else BluetoothVoiceNoteUtilLegacy(context, listener, bluetoothPermissionDeniedHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(31)
|
||||
private class BluetoothVoiceNoteUtil31(val listener: () -> Unit) : BluetoothVoiceNoteUtil {
|
||||
private class BluetoothVoiceNoteUtil31(val listener: (Boolean) -> Unit) : BluetoothVoiceNoteUtil {
|
||||
override fun connectBluetoothScoConnection() {
|
||||
val audioManager = ApplicationDependencies.getAndroidCallAudioManager()
|
||||
val device: AudioDeviceInfo? = audioManager.connectedBluetoothDevice
|
||||
@@ -40,13 +40,15 @@ private class BluetoothVoiceNoteUtil31(val listener: () -> Unit) : BluetoothVoic
|
||||
val result: Boolean = audioManager.setCommunicationDevice(device)
|
||||
if (result) {
|
||||
Log.d(TAG, "Successfully set Bluetooth device as active communication device.")
|
||||
listener(true)
|
||||
} else {
|
||||
Log.d(TAG, "Found Bluetooth device but failed to set it as active communication device.")
|
||||
listener(false)
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Could not find Bluetooth device in list of communications devices, falling back to current input.")
|
||||
listener(false)
|
||||
}
|
||||
listener()
|
||||
}
|
||||
|
||||
override fun disconnectBluetoothScoConnection() {
|
||||
@@ -64,15 +66,23 @@ private class BluetoothVoiceNoteUtil31(val listener: () -> Unit) : BluetoothVoic
|
||||
* @param listener This will be executed on the main thread after the Bluetooth connection connects, or if it doesn't.
|
||||
* @param bluetoothPermissionDeniedHandler called when we detect the Bluetooth permission has been denied to our app.
|
||||
*/
|
||||
private class BluetoothVoiceNoteUtilLegacy(val context: Context, val listener: () -> Unit, val bluetoothPermissionDeniedHandler: () -> Unit) : BluetoothVoiceNoteUtil {
|
||||
private class BluetoothVoiceNoteUtilLegacy(val context: Context, val listener: (Boolean) -> Unit, val bluetoothPermissionDeniedHandler: () -> Unit) : BluetoothVoiceNoteUtil {
|
||||
private val commandAndControlThread: HandlerThread = SignalExecutors.getAndStartHandlerThread("voice-note-audio", ThreadUtil.PRIORITY_IMPORTANT_BACKGROUND_THREAD)
|
||||
private val uiThreadHandler = Handler(context.mainLooper)
|
||||
private val audioHandler: SignalAudioHandler = SignalAudioHandler(commandAndControlThread.looper)
|
||||
private val deviceUpdatedListener: AudioDeviceUpdatedListener = object : AudioDeviceUpdatedListener {
|
||||
override fun onAudioDeviceUpdated() {
|
||||
if (signalBluetoothManager.state == SignalBluetoothManager.State.CONNECTED) {
|
||||
Log.d(TAG, "Bluetooth SCO connected. Starting voice note recording on UI thread.")
|
||||
uiThreadHandler.post { listener() }
|
||||
when (signalBluetoothManager.state) {
|
||||
SignalBluetoothManager.State.CONNECTED -> {
|
||||
Log.d(TAG, "Bluetooth SCO connected. Starting voice note recording on UI thread.")
|
||||
uiThreadHandler.post { listener(true) }
|
||||
}
|
||||
SignalBluetoothManager.State.ERROR,
|
||||
SignalBluetoothManager.State.PERMISSION_DENIED -> {
|
||||
Log.w(TAG, "Unable to complete Bluetooth connection due to ${signalBluetoothManager.state}. Starting voice note recording anyway on UI thread.")
|
||||
uiThreadHandler.post { listener(false) }
|
||||
}
|
||||
else -> Log.d(TAG, "Current Bluetooth connection state: ${signalBluetoothManager.state}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +115,7 @@ private class BluetoothVoiceNoteUtilLegacy(val context: Context, val listener: (
|
||||
bluetoothPermissionDeniedHandler()
|
||||
hasWarnedAboutBluetooth = true
|
||||
}
|
||||
listener()
|
||||
listener(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
@@ -304,7 +305,6 @@ import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
@@ -513,7 +513,7 @@ public class ConversationParentFragment extends Fragment
|
||||
|
||||
voiceNoteMediaController = new VoiceNoteMediaController(requireActivity(), true);
|
||||
voiceRecorderWakeLock = new VoiceRecorderWakeLock(requireActivity());
|
||||
bluetoothVoiceNoteUtil = BluetoothVoiceNoteUtil.Companion.create(requireContext(), this::beginRecording, this::onBluetoothPermissionDenied);
|
||||
bluetoothVoiceNoteUtil = BluetoothVoiceNoteUtil.Companion.create(requireContext(), this::onBluetoothConnectionAttempt, this::onBluetoothPermissionDenied);
|
||||
|
||||
// TODO [alex] LargeScreenSupport -- Should be removed once we move to multi-pane layout.
|
||||
new FullscreenHelper(requireActivity()).showSystemUI();
|
||||
@@ -3306,6 +3306,11 @@ public class ConversationParentFragment extends Fragment
|
||||
}
|
||||
}
|
||||
|
||||
private Unit onBluetoothConnectionAttempt(Boolean success) {
|
||||
beginRecording();
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
private Unit beginRecording() {
|
||||
Vibrator vibrator = ServiceUtil.getVibrator(requireContext());
|
||||
vibrator.vibrate(20);
|
||||
|
||||
@@ -47,7 +47,7 @@ class VoiceMessageRecordingDelegate(
|
||||
private val voiceRecorderWakeLock = VoiceRecorderWakeLock(fragment.requireActivity())
|
||||
private val bluetoothVoiceNoteUtil = BluetoothVoiceNoteUtil.create(
|
||||
fragment.requireContext(),
|
||||
this::beginRecording,
|
||||
this::onBluetoothConnectionAttempt,
|
||||
this::onBluetoothPermissionDenied
|
||||
)
|
||||
|
||||
@@ -104,6 +104,10 @@ class VoiceMessageRecordingDelegate(
|
||||
bluetoothVoiceNoteUtil.connectBluetoothScoConnection()
|
||||
}
|
||||
|
||||
private fun onBluetoothConnectionAttempt(success: Boolean) {
|
||||
beginRecording()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun beginRecording() {
|
||||
val vibrator = ServiceUtil.getVibrator(fragment.requireContext())
|
||||
|
||||
Reference in New Issue
Block a user