All checks were successful
Build APK / build-apk (push) Successful in 1m47s
Für das Kamera-Problem: mehrere Geräte auswählen und ihre Erreichbarkeit über längere Zeit überwachen — jeder Ausfall wird mit Uhrzeit protokolliert. - MonitorService: schlanker Vordergrund-Dienst, hält den Prozess am Leben, damit die Überwachung bei Display aus / App-Wechsel weiterläuft - Plugin startMonitor/stopMonitor/getMonitorStatus: pingt die Geräte im gewählten Intervall, Wechsel erreichbar↔weg erzeugt ein monitorEvent; WifiLock gegen WLAN-Schlaf, Heads-up-Benachrichtigung bei Ausfall - Monitor-Seite (protokoll/[id]/monitor): Geräte-Mehrfachauswahl, Intervallwahl, Live-Ereignisliste, frühere Überwachungen mit Ausfallzahl - Überwachung läuft beim Verlassen der Seite weiter; Rückkehr nimmt den Stand wieder auf (getMonitorStatus) - Manifest: MonitorService + FOREGROUND_SERVICE_DATA_SYNC, POST_NOTIFICATIONS - Kachel "Geräte-Monitor" im Werkzeuge-Raster Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
81 lines
2.9 KiB
Kotlin
81 lines
2.9 KiB
Kotlin
package de.data_it_solution.netdiag
|
|
|
|
import android.app.Notification
|
|
import android.app.NotificationChannel
|
|
import android.app.NotificationManager
|
|
import android.app.Service
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.pm.ServiceInfo
|
|
import android.os.Build
|
|
import android.os.IBinder
|
|
import androidx.core.app.NotificationCompat
|
|
|
|
/**
|
|
* Schlanker Vordergrund-Dienst für den Geräte-Monitor.
|
|
*
|
|
* Er hält den App-Prozess am Leben, solange die Überwachung läuft — damit
|
|
* Android die Mess-Schleife bei ausgeschaltetem Display oder App-Wechsel nicht
|
|
* beendet. Die eigentliche Ping-Logik läuft im NetDiagScannerPlugin; dieser
|
|
* Dienst zeigt nur die dauerhafte Benachrichtigung.
|
|
*/
|
|
class MonitorService : Service() {
|
|
|
|
override fun onBind(intent: Intent?): IBinder? = null
|
|
|
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
val text = intent?.getStringExtra(EXTRA_TEXT) ?: "Geräte-Überwachung läuft"
|
|
val notification = buildNotification(text)
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
startForeground(NOTIF_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
|
|
} else {
|
|
startForeground(NOTIF_ID, notification)
|
|
}
|
|
return START_STICKY
|
|
}
|
|
|
|
private fun buildNotification(text: String): Notification {
|
|
ensureChannel(this)
|
|
return NotificationCompat.Builder(this, CHANNEL_ID)
|
|
.setContentTitle("NetDiag — Geräte-Monitor")
|
|
.setContentText(text)
|
|
.setSmallIcon(android.R.drawable.ic_menu_compass)
|
|
.setOngoing(true)
|
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
.build()
|
|
}
|
|
|
|
companion object {
|
|
const val CHANNEL_ID = "netdiag-monitor"
|
|
const val NOTIF_ID = 4711
|
|
const val EXTRA_TEXT = "text"
|
|
|
|
/** Benachrichtigungskanal anlegen (idempotent) */
|
|
fun ensureChannel(ctx: Context) {
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
|
|
val mgr = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
if (mgr.getNotificationChannel(CHANNEL_ID) == null) {
|
|
mgr.createNotificationChannel(
|
|
NotificationChannel(
|
|
CHANNEL_ID,
|
|
"Geräte-Monitor",
|
|
NotificationManager.IMPORTANCE_LOW,
|
|
),
|
|
)
|
|
}
|
|
}
|
|
|
|
fun start(ctx: Context, text: String) {
|
|
val i = Intent(ctx, MonitorService::class.java).putExtra(EXTRA_TEXT, text)
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
ctx.startForegroundService(i)
|
|
} else {
|
|
ctx.startService(i)
|
|
}
|
|
}
|
|
|
|
fun stop(ctx: Context) {
|
|
ctx.stopService(Intent(ctx, MonitorService::class.java))
|
|
}
|
|
}
|
|
}
|