diff --git a/stream-video-android-core/api/stream-video-android-core.api b/stream-video-android-core/api/stream-video-android-core.api index 78171e6a4a..9c1edce460 100644 --- a/stream-video-android-core/api/stream-video-android-core.api +++ b/stream-video-android-core/api/stream-video-android-core.api @@ -4472,18 +4472,13 @@ public final class io/getstream/video/android/core/socket/SocketState$NotConnect } public final class io/getstream/video/android/core/sounds/Sounds { - public fun ()V - public fun (Ljava/lang/Integer;Ljava/lang/Integer;)V - public synthetic fun (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Ljava/lang/Integer; - public final fun component2 ()Ljava/lang/Integer; - public final fun copy (Ljava/lang/Integer;Ljava/lang/Integer;)Lio/getstream/video/android/core/sounds/Sounds; - public static synthetic fun copy$default (Lio/getstream/video/android/core/sounds/Sounds;Ljava/lang/Integer;Ljava/lang/Integer;ILjava/lang/Object;)Lio/getstream/video/android/core/sounds/Sounds; - public fun equals (Ljava/lang/Object;)Z - public final fun getIncomingCallSound ()Ljava/lang/Integer; - public final fun getOutgoingCallSound ()Ljava/lang/Integer; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; + public static final field Companion Lio/getstream/video/android/core/sounds/Sounds$Companion; + public static final field DEVICE_INCOMING_RINGTONE I + public fun (Landroid/content/Context;Ljava/lang/Integer;Ljava/lang/Integer;)V + public synthetic fun (Landroid/content/Context;Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V +} + +public final class io/getstream/video/android/core/sounds/Sounds$Companion { } public final class io/getstream/video/android/core/utils/AndroidUtilsKt { diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt index 180dc5ccb0..34394ae278 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt @@ -99,7 +99,7 @@ public class StreamVideoBuilder @JvmOverloads constructor( private val runForegroundServiceForCalls: Boolean = true, private val callServiceConfig: CallServiceConfig? = null, private val localSfuAddress: String? = null, - private val sounds: Sounds = Sounds(), + private val sounds: Sounds = Sounds(context), private val crashOnMissingPermission: Boolean = false, private val permissionCheck: StreamPermissionCheck = DefaultStreamPermissionCheck(), private val audioUsage: Int = defaultAudioUsage, diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt index 9beb88a79f..ac967ea7fd 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/service/CallService.kt @@ -25,8 +25,8 @@ import android.content.Intent import android.content.IntentFilter import android.content.pm.ServiceInfo import android.media.MediaPlayer +import android.net.Uri import android.os.IBinder -import androidx.annotation.RawRes import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat import io.getstream.log.StreamLog @@ -424,7 +424,7 @@ internal open class CallService : Service() { when (it) { is RingingState.Incoming -> { if (!it.acceptedByMe) { - playCallSound(streamVideo.sounds.incomingCallSound) + playCallSound(streamVideo.sounds.incomingCallSoundUri, mediaPlayer) } else { stopCallSound() // Stops sound sooner than Active. More responsive. } @@ -432,7 +432,7 @@ internal open class CallService : Service() { is RingingState.Outgoing -> { if (!it.acceptedByCallee) { - playCallSound(streamVideo.sounds.outgoingCallSound) + playCallSound(streamVideo.sounds.outgoingCallSoundUri, mediaPlayer) } else { stopCallSound() // Stops sound sooner than Active. More responsive. } @@ -490,13 +490,13 @@ internal open class CallService : Service() { } } - private fun playCallSound(@RawRes sound: Int?) { - sound?.let { + private fun playCallSound(soundUri: Uri?, mediaPlayer: MediaPlayer?) { + if (soundUri != null && mediaPlayer != null) { try { - mediaPlayer?.let { - if (!it.isPlaying) { - setMediaPlayerDataSource(it, sound) - it.start() + with(mediaPlayer) { + if (!isPlaying) { + setMediaPlayerDataSource(this, soundUri) + start() } } } catch (e: IllegalStateException) { @@ -505,13 +505,9 @@ internal open class CallService : Service() { } } - private fun setMediaPlayerDataSource(mediaPlayer: MediaPlayer, @RawRes resId: Int) { + private fun setMediaPlayerDataSource(mediaPlayer: MediaPlayer, uri: Uri) { mediaPlayer.reset() - val afd = resources.openRawResourceFd(resId) - if (afd != null) { - mediaPlayer.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length) - afd.close() - } + mediaPlayer.setDataSource(applicationContext, uri) mediaPlayer.isLooping = true mediaPlayer.prepare() } diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/sounds/Sounds.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/sounds/Sounds.kt index ececedd5a9..3417750424 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/sounds/Sounds.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/sounds/Sounds.kt @@ -16,16 +16,51 @@ package io.getstream.video.android.core.sounds +import android.content.Context +import android.media.RingtoneManager +import android.net.Uri import androidx.annotation.RawRes +import io.getstream.log.taggedLogger import io.getstream.video.android.core.R /** * Contains all the sounds that the SDK uses. * - * @param incomingCallSound Resource used as a ringtone for incoming calls. - * @param outgoingCallSound Resource used as a ringing tone for outgoing calls. + * @param incomingCallSoundResId Resource to be used as a ringtone for incoming calls. Set to [DEVICE_INCOMING_RINGTONE] to use the device ringtone. + * @param outgoingCallSoundResId Resource to be used as a ringing tone for outgoing calls. */ -data class Sounds( - @RawRes val incomingCallSound: Int? = R.raw.call_incoming_sound, - @RawRes val outgoingCallSound: Int? = R.raw.call_outgoing_sound, -) +class Sounds( + private val context: Context, + @RawRes private val incomingCallSoundResId: Int? = DEVICE_INCOMING_RINGTONE, + @RawRes private val outgoingCallSoundResId: Int? = R.raw.call_outgoing_sound, +) { + private val logger by taggedLogger("StreamVideo:Sounds") + + internal val incomingCallSoundUri: Uri? + get() = if (incomingCallSoundResId == DEVICE_INCOMING_RINGTONE) { + RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE) ?: run { + logger.w { "Device ringtone was null. Falling back to default incoming call sound." } + parseSoundUri(R.raw.call_incoming_sound) + } + } else { + parseSoundUri(incomingCallSoundResId) + } + + internal val outgoingCallSoundUri: Uri? + get() = if (outgoingCallSoundResId == DEVICE_INCOMING_RINGTONE) { + logger.w { + "Cannot assign DEVICE_INCOMING_RINGTONE to Sounds#outgoingCallSoundResId. Falling back to default outgoing call sound." + } + parseSoundUri(R.raw.call_outgoing_sound) + } else { + parseSoundUri(outgoingCallSoundResId) + } + + private fun parseSoundUri(@RawRes soundResId: Int?) = soundResId?.let { + Uri.parse("android.resource://${context.packageName}/$soundResId") + } + + companion object { + @RawRes const val DEVICE_INCOMING_RINGTONE = -1 + } +}