Skip to content

Commit 8dea78a

Browse files
authored
fix(notification): scheduled notifications not working (#909)
* fix(notification): scheduled notifications not working * do not use toJSON since it doesnt work on isolation pattern * fmt
1 parent 61edbbe commit 8dea78a

11 files changed

Lines changed: 102 additions & 56 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"notification": patch
3+
"notification-js": patch
4+
---
5+
6+
Fixes deserialization and implementation bugs with scheduled notifications on Android.

examples/api/vite.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import process from "process";
1111
// https://vitejs.dev/config/
1212
export default defineConfig(async () => {
1313
const host =
14-
process.env.TAURI_PLATFORM === "android" ||
15-
process.env.TAURI_PLATFORM === "ios"
14+
process.env.TAURI_ENV_PLATFORM === "android" ||
15+
process.env.TAURI_ENV_PLATFORM === "ios"
1616
? await internalIpV4()
1717
: "localhost";
1818
return {

plugins/notification/android/src/main/AndroidManifest.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
</intent-filter>
1515
</receiver>
1616
</application>
17-
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
18-
<uses-permission android:name="android.permission.WAKE_LOCK"/>
19-
</manifest>
17+
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
18+
<uses-permission android:name="android.permission.WAKE_LOCK" />
19+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
20+
</manifest>

plugins/notification/android/src/main/java/Notification.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ class Notification {
8080
return null
8181
}
8282

83-
val isScheduled = schedule != null
84-
8583
companion object {
8684
fun buildNotificationPendingList(notifications: List<Notification>): List<PendingNotification> {
8785
val pendingNotifications = mutableListOf<PendingNotification>()

plugins/notification/android/src/main/java/NotificationPlugin.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) {
268268
@PermissionCallback
269269
private fun permissionsCallback(invoke: Invoke) {
270270
val permissionsResultJSON = JSObject()
271-
permissionsResultJSON.put("display", getPermissionState())
271+
permissionsResultJSON.put("permissionState", getPermissionState())
272272
invoke.resolve(permissionsResultJSON)
273273
}
274274

plugins/notification/android/src/main/java/NotificationSchedule.kt

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
package app.tauri.notification
66

77
import android.annotation.SuppressLint
8-
import android.content.ClipData.Item
98
import android.text.format.DateUtils
109
import com.fasterxml.jackson.annotation.JsonFormat
10+
import com.fasterxml.jackson.annotation.JsonProperty
1111
import com.fasterxml.jackson.core.JsonGenerator
1212
import com.fasterxml.jackson.core.JsonParser
1313
import com.fasterxml.jackson.core.JsonProcessingException
@@ -17,18 +17,33 @@ import com.fasterxml.jackson.databind.JsonNode
1717
import com.fasterxml.jackson.databind.SerializerProvider
1818
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
1919
import com.fasterxml.jackson.databind.annotation.JsonSerialize
20+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
2021
import com.fasterxml.jackson.databind.ser.std.StdSerializer
2122
import java.io.IOException
2223
import java.text.SimpleDateFormat
2324
import java.util.Calendar
2425
import java.util.Date
2526
import java.util.TimeZone
2627

27-
2828
const val JS_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
2929

3030
enum class NotificationInterval {
31-
Year, Month, TwoWeeks, Week, Day, Hour, Minute, Second
31+
@JsonProperty("year")
32+
Year,
33+
@JsonProperty("month")
34+
Month,
35+
@JsonProperty("twoWeeks")
36+
TwoWeeks,
37+
@JsonProperty("week")
38+
Week,
39+
@JsonProperty("day")
40+
Day,
41+
@JsonProperty("hour")
42+
Hour,
43+
@JsonProperty("minute")
44+
Minute,
45+
@JsonProperty("second")
46+
Second
3247
}
3348

3449
fun getIntervalTime(interval: NotificationInterval, count: Int): Long {
@@ -50,9 +65,24 @@ fun getIntervalTime(interval: NotificationInterval, count: Int): Long {
5065
@JsonSerialize(using = NotificationScheduleSerializer::class)
5166
sealed class NotificationSchedule {
5267
// At specific moment of time (with repeating option)
53-
class At(@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = JS_DATE_FORMAT) var date: Date, val repeating: Boolean = false, val allowWhileIdle: Boolean = false): NotificationSchedule()
54-
class Interval(val interval: DateMatch, val allowWhileIdle: Boolean = false): NotificationSchedule()
55-
class Every(val interval: NotificationInterval, val count: Int = 0, val allowWhileIdle: Boolean = false): NotificationSchedule()
68+
@JsonDeserialize
69+
class At: NotificationSchedule() {
70+
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = JS_DATE_FORMAT)
71+
lateinit var date: Date
72+
var repeating: Boolean = false
73+
var allowWhileIdle: Boolean = false
74+
}
75+
@JsonDeserialize
76+
class Interval: NotificationSchedule() {
77+
lateinit var interval: DateMatch
78+
var allowWhileIdle: Boolean = false
79+
}
80+
@JsonDeserialize
81+
class Every: NotificationSchedule() {
82+
lateinit var interval: NotificationInterval
83+
var count: Int = 0
84+
var allowWhileIdle: Boolean = false
85+
}
5686

5787
fun isRemovable(): Boolean {
5888
return when (this) {

plugins/notification/android/src/main/java/NotificationStorage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class NotificationStorage(private val context: Context, private val jsonMapper:
2020
val storage = getStorage(NOTIFICATION_STORE_ID)
2121
val editor = storage.edit()
2222
for (request in localNotifications) {
23-
if (request.isScheduled) {
23+
if (request.schedule != null) {
2424
val key: String = request.id.toString()
2525
editor.putString(key, request.sourceJson.toString())
2626
}

plugins/notification/android/src/main/java/TauriNotificationManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class TauriNotificationManager(
212212
createActionIntents(notification, mBuilder)
213213
// notificationId is a unique int for each notification that you must define
214214
val buildNotification = mBuilder.build()
215-
if (notification.isScheduled) {
215+
if (notification.schedule != null) {
216216
triggerScheduledNotification(buildNotification, notification)
217217
} else {
218218
notificationManager.notify(notification.id, buildNotification)
@@ -473,7 +473,7 @@ class TimedNotificationPublisher : BroadcastReceiver() {
473473
override fun onReceive(context: Context, intent: Intent) {
474474
val notificationManager =
475475
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
476-
val notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
476+
val notification = if (SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
477477
intent.getParcelableExtra(
478478
NOTIFICATION_KEY,
479479
android.app.Notification::class.java

plugins/notification/guest-js/index.ts

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -163,49 +163,57 @@ enum ScheduleEvery {
163163
Second = "second",
164164
}
165165

166-
type ScheduleData =
167-
| {
168-
at: {
166+
class Schedule {
167+
at:
168+
| {
169169
date: Date;
170170
repeating: boolean;
171171
allowWhileIdle: boolean;
172-
};
173-
}
174-
| {
175-
interval: {
172+
}
173+
| undefined;
174+
interval:
175+
| {
176176
interval: ScheduleInterval;
177177
allowWhileIdle: boolean;
178-
};
179-
}
180-
| {
181-
every: {
178+
}
179+
| undefined;
180+
every:
181+
| {
182182
interval: ScheduleEvery;
183183
count: number;
184184
allowWhileIdle: boolean;
185-
};
185+
}
186+
| undefined;
187+
188+
static at(date: Date, repeating = false, allowWhileIdle = false): Schedule {
189+
return {
190+
at: { date, repeating, allowWhileIdle },
191+
interval: undefined,
192+
every: undefined,
186193
};
187-
188-
class Schedule {
189-
schedule: ScheduleData;
190-
191-
private constructor(schedule: ScheduleData) {
192-
this.schedule = schedule;
193-
}
194-
195-
toJSON(): string {
196-
return JSON.stringify(this.schedule);
197-
}
198-
199-
static at(date: Date, repeating = false, allowWhileIdle = false) {
200-
return new Schedule({ at: { date, repeating, allowWhileIdle } });
201194
}
202195

203-
static interval(interval: ScheduleInterval, allowWhileIdle = false) {
204-
return new Schedule({ interval: { interval, allowWhileIdle } });
196+
static interval(
197+
interval: ScheduleInterval,
198+
allowWhileIdle = false,
199+
): Schedule {
200+
return {
201+
at: undefined,
202+
interval: { interval, allowWhileIdle },
203+
every: undefined,
204+
};
205205
}
206206

207-
static every(kind: ScheduleEvery, count: number, allowWhileIdle = false) {
208-
return new Schedule({ every: { interval: kind, count, allowWhileIdle } });
207+
static every(
208+
kind: ScheduleEvery,
209+
count: number,
210+
allowWhileIdle = false,
211+
): Schedule {
212+
return {
213+
at: undefined,
214+
interval: undefined,
215+
every: { interval: kind, count, allowWhileIdle },
216+
};
209217
}
210218
}
211219

plugins/notification/src/api-iife.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)