Initial commit: VesiscanBasic Android app
Port of MedilightV2 iOS app to Android with Kotlin + Jetpack Compose. Includes BLE connectivity, NIRS/Piezo sensor modes, Rive animations, interactive measurement history charts, and foldable device support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package com.example.medilightv2android.services
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.example.medilightv2android.R
|
||||
import com.example.medilightv2android.models.UrgencyLevel
|
||||
|
||||
class NotificationService private constructor(private val context: Context) {
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance: NotificationService? = null
|
||||
fun getInstance(context: Context): NotificationService =
|
||||
instance ?: synchronized(this) {
|
||||
instance ?: NotificationService(context.applicationContext).also { instance = it }
|
||||
}
|
||||
|
||||
private const val CHANNEL_ID = "bladder_urgency"
|
||||
private const val CHANNEL_NAME = "Bladder Monitoring"
|
||||
}
|
||||
|
||||
private var lastNotifiedUrgency: String? = null
|
||||
|
||||
init {
|
||||
createNotificationChannel()
|
||||
}
|
||||
|
||||
private fun createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
CHANNEL_NAME,
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
).apply {
|
||||
description = "Bladder level urgency notifications"
|
||||
enableVibration(true)
|
||||
}
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
fun sendUrgencyNotification(urgency: UrgencyLevel, volume: Int) {
|
||||
val urgencyKey = urgency.rawStringValue
|
||||
if (urgencyKey == "safe" || urgencyKey == lastNotifiedUrgency) return
|
||||
lastNotifiedUrgency = urgencyKey
|
||||
|
||||
val (title, body) = when (urgency) {
|
||||
UrgencyLevel.WARNING -> "Bladder Level Rising" to "Estimated $volume ml. Prepare for catheterization."
|
||||
UrgencyLevel.URGENT -> "Catheterization Needed" to "Estimated $volume ml. Please catheterize now."
|
||||
UrgencyLevel.SAFE -> return
|
||||
}
|
||||
|
||||
val priority = if (urgency == UrgencyLevel.URGENT)
|
||||
NotificationCompat.PRIORITY_MAX else NotificationCompat.PRIORITY_HIGH
|
||||
|
||||
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||
.setContentTitle(title)
|
||||
.setContentText(body)
|
||||
.setPriority(priority)
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
try {
|
||||
NotificationManagerCompat.from(context).notify(urgencyKey.hashCode(), notification)
|
||||
} catch (_: SecurityException) { }
|
||||
}
|
||||
|
||||
fun cancelAll() {
|
||||
lastNotifiedUrgency = null
|
||||
NotificationManagerCompat.from(context).cancelAll()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user