From 13f1101338181fe4f75f651249248ed111c0ffaa Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 8 May 2026 01:06:45 +0000 Subject: [PATCH] fix(scheduled-posts): explicit POST_NOTIFICATIONS check before notify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lint flagged the notify() call as MissingPermission because there was no visible check that POST_NOTIFICATIONS was granted. Gate the call behind areNotificationsEnabled() — matching the pattern used in EventNotificationConsumer — and catch SecurityException for the narrow window where permission could be revoked between the check and the notify(). --- .../service/scheduledposts/ScheduledPostNotifier.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/scheduledposts/ScheduledPostNotifier.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/scheduledposts/ScheduledPostNotifier.kt index 37f57c45e..6ac5b4741 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/scheduledposts/ScheduledPostNotifier.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/scheduledposts/ScheduledPostNotifier.kt @@ -98,6 +98,11 @@ object ScheduledPostNotifier { tapIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, ) + val notificationManager = NotificationManagerCompat.from(context) + // POST_NOTIFICATIONS is runtime-granted on Android 13+; bail out + // explicitly so lint doesn't flag the notify() call and so a denied + // user doesn't see a misleading no-op log. + if (!notificationManager.areNotificationsEnabled()) return val builder = NotificationCompat .Builder(context, channelId) @@ -110,8 +115,11 @@ object ScheduledPostNotifier { .setCategory(NotificationCompat.CATEGORY_STATUS) .setAutoCancel(true) .setWhen(System.currentTimeMillis()) - // Silently no-ops on Android 13+ if POST_NOTIFICATIONS isn't granted. - NotificationManagerCompat.from(context).notify(notId, builder.build()) + try { + notificationManager.notify(notId, builder.build()) + } catch (_: SecurityException) { + // Race: permission revoked between the check above and notify(). + } } private fun ensureChannel(context: Context) {