Skip to content

Commit ac4c34e

Browse files
pigeon: Add binding for NotificationChannel.soundResourceName
1 parent 3ed7a7b commit ac4c34e

File tree

5 files changed

+64
-5
lines changed

5 files changed

+64
-5
lines changed

android/app/src/main/kotlin/com/zulip/flutter/Notifications.g.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ data class NotificationChannel (
6262
val importance: Long,
6363
val name: String? = null,
6464
val lightsEnabled: Boolean? = null,
65+
/**
66+
* The name of the sound file resource.
67+
*
68+
* The resource ID is retrieved using
69+
* `android.content.res.Resources.getIdentifier`, which is then used to
70+
* generate an `android.resource://` URI. This URI is then passed
71+
* to the `NotificationChannelCompat` builder.
72+
*/
73+
val soundResourceName: String? = null,
6574
val vibrationPattern: LongArray? = null
6675

6776
) {
@@ -72,8 +81,9 @@ data class NotificationChannel (
7281
val importance = __pigeon_list[1].let { num -> if (num is Int) num.toLong() else num as Long }
7382
val name = __pigeon_list[2] as String?
7483
val lightsEnabled = __pigeon_list[3] as Boolean?
75-
val vibrationPattern = __pigeon_list[4] as LongArray?
76-
return NotificationChannel(id, importance, name, lightsEnabled, vibrationPattern)
84+
val soundResourceName = __pigeon_list[4] as String?
85+
val vibrationPattern = __pigeon_list[5] as LongArray?
86+
return NotificationChannel(id, importance, name, lightsEnabled, soundResourceName, vibrationPattern)
7787
}
7888
}
7989
fun toList(): List<Any?> {
@@ -82,6 +92,7 @@ data class NotificationChannel (
8292
importance,
8393
name,
8494
lightsEnabled,
95+
soundResourceName,
8596
vibrationPattern,
8697
)
8798
}

android/app/src/main/kotlin/com/zulip/flutter/ZulipPlugin.kt

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.zulip.flutter
22

33
import android.annotation.SuppressLint
4+
import android.content.ContentResolver
45
import android.content.Context
56
import android.content.Intent
7+
import android.media.AudioAttributes
8+
import android.net.Uri
69
import android.os.Bundle
710
import android.util.Log
811
import androidx.annotation.Keep
@@ -41,28 +44,50 @@ fun toPigeonPerson(person: androidx.core.app.Person): Person {
4144
)
4245
}
4346

47+
/** The Android resource URL for the given resource. */
48+
// Based on: https://stackoverflow.com/a/38340580
49+
fun Context.resourceUrl(resourceId: Int): Uri = with(resources) {
50+
Uri.Builder()
51+
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
52+
.authority(getResourcePackageName(resourceId))
53+
.appendPath(getResourceTypeName(resourceId))
54+
.appendPath(getResourceEntryName(resourceId))
55+
.build()
56+
}
57+
4458
private class AndroidNotificationHost(val context: Context)
45-
: AndroidNotificationHostApi {
59+
: AndroidNotificationHostApi {
4660
override fun getNotificationChannels(): List<NotificationChannel> {
4761
return NotificationManagerCompat.from(context)
4862
.notificationChannelsCompat
4963
.map { NotificationChannel(
5064
it.id,
5165
it.importance.toLong(),
5266
it.name?.toString(),
53-
it.shouldShowLights()
67+
it.shouldShowLights(),
68+
it.sound?.toString(),
69+
it.vibrationPattern,
5470
) }
5571
}
5672

5773
override fun deleteNotificationChannel(channelId: String) {
5874
NotificationManagerCompat.from(context).deleteNotificationChannel(channelId)
5975
}
6076

77+
@SuppressLint(
78+
// For `getIdentifier`. TODO make a cleaner API.
79+
"DiscouragedApi")
6180
override fun createNotificationChannel(channel: NotificationChannel) {
6281
val notificationChannel = NotificationChannelCompat
6382
.Builder(channel.id, channel.importance.toInt()).apply {
6483
channel.name?.let { setName(it) }
6584
channel.lightsEnabled?.let { setLightsEnabled(it) }
85+
channel.soundResourceName?.let {
86+
val resourceId = context.resources.getIdentifier(
87+
it, "raw", context.packageName)
88+
setSound(context.resourceUrl(resourceId),
89+
AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build())
90+
}
6691
channel.vibrationPattern?.let { setVibrationPattern(it) }
6792
}.build()
6893
NotificationManagerCompat.from(context).createNotificationChannel(notificationChannel)

lib/host/android_notifications.g.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class NotificationChannel {
2424
required this.importance,
2525
this.name,
2626
this.lightsEnabled,
27+
this.soundResourceName,
2728
this.vibrationPattern,
2829
});
2930

@@ -39,6 +40,14 @@ class NotificationChannel {
3940

4041
bool? lightsEnabled;
4142

43+
/// The name of the sound file resource.
44+
///
45+
/// The resource ID is retrieved using
46+
/// `android.content.res.Resources.getIdentifier`, which is then used to
47+
/// generate an `android.resource://` URI. This URI is then passed
48+
/// to the `NotificationChannelCompat` builder.
49+
String? soundResourceName;
50+
4251
Int64List? vibrationPattern;
4352

4453
Object encode() {
@@ -47,6 +56,7 @@ class NotificationChannel {
4756
importance,
4857
name,
4958
lightsEnabled,
59+
soundResourceName,
5060
vibrationPattern,
5161
];
5262
}
@@ -58,7 +68,8 @@ class NotificationChannel {
5868
importance: result[1]! as int,
5969
name: result[2] as String?,
6070
lightsEnabled: result[3] as bool?,
61-
vibrationPattern: result[4] as Int64List?,
71+
soundResourceName: result[4] as String?,
72+
vibrationPattern: result[5] as Int64List?,
6273
);
6374
}
6475
}

pigeon/notifications.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class NotificationChannel {
2020
required this.importance,
2121
this.name,
2222
this.lightsEnabled,
23+
this.soundResourceName,
2324
this.vibrationPattern,
2425
});
2526

@@ -33,6 +34,15 @@ class NotificationChannel {
3334

3435
final String? name;
3536
final bool? lightsEnabled;
37+
38+
/// The name of the sound file resource.
39+
///
40+
/// The resource ID is retrieved using
41+
/// `android.content.res.Resources.getIdentifier`, which is then used to
42+
/// generate an `android.resource://` URI. This URI is then passed
43+
/// to the `NotificationChannelCompat` builder.
44+
final String? soundResourceName;
45+
3646
final Int64List? vibrationPattern;
3747
}
3848

test/notifications/display_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ void main() {
127127
..name.equals('Messages')
128128
..importance.equals(NotificationImportance.high)
129129
..lightsEnabled.equals(true)
130+
..soundResourceName.isNull()
130131
..vibrationPattern.isNotNull().deepEquals(
131132
NotificationChannelManager.kVibrationPattern)
132133
;
@@ -875,6 +876,7 @@ extension NotificationChannelChecks on Subject<NotificationChannel> {
875876
Subject<int> get importance => has((x) => x.importance, 'importance');
876877
Subject<String?> get name => has((x) => x.name, 'name');
877878
Subject<bool?> get lightsEnabled => has((x) => x.lightsEnabled, 'lightsEnabled');
879+
Subject<String?> get soundResourceName => has((x) => x.soundResourceName, 'soundResourceName');
878880
Subject<Int64List?> get vibrationPattern => has((x) => x.vibrationPattern, 'vibrationPattern');
879881
}
880882

0 commit comments

Comments
 (0)