使用引用资源ID的声音URI时,Android通知通道声音无法正常工作。

4
我们已经为运行在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)
        }
    }

我核实了文件仍存在于/res/raw。导致这个问题的提交只是在/res文件夹中添加/修改了一些文件。
1个回答

6

看起来问题出在将 soundUri 设置为如下值:

val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/" + R.raw.notification)

看起来 R.raw.notification 的值已经从声音工作的版本的 2131689979 变成了声音不工作的版本的 2131755515。而且由于你无法使用通知渠道更改通知声音,我几乎可以确定该渠道正在尝试使用旧的资源 ID (android.resource://our.package.name/2131689979) 解析 soundUri
我认为更好的方法是直接按名称引用文件,如下所示:
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                    context.applicationContext.packageName + "/raw/notification")

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

就是这样!我已经看了一段时间了。首先,应用程序提供的声音完美地工作,但后来它突然停止了,通常是几周后。非常感谢。 - hobbs
我尝试按照您建议的方式直接使用字符串名称设置通知通道的声音,但仍然会出现FileNotFound异常,因为它尝试查找旧的资源ID。(即MediaPlayer: Couldn't open android.resource://<appname>/2131099651: java.io.FileNotFoundException)实际上是什么将推送中的通道ID映射到声音URI? - efeder
事实证明,在URI中使用字符串确实有效,即使资源ID发生变化,但前提是从另一个使用基于字符串的URI的应用程序版本升级。因此,如果您之前的版本在URI中使用了资源ID,则使用基于字符串的URI的新版本将无法正常工作。 - efeder
我在 Android 的问题跟踪器上找到了这个问题。如果你也遇到了这个问题,请点赞支持一下。https://issuetracker.google.com/issues/131303134 - efeder
是的,我们不得不将所有用户迁移到基于字符串资源的新通知渠道。我们通过在我们的渠道ID中添加“version”后缀来实现这一点,这样我们就可以找到/删除旧渠道并创建新的渠道(如果它们不存在)。 - Steve Strates
谢谢,最终我删除了原有的频道并创建了新的带有新ID的频道! - efeder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接