From 20e1f542779b1c9027449e4e9875814e2f0fa05a Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 5 Mar 2024 13:08:43 +0100 Subject: [PATCH] play ringback sound on android 6/7 --- .../services/AppRTCAudioManager.java | 28 +++++++++++++++++++ .../services/CallIntegration.java | 10 +++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/AppRTCAudioManager.java b/src/main/java/eu/siacs/conversations/services/AppRTCAudioManager.java index 2cd3ac346..d9eaeee48 100644 --- a/src/main/java/eu/siacs/conversations/services/AppRTCAudioManager.java +++ b/src/main/java/eu/siacs/conversations/services/AppRTCAudioManager.java @@ -16,6 +16,7 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.media.AudioDeviceInfo; import android.media.AudioManager; +import android.media.ToneGenerator; import android.util.Log; import androidx.annotation.Nullable; @@ -25,11 +26,14 @@ import com.google.common.collect.ImmutableSet; import eu.siacs.conversations.Config; import eu.siacs.conversations.utils.AppRTCUtils; +import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import org.webrtc.ThreadUtils; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; /** AppRTCAudioManager manages all audio related parts of the AppRTC demo. */ public class AppRTCAudioManager { @@ -66,6 +70,7 @@ public class AppRTCAudioManager { private final BroadcastReceiver wiredHeadsetReceiver; // Callback method for changes in audio focus. @Nullable private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener; + private ScheduledFuture ringBackFuture; public AppRTCAudioManager(final Context context) { apprtcContext = context; @@ -454,6 +459,29 @@ public class AppRTCAudioManager { ContextCompat.getMainExecutor(apprtcContext).execute(runnable); } + public void startRingBack() { + this.ringBackFuture = + JingleConnectionManager.SCHEDULED_EXECUTOR_SERVICE.scheduleAtFixedRate( + () -> { + final var toneGenerator = + new ToneGenerator( + AudioManager.STREAM_MUSIC, + CallIntegration.DEFAULT_VOLUME); + toneGenerator.startTone(ToneGenerator.TONE_CDMA_DIAL_TONE_LITE, 750); + }, + 0, + 3, + TimeUnit.SECONDS); + } + + public void stopRingBack() { + final var future = this.ringBackFuture; + if (future == null || future.isDone()) { + return; + } + future.cancel(true); + } + /** AudioManager state. */ public enum AudioManagerState { UNINITIALIZED, diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegration.java b/src/main/java/eu/siacs/conversations/services/CallIntegration.java index 378dd6277..0074d7079 100644 --- a/src/main/java/eu/siacs/conversations/services/CallIntegration.java +++ b/src/main/java/eu/siacs/conversations/services/CallIntegration.java @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean; public class CallIntegration extends Connection { - private static final int DEFAULT_VOLUME = 80; + public static final int DEFAULT_VOLUME = 80; private final Context context; @@ -309,7 +309,13 @@ public class CallIntegration extends Connection { @Override public void onStateChanged(final int state) { Log.d(Config.LOGTAG, "onStateChanged(" + state + ")"); - // TODO devices before selfManaged() will likely have to play their own ringback sound + if (notSelfManaged()) { + if (state == STATE_DIALING) { + requireAppRtcAudioManager().startRingBack(); + } else { + requireAppRtcAudioManager().stopRingBack(); + } + } if (state == STATE_ACTIVE) { playConnectedSound(); } else if (state == STATE_DISCONNECTED) {