Use Settings.System.DEFAULT_RINGTONE_URI for ringing notifications (#4310)

* Use `Settings.System.DEFAULT_RINGTONE_URI` for ringing notifications

This replaces `RingtoneManager.getActualDefaultRingtoneUri`, it should get the same audio file and avoid some reported issues about not having permission to load the audio file.
This commit is contained in:
Jorge Martin Espinosa 2025-02-27 13:57:43 +01:00 committed by GitHub
parent ab71b11351
commit 0d2e651c1b
4 changed files with 12 additions and 27 deletions

View file

@ -11,7 +11,7 @@ import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.media.AudioManager import android.media.AudioManager
import android.media.RingtoneManager import android.provider.Settings
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.PendingIntentCompat import androidx.core.app.PendingIntentCompat
import androidx.core.app.Person import androidx.core.app.Person
@ -109,8 +109,6 @@ class RingingCallNotificationCreator @Inject constructor(
false false
) )
// TODO use a fallback ringtone if the default ringtone is not available
val ringtoneUri = runCatching { RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE) }.getOrNull()
return NotificationCompat.Builder(context, notificationChannelId) return NotificationCompat.Builder(context, notificationChannelId)
.setSmallIcon(CommonDrawables.ic_notification_small) .setSmallIcon(CommonDrawables.ic_notification_small)
.setPriority(NotificationCompat.PRIORITY_MAX) .setPriority(NotificationCompat.PRIORITY_MAX)
@ -126,10 +124,8 @@ class RingingCallNotificationCreator @Inject constructor(
setContentText(textContent) setContentText(textContent)
// Else the content text is set by the style (will be "Incoming call") // Else the content text is set by the style (will be "Incoming call")
} }
if (ringtoneUri != null) {
setSound(ringtoneUri, AudioManager.STREAM_RING)
}
} }
.setSound(Settings.System.DEFAULT_RINGTONE_URI, AudioManager.STREAM_RING)
.setTimeoutAfter(ElementCallConfig.RINGING_CALL_DURATION_SECONDS.seconds.inWholeMilliseconds) .setTimeoutAfter(ElementCallConfig.RINGING_CALL_DURATION_SECONDS.seconds.inWholeMilliseconds)
.setContentIntent(answerIntent) .setContentIntent(answerIntent)
.setDeleteIntent(declineIntent) .setDeleteIntent(declineIntent)

View file

@ -7,18 +7,16 @@
package io.element.android.libraries.push.impl.notifications.channels package io.element.android.libraries.push.impl.notifications.channels
import android.content.Context
import android.media.AudioAttributes import android.media.AudioAttributes
import android.media.AudioManager import android.media.AudioManager
import android.media.RingtoneManager
import android.os.Build import android.os.Build
import android.provider.Settings
import androidx.annotation.ChecksSdkIntAtLeast import androidx.annotation.ChecksSdkIntAtLeast
import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.appconfig.NotificationConfig import io.element.android.appconfig.NotificationConfig
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.SingleIn import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.R
import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.strings.StringProvider
@ -60,7 +58,6 @@ private fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSI
@SingleIn(AppScope::class) @SingleIn(AppScope::class)
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultNotificationChannels @Inject constructor( class DefaultNotificationChannels @Inject constructor(
@ApplicationContext private val context: Context,
private val notificationManager: NotificationManagerCompat, private val notificationManager: NotificationManagerCompat,
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
) : NotificationChannels { ) : NotificationChannels {
@ -153,8 +150,6 @@ class DefaultNotificationChannels @Inject constructor(
) )
// Register a channel for incoming call notifications which will ring the device when received // Register a channel for incoming call notifications which will ring the device when received
// TODO use a fallback ringtone if the default ringtone is not available
val ringtoneUri = runCatching { RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE) }.getOrNull()
notificationManager.createNotificationChannel( notificationManager.createNotificationChannel(
NotificationChannelCompat.Builder( NotificationChannelCompat.Builder(
RINGING_CALL_NOTIFICATION_CHANNEL_ID, RINGING_CALL_NOTIFICATION_CHANNEL_ID,
@ -162,18 +157,14 @@ class DefaultNotificationChannels @Inject constructor(
) )
.setName(stringProvider.getString(R.string.notification_channel_ringing_calls).ifEmpty { "Ringing calls" }) .setName(stringProvider.getString(R.string.notification_channel_ringing_calls).ifEmpty { "Ringing calls" })
.setVibrationEnabled(true) .setVibrationEnabled(true)
.apply { .setSound(
if (ringtoneUri != null) { Settings.System.DEFAULT_RINGTONE_URI,
setSound( AudioAttributes.Builder()
ringtoneUri, .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
AudioAttributes.Builder() .setLegacyStreamType(AudioManager.STREAM_RING)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.setLegacyStreamType(AudioManager.STREAM_RING) .build()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) )
.build()
)
}
}
.setDescription(stringProvider.getString(R.string.notification_channel_ringing_calls)) .setDescription(stringProvider.getString(R.string.notification_channel_ringing_calls))
.setLightsEnabled(true) .setLightsEnabled(true)
.setLightColor(accentColor) .setLightColor(accentColor)

View file

@ -10,7 +10,6 @@ package io.element.android.libraries.push.impl.notifications.channels
import android.os.Build import android.os.Build
import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.services.toolbox.test.strings.FakeStringProvider
import io.mockk.every import io.mockk.every
@ -65,7 +64,6 @@ class NotificationChannelsTest {
private fun createNotificationChannels( private fun createNotificationChannels(
notificationManager: NotificationManagerCompat = mockk(relaxed = true), notificationManager: NotificationManagerCompat = mockk(relaxed = true),
) = DefaultNotificationChannels( ) = DefaultNotificationChannels(
context = InstrumentationRegistry.getInstrumentation().targetContext,
notificationManager = notificationManager, notificationManager = notificationManager,
stringProvider = FakeStringProvider(), stringProvider = FakeStringProvider(),
) )

View file

@ -331,5 +331,5 @@ fun createNotificationCreator(
fun createNotificationChannels(): NotificationChannels { fun createNotificationChannels(): NotificationChannels {
val context = RuntimeEnvironment.getApplication() val context = RuntimeEnvironment.getApplication()
return DefaultNotificationChannels(context, NotificationManagerCompat.from(context), FakeStringProvider("")) return DefaultNotificationChannels(NotificationManagerCompat.from(context), FakeStringProvider(""))
} }