diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 941b4d5..efadaff 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,9 @@
+
+
+
+
+
diff --git a/app/src/main/java/com/example/helios_location_finder/ListenerService.kt b/app/src/main/java/com/example/helios_location_finder/ListenerService.kt
new file mode 100644
index 0000000..acafb32
--- /dev/null
+++ b/app/src/main/java/com/example/helios_location_finder/ListenerService.kt
@@ -0,0 +1,80 @@
+package com.example.helios_location_finder
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.app.Service
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.IBinder
+import android.util.Log
+import androidx.core.content.ContextCompat
+
+class ListenerService : Service() {
+
+ companion object {
+ private const val TAG = "ListenerService"
+ private const val CHANNEL_ID = "helios_listener"
+ private const val NOTIFICATION_ID = 1
+
+ fun start(context: android.content.Context) {
+ val intent = Intent(context, ListenerService::class.java)
+ ContextCompat.startForegroundService(context, intent)
+ }
+ }
+
+ private val receiver = NtfyReceiver()
+
+ override fun onCreate() {
+ super.onCreate()
+ createNotificationChannel()
+ startForeground(NOTIFICATION_ID, buildNotification())
+
+ val filter = IntentFilter("io.heckel.ntfy.MESSAGE_RECEIVED")
+ ContextCompat.registerReceiver(
+ this, receiver, filter, ContextCompat.RECEIVER_EXPORTED
+ )
+ Log.d(TAG, "Listener service started, receiver registered")
+ }
+
+ override fun onDestroy() {
+ unregisterReceiver(receiver)
+ Log.d(TAG, "Listener service stopped, receiver unregistered")
+ super.onDestroy()
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ return START_STICKY
+ }
+
+ override fun onBind(intent: Intent?): IBinder? = null
+
+ private fun createNotificationChannel() {
+ val channel = NotificationChannel(
+ CHANNEL_ID,
+ "Helios Tracker",
+ NotificationManager.IMPORTANCE_LOW
+ ).apply {
+ description = "Keeps Helios Tracker listening for LOCATE commands"
+ setShowBadge(false)
+ }
+ getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
+ }
+
+ private fun buildNotification(): Notification {
+ val pendingIntent = PendingIntent.getActivity(
+ this, 0,
+ Intent(this, MainActivity::class.java),
+ PendingIntent.FLAG_IMMUTABLE
+ )
+
+ return Notification.Builder(this, CHANNEL_ID)
+ .setContentTitle("Helios Tracker")
+ .setContentText("Lauscht auf LOCATE-Anfragen")
+ .setSmallIcon(android.R.drawable.ic_menu_mylocation)
+ .setContentIntent(pendingIntent)
+ .setOngoing(true)
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/example/helios_location_finder/MainActivity.kt b/app/src/main/java/com/example/helios_location_finder/MainActivity.kt
index 451365c..40bdf26 100644
--- a/app/src/main/java/com/example/helios_location_finder/MainActivity.kt
+++ b/app/src/main/java/com/example/helios_location_finder/MainActivity.kt
@@ -50,6 +50,7 @@ class MainActivity : ComponentActivity() {
private val foregroundGranted = mutableStateOf(false)
private val backgroundGranted = mutableStateOf(false)
+ private val serviceRunning = mutableStateOf(false)
private val foregroundPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
@@ -62,11 +63,19 @@ class MainActivity : ComponentActivity() {
ActivityResultContracts.RequestPermission()
) { granted ->
backgroundGranted.value = granted
+ if (granted) startListenerService()
+ }
+
+ private val notificationPermissionLauncher = registerForActivityResult(
+ ActivityResultContracts.RequestPermission()
+ ) { granted ->
+ if (granted) startListenerService()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
checkPermissions()
+ startListenerService()
val listenTopic = mutableStateOf(Prefs.getListenTopic(this))
val replyTopic = mutableStateOf(Prefs.getReplyTopic(this))
@@ -133,6 +142,20 @@ class MainActivity : ComponentActivity() {
backgroundPermissionLauncher.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
}
+
+ private fun startListenerService() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ if (ContextCompat.checkSelfPermission(
+ this, Manifest.permission.POST_NOTIFICATIONS
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
+ return
+ }
+ }
+ ListenerService.start(this)
+ serviceRunning.value = true
+ }
}
@Composable