Skip to content

Commit 6852ab4

Browse files
pigeon: Add binding for NotificationChannel.soundResourceName
1 parent 6d02c6b commit 6852ab4

File tree

5 files changed

+63
-5
lines changed

5 files changed

+63
-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 a `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: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
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.net.Uri
68
import android.os.Bundle
79
import android.util.Log
810
import androidx.annotation.Keep
@@ -41,28 +43,50 @@ fun toPigeonPerson(person: androidx.core.app.Person): Person {
4143
)
4244
}
4345

46+
/** The Android resource URL for the given resource. */
47+
// Based on: https://stackoverflow.com/a/38340580
48+
fun Context.resourceUrl(resourceId: Int): Uri = with(resources) {
49+
Uri.Builder()
50+
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
51+
.authority(getResourcePackageName(resourceId))
52+
.appendPath(getResourceTypeName(resourceId))
53+
.appendPath(getResourceEntryName(resourceId))
54+
.build()
55+
}
56+
4457
private class AndroidNotificationHost(val context: Context)
45-
: AndroidNotificationHostApi {
58+
: AndroidNotificationHostApi {
4659
override fun getNotificationChannels(): List<NotificationChannel> {
4760
return NotificationManagerCompat.from(context)
4861
.notificationChannelsCompat
4962
.map { NotificationChannel(
5063
it.id,
5164
it.importance.toLong(),
5265
it.name?.toString(),
53-
it.shouldShowLights()
66+
it.shouldShowLights(),
67+
it.sound?.toString(),
68+
it.vibrationPattern,
5469
) }
5570
}
5671

5772
override fun deleteNotificationChannel(channelId: String) {
5873
NotificationManagerCompat.from(context).deleteNotificationChannel(channelId)
5974
}
6075

76+
@SuppressLint(
77+
// For `getIdentifier`. TODO make a cleaner API.
78+
"DiscouragedApi")
6179
override fun createNotificationChannel(channel: NotificationChannel) {
6280
val notificationChannel = NotificationChannelCompat
6381
.Builder(channel.id, channel.importance.toInt()).apply {
6482
channel.name?.let { setName(it) }
6583
channel.lightsEnabled?.let { setLightsEnabled(it) }
84+
channel.soundResourceName?.let {
85+
val resourceId = context.resources.getIdentifier(
86+
it, "raw", context.packageName)
87+
setSound(context.resourceUrl(resourceId),
88+
AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build())
89+
}
6690
channel.vibrationPattern?.let { setVibrationPattern(it) }
6791
}.build()
6892
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 a `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 a `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
@@ -126,6 +126,7 @@ void main() {
126126
..name.equals('Messages')
127127
..importance.equals(NotificationImportance.high)
128128
..lightsEnabled.equals(true)
129+
..soundResourceName.isNull()
129130
..vibrationPattern.isNotNull().deepEquals(
130131
NotificationChannelManager.kVibrationPattern)
131132
;
@@ -874,6 +875,7 @@ extension NotificationChannelChecks on Subject<NotificationChannel> {
874875
Subject<int> get importance => has((x) => x.importance, 'importance');
875876
Subject<String?> get name => has((x) => x.name, 'name');
876877
Subject<bool?> get lightsEnabled => has((x) => x.lightsEnabled, 'lightsEnabled');
878+
Subject<String?> get soundResourceName => has((x) => x.soundResourceName, 'soundResourceName');
877879
Subject<Int64List?> get vibrationPattern => has((x) => x.vibrationPattern, 'vibrationPattern');
878880
}
879881

0 commit comments

Comments
 (0)