使用引用资源ID的声音URI时,Android通知频道声音停止工作

使用引用资源ID的声音URI时,Android通知频道声音停止工作,android,android-notifications,android-8.0-oreo,android-9.0-pie,Android,Android Notifications,Android 8.0 Oreo,Android 9.0 Pie,我们已经为运行在Oreo和更高版本上的设备创建了通知通道,这些设备使用位于/res/raw文件夹中的自定义通知声音。最近,当用户升级我们的应用程序时,通知声音停止工作,通知只会震动设备 我们已确认卸载/重新安装或清除应用程序数据可以解决此问题。然而,为了让通知声音在不需要重新安装的情况下再次适用于所有人,我们需要删除并重新创建这些频道 我们按如下方式创建通知通道: fun initNotificationChannel(channel: PSSNotificationChannel) {

我们已经为运行在Oreo和更高版本上的设备创建了通知通道,这些设备使用位于
/res/raw
文件夹中的自定义通知声音。最近,当用户升级我们的应用程序时,通知声音停止工作,通知只会震动设备

我们已确认卸载/重新安装或清除应用程序数据可以解决此问题。然而,为了让通知声音在不需要重新安装的情况下再次适用于所有人,我们需要删除并重新创建这些频道

我们按如下方式创建通知通道:

fun initNotificationChannel(channel: PSSNotificationChannel) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val id = channel.id
            val name = context.getString(channel.nameResId)
            val importance = channel.importance
            val channel = NotificationChannel(id, name, importance)

            ...

            // Default sound
            val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/" + R.raw.notification)
            val audioAttributes = AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build()
            channel.setSound(soundUri, audioAttributes)

            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
            notificationManager?.createNotificationChannel(channel)
        }
    }
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/" + R.raw.notification)
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/raw/notification")

我已验证该文件仍然存在于
/res/raw
中。而导致这种情况的提交似乎只是一些添加/修改到
/res
文件夹的文件。

似乎是这个问题将
声音URI设置为如下所示:

fun initNotificationChannel(channel: PSSNotificationChannel) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val id = channel.id
            val name = context.getString(channel.nameResId)
            val importance = channel.importance
            val channel = NotificationChannel(id, name, importance)

            ...

            // Default sound
            val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/" + R.raw.notification)
            val audioAttributes = AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build()
            channel.setSound(soundUri, audioAttributes)

            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
            notificationManager?.createNotificationChannel(channel)
        }
    }
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/" + R.raw.notification)
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/raw/notification")
它看起来像是
R.raw.notification
的值从
2131689979
(声音工作的版本)更改为
2131755515
(声音不工作的版本)。由于您无法使用通知频道更改通知声音,我几乎可以肯定该频道正在尝试使用旧资源id(
android)解析
soundUri
。resource://our.package.name/2131689979

我认为更好的方法是直接按名称引用文件,如下所示:

fun initNotificationChannel(channel: PSSNotificationChannel) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val id = channel.id
            val name = context.getString(channel.nameResId)
            val importance = channel.importance
            val channel = NotificationChannel(id, name, importance)

            ...

            // Default sound
            val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/" + R.raw.notification)
            val audioAttributes = AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build()
            channel.setSound(soundUri, audioAttributes)

            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
            notificationManager?.createNotificationChannel(channel)
        }
    }
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/" + R.raw.notification)
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/raw/notification")

我还注意到像Facebook Messenger和Slack这样的应用程序使用一个公共通知文件夹,他们可能只是在上面复制文件并引用确切的路径。这似乎还允许用户重新选择应用程序提供的声音,因为它在文件系统中可见。

就是这样!我已经看了一段时间了。起初,该应用程序提供的声音效果非常好,但通常在几周后就停止了。非常感谢。我尝试过以您建议的方式直接使用字符串名称设置通知频道的声音,但我仍然收到一个FileNotFound异常,因为它试图查找旧的资源id。(即,
MediaPlayer:无法打开android。)。resource:///2131099651: java.io.FileNotFoundException
)从推送中的频道id到声音uri的实际映射是什么?事实证明,即使资源id发生变化,在uri中使用字符串也会起作用,但前提是从另一个应用程序版本升级,该版本也使用了基于字符串的uri。因此,如果您以前的版本在uri中使用了资源ID,那么使用基于字符串的uri的较新版本将不起作用。如果遇到此问题,请使用星号@是的,我们必须使用基于字符串的资源将所有用户迁移到新的通知通道。我们通过在频道ID中添加
version
后缀来实现这一点,这样我们就可以查找/删除旧频道,并创建新频道(如果它们不存在的话)。