Skip to content

Commit 1f641b7

Browse files
1 parent c89af39 commit 1f641b7

File tree

6 files changed

+257
-18
lines changed

6 files changed

+257
-18
lines changed

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

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,49 @@ class FlutterError (
4444
val details: Any? = null
4545
) : Throwable()
4646

47+
/**
48+
* Corresponds to `androidx.core.app.NotificationChannelCompat`
49+
*
50+
* See: https://developer.android.com/reference/androidx/core/app/NotificationChannelCompat
51+
*
52+
* Generated class from Pigeon that represents data sent in messages.
53+
*/
54+
data class NotificationChannel (
55+
val id: String,
56+
/**
57+
* Specifies the importance level of notifications
58+
* to be posted on this channel.
59+
*
60+
* Must be a valid constant from [NotificationImportance].
61+
*/
62+
val importance: Long,
63+
val name: String? = null,
64+
val lightsEnabled: Boolean? = null,
65+
val vibrationPattern: LongArray? = null
66+
67+
) {
68+
companion object {
69+
@Suppress("LocalVariableName")
70+
fun fromList(__pigeon_list: List<Any?>): NotificationChannel {
71+
val id = __pigeon_list[0] as String
72+
val importance = __pigeon_list[1].let { num -> if (num is Int) num.toLong() else num as Long }
73+
val name = __pigeon_list[2] as String?
74+
val lightsEnabled = __pigeon_list[3] as Boolean?
75+
val vibrationPattern = __pigeon_list[4] as LongArray?
76+
return NotificationChannel(id, importance, name, lightsEnabled, vibrationPattern)
77+
}
78+
}
79+
fun toList(): List<Any?> {
80+
return listOf(
81+
id,
82+
importance,
83+
name,
84+
lightsEnabled,
85+
vibrationPattern,
86+
)
87+
}
88+
}
89+
4790
/**
4891
* Corresponds to `android.app.PendingIntent`.
4992
*
@@ -218,25 +261,30 @@ private object NotificationsPigeonCodec : StandardMessageCodec() {
218261
return when (type) {
219262
129.toByte() -> {
220263
return (readValue(buffer) as? List<Any?>)?.let {
221-
PendingIntent.fromList(it)
264+
NotificationChannel.fromList(it)
222265
}
223266
}
224267
130.toByte() -> {
225268
return (readValue(buffer) as? List<Any?>)?.let {
226-
InboxStyle.fromList(it)
269+
PendingIntent.fromList(it)
227270
}
228271
}
229272
131.toByte() -> {
230273
return (readValue(buffer) as? List<Any?>)?.let {
231-
Person.fromList(it)
274+
InboxStyle.fromList(it)
232275
}
233276
}
234277
132.toByte() -> {
235278
return (readValue(buffer) as? List<Any?>)?.let {
236-
MessagingStyleMessage.fromList(it)
279+
Person.fromList(it)
237280
}
238281
}
239282
133.toByte() -> {
283+
return (readValue(buffer) as? List<Any?>)?.let {
284+
MessagingStyleMessage.fromList(it)
285+
}
286+
}
287+
134.toByte() -> {
240288
return (readValue(buffer) as? List<Any?>)?.let {
241289
MessagingStyle.fromList(it)
242290
}
@@ -246,33 +294,43 @@ private object NotificationsPigeonCodec : StandardMessageCodec() {
246294
}
247295
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
248296
when (value) {
249-
is PendingIntent -> {
297+
is NotificationChannel -> {
250298
stream.write(129)
251299
writeValue(stream, value.toList())
252300
}
253-
is InboxStyle -> {
301+
is PendingIntent -> {
254302
stream.write(130)
255303
writeValue(stream, value.toList())
256304
}
257-
is Person -> {
305+
is InboxStyle -> {
258306
stream.write(131)
259307
writeValue(stream, value.toList())
260308
}
261-
is MessagingStyleMessage -> {
309+
is Person -> {
262310
stream.write(132)
263311
writeValue(stream, value.toList())
264312
}
265-
is MessagingStyle -> {
313+
is MessagingStyleMessage -> {
266314
stream.write(133)
267315
writeValue(stream, value.toList())
268316
}
317+
is MessagingStyle -> {
318+
stream.write(134)
319+
writeValue(stream, value.toList())
320+
}
269321
else -> super.writeValue(stream, value)
270322
}
271323
}
272324
}
273325

274326
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
275327
interface AndroidNotificationHostApi {
328+
/**
329+
* Corresponds to `androidx.core.app.NotificationManagerCompat.createNotificationChannel`.
330+
*
331+
* See: https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#createNotificationChannel(androidx.core.app.NotificationChannelCompat)
332+
*/
333+
fun createNotificationChannel(channel: NotificationChannel)
276334
/**
277335
* Corresponds to `android.app.NotificationManager.notify`,
278336
* combined with `androidx.core.app.NotificationCompat.Builder`.
@@ -317,6 +375,24 @@ interface AndroidNotificationHostApi {
317375
@JvmOverloads
318376
fun setUp(binaryMessenger: BinaryMessenger, api: AndroidNotificationHostApi?, messageChannelSuffix: String = "") {
319377
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
378+
run {
379+
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.zulip.AndroidNotificationHostApi.createNotificationChannel$separatedMessageChannelSuffix", codec)
380+
if (api != null) {
381+
channel.setMessageHandler { message, reply ->
382+
val args = message as List<Any?>
383+
val channelArg = args[0] as NotificationChannel
384+
val wrapped: List<Any?> = try {
385+
api.createNotificationChannel(channelArg)
386+
listOf(null)
387+
} catch (exception: Throwable) {
388+
wrapError(exception)
389+
}
390+
reply.reply(wrapped)
391+
}
392+
} else {
393+
channel.setMessageHandler(null)
394+
}
395+
}
320396
run {
321397
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.zulip.AndroidNotificationHostApi.notify$separatedMessageChannelSuffix", codec)
322398
if (api != null) {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.content.Intent
66
import android.os.Bundle
77
import android.util.Log
88
import androidx.annotation.Keep
9+
import androidx.core.app.NotificationChannelCompat
910
import androidx.core.app.NotificationCompat
1011
import androidx.core.app.NotificationManagerCompat
1112
import androidx.core.graphics.drawable.IconCompat
@@ -42,6 +43,16 @@ fun toPigeonPerson(person: androidx.core.app.Person): Person {
4243

4344
private class AndroidNotificationHost(val context: Context)
4445
: AndroidNotificationHostApi {
46+
override fun createNotificationChannel(channel: NotificationChannel) {
47+
val notificationChannel = NotificationChannelCompat
48+
.Builder(channel.id, channel.importance.toInt()).apply {
49+
channel.name?.let { setName(it) }
50+
channel.lightsEnabled?.let { setLightsEnabled(it) }
51+
channel.vibrationPattern?.let { setVibrationPattern(it) }
52+
}.build()
53+
NotificationManagerCompat.from(context).createNotificationChannel(notificationChannel)
54+
}
55+
4556
@SuppressLint(
4657
// If permission is missing, `notify` will throw an exception.
4758
// Which hopefully will propagate to Dart, and then it's up to Dart code to handle it.

lib/host/android_notifications.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
export './android_notifications.g.dart';
22

3+
/// For use in [NotificationChannel.importance].
4+
///
5+
/// See:
6+
/// https://developer.android.com/reference/android/app/NotificationChannel#setImportance(int)
7+
/// https://developer.android.com/reference/android/app/NotificationChannel#getImportance()
8+
abstract class NotificationImportance {
9+
/// Corresponds to `IMPORTANCE_UNSPECIFIED`:
10+
/// https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#IMPORTANCE_UNSPECIFIED()
11+
static const unspecified = -1000;
12+
13+
/// Corresponds to `IMPORTANCE_NONE`:
14+
/// https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#IMPORTANCE_NONE()
15+
static const none = 0;
16+
17+
/// Corresponds to `IMPORTANCE_MIN`:
18+
/// https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#IMPORTANCE_MIN()
19+
static const min = 1;
20+
21+
/// Corresponds to `IMPORTANCE_LOW`:
22+
/// https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#IMPORTANCE_LOW()
23+
static const low = 2;
24+
25+
/// Corresponds to `IMPORTANCE_DEFAULT`:
26+
/// https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#IMPORTANCE_DEFAULT()
27+
static const default_ = 3;
28+
29+
/// Corresponds to `IMPORTANCE_HIGH`:
30+
/// https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#IMPORTANCE_HIGH()
31+
static const high = 4;
32+
33+
/// Corresponds to `IMPORTANCE_MAX`:
34+
/// https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#IMPORTANCE_MAX()
35+
static const max = 5;
36+
}
37+
338
/// For use in [PendingIntent.flags].
439
///
540
/// See: https://developer.android.com/reference/android/app/PendingIntent#constants_1

lib/host/android_notifications.g.dart

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,54 @@ PlatformException _createConnectionError(String channelName) {
1515
);
1616
}
1717

18+
/// Corresponds to `androidx.core.app.NotificationChannelCompat`
19+
///
20+
/// See: https://developer.android.com/reference/androidx/core/app/NotificationChannelCompat
21+
class NotificationChannel {
22+
NotificationChannel({
23+
required this.id,
24+
required this.importance,
25+
this.name,
26+
this.lightsEnabled,
27+
this.vibrationPattern,
28+
});
29+
30+
String id;
31+
32+
/// Specifies the importance level of notifications
33+
/// to be posted on this channel.
34+
///
35+
/// Must be a valid constant from [NotificationImportance].
36+
int importance;
37+
38+
String? name;
39+
40+
bool? lightsEnabled;
41+
42+
Int64List? vibrationPattern;
43+
44+
Object encode() {
45+
return <Object?>[
46+
id,
47+
importance,
48+
name,
49+
lightsEnabled,
50+
vibrationPattern,
51+
];
52+
}
53+
54+
static NotificationChannel decode(Object result) {
55+
result as List<Object?>;
56+
return NotificationChannel(
57+
id: result[0]! as String,
58+
importance: result[1]! as int,
59+
name: result[2] as String?,
60+
lightsEnabled: result[3] as bool?,
61+
vibrationPattern: result[4] as Int64List?,
62+
);
63+
}
64+
}
65+
1866
/// Corresponds to `android.app.PendingIntent`.
1967
///
2068
/// See: https://developer.android.com/reference/android/app/PendingIntent
@@ -197,21 +245,24 @@ class _PigeonCodec extends StandardMessageCodec {
197245
const _PigeonCodec();
198246
@override
199247
void writeValue(WriteBuffer buffer, Object? value) {
200-
if (value is PendingIntent) {
248+
if (value is NotificationChannel) {
201249
buffer.putUint8(129);
202250
writeValue(buffer, value.encode());
203-
} else if (value is InboxStyle) {
251+
} else if (value is PendingIntent) {
204252
buffer.putUint8(130);
205253
writeValue(buffer, value.encode());
206-
} else if (value is Person) {
254+
} else if (value is InboxStyle) {
207255
buffer.putUint8(131);
208256
writeValue(buffer, value.encode());
209-
} else if (value is MessagingStyleMessage) {
257+
} else if (value is Person) {
210258
buffer.putUint8(132);
211259
writeValue(buffer, value.encode());
212-
} else if (value is MessagingStyle) {
260+
} else if (value is MessagingStyleMessage) {
213261
buffer.putUint8(133);
214262
writeValue(buffer, value.encode());
263+
} else if (value is MessagingStyle) {
264+
buffer.putUint8(134);
265+
writeValue(buffer, value.encode());
215266
} else {
216267
super.writeValue(buffer, value);
217268
}
@@ -221,14 +272,16 @@ class _PigeonCodec extends StandardMessageCodec {
221272
Object? readValueOfType(int type, ReadBuffer buffer) {
222273
switch (type) {
223274
case 129:
224-
return PendingIntent.decode(readValue(buffer)!);
275+
return NotificationChannel.decode(readValue(buffer)!);
225276
case 130:
226-
return InboxStyle.decode(readValue(buffer)!);
277+
return PendingIntent.decode(readValue(buffer)!);
227278
case 131:
228-
return Person.decode(readValue(buffer)!);
279+
return InboxStyle.decode(readValue(buffer)!);
229280
case 132:
230-
return MessagingStyleMessage.decode(readValue(buffer)!);
281+
return Person.decode(readValue(buffer)!);
231282
case 133:
283+
return MessagingStyleMessage.decode(readValue(buffer)!);
284+
case 134:
232285
return MessagingStyle.decode(readValue(buffer)!);
233286
default:
234287
return super.readValueOfType(type, buffer);
@@ -249,6 +302,31 @@ class AndroidNotificationHostApi {
249302

250303
final String __pigeon_messageChannelSuffix;
251304

305+
/// Corresponds to `androidx.core.app.NotificationManagerCompat.createNotificationChannel`.
306+
///
307+
/// See: https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat#createNotificationChannel(androidx.core.app.NotificationChannelCompat)
308+
Future<void> createNotificationChannel(NotificationChannel channel) async {
309+
final String __pigeon_channelName = 'dev.flutter.pigeon.zulip.AndroidNotificationHostApi.createNotificationChannel$__pigeon_messageChannelSuffix';
310+
final BasicMessageChannel<Object?> __pigeon_channel = BasicMessageChannel<Object?>(
311+
__pigeon_channelName,
312+
pigeonChannelCodec,
313+
binaryMessenger: __pigeon_binaryMessenger,
314+
);
315+
final List<Object?>? __pigeon_replyList =
316+
await __pigeon_channel.send(<Object?>[channel]) as List<Object?>?;
317+
if (__pigeon_replyList == null) {
318+
throw _createConnectionError(__pigeon_channelName);
319+
} else if (__pigeon_replyList.length > 1) {
320+
throw PlatformException(
321+
code: __pigeon_replyList[0]! as String,
322+
message: __pigeon_replyList[1] as String?,
323+
details: __pigeon_replyList[2],
324+
);
325+
} else {
326+
return;
327+
}
328+
}
329+
252330
/// Corresponds to `android.app.NotificationManager.notify`,
253331
/// combined with `androidx.core.app.NotificationCompat.Builder`.
254332
///

0 commit comments

Comments
 (0)