fix(#65): request POST_NOTIFICATIONS runtime permission on Android 13+ (#97)

* fix(#65): request POST_NOTIFICATIONS runtime permission on Android 13+

On API 33+ the manifest declaration alone is not enough — the app must
request POST_NOTIFICATIONS via ActivityResultContracts.RequestPermission
at runtime before it can show any notification, including the foreground
service notification from ChatNotificationService.

- Added rememberLauncherForActivityResult for POST_NOTIFICATIONS
- Added LaunchedEffect(Unit) that fires the permission request on first
  composition when running on API 33+ and permission is not yet granted
- The next lifecycle event (ON_STOP → NotificationHelper.start) picks
  up the permission if granted

* fix: add missing import android.os.Build for POST_NOTIFICATIONS permission check

* fix: add missing import for rememberLauncherForActivityResult (androidx.activity.compose)

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-06-19 22:15:47 +03:00
1 parent 27a896c634
commit cc52442be3
1 file changed
+24
@@ -1,5 +1,8 @@
package com.m57.hermescontrol.ui.chat
import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.LinearEasing
@@ -85,6 +88,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.m57.hermescontrol.notification.NotificationHelper
@@ -136,6 +140,26 @@ fun ChatScreen(
}
}
// Request POST_NOTIFICATIONS runtime permission on Android 13+ (API 33).
// The manifest declaration alone is insufficient — on API 33+ the system
// requires a runtime permission prompt before the app can post any
// notification, including the foreground service notification.
val requestNotificationPermission =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
) { /* granted — next lifecycle event will pick it up */ }
LaunchedEffect(Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val permission = android.Manifest.permission.POST_NOTIFICATIONS
if (
ContextCompat.checkSelfPermission(context, permission) !=
android.content.pm.PackageManager.PERMISSION_GRANTED
) {
requestNotificationPermission.launch(permission)
}
}
}
// Auto-scroll to bottom on new messages
LaunchedEffect(state.messages.size, state.currentStreamingText) {
if (state.messages.isNotEmpty()) {