@@ -27,8 +27,11 @@ import com.google.android.gms.location.*
2727import com.google.gson.Gson
2828import dagger.hilt.android.AndroidEntryPoint
2929import kotlinx.coroutines.*
30+ import kotlinx.coroutines.flow.MutableSharedFlow
3031import kotlinx.coroutines.flow.MutableStateFlow
32+ import kotlinx.coroutines.flow.SharedFlow
3133import kotlinx.coroutines.flow.StateFlow
34+ import kotlinx.coroutines.flow.asSharedFlow
3235import java.util.*
3336import javax.inject.Inject
3437
@@ -106,6 +109,11 @@ class ScanningService : Service() {
106109 // Scan statistics
107110 val scanStats = MutableStateFlow (ScanStatistics ())
108111
112+ // Detection refresh event - emits when detections are added/updated
113+ // This ensures UI updates even if Room's Flow emissions fail with SQLCipher
114+ private val _detectionRefreshEvent = MutableSharedFlow <Unit >(replay = 0 , extraBufferCapacity = 1 )
115+ val detectionRefreshEvent: SharedFlow <Unit > = _detectionRefreshEvent .asSharedFlow()
116+
109117 // Learning mode - for capturing unknown device signatures
110118 val learningModeEnabled = MutableStateFlow (false )
111119 val learnedSignatures = MutableStateFlow <List <LearnedSignature >>(emptyList())
@@ -834,19 +842,24 @@ class ScanningService : Service() {
834842 // Check if we already have this detection (use unique SSID)
835843 val existing = det.ssid?.let { repository.getDetectionBySsid(it) }
836844 if (existing == null ) {
837- repository.insertDetection(det)
838-
839- // Alert and vibrate for high-severity anomalies
840- if (anomaly.severity == ThreatLevel .CRITICAL ||
841- anomaly.severity == ThreatLevel .HIGH ) {
842- alertUser(det)
843- }
844-
845- lastDetection.value = det
846- detectionCount.value = repository.getTotalDetectionCount()
847-
848- if (BuildConfig .DEBUG ) {
849- Log .w(TAG , " CELLULAR ANOMALY: ${anomaly.type.displayName} - ${anomaly.description} " )
845+ try {
846+ repository.insertDetection(det)
847+
848+ // Alert and vibrate for high-severity anomalies
849+ if (anomaly.severity == ThreatLevel .CRITICAL ||
850+ anomaly.severity == ThreatLevel .HIGH ) {
851+ alertUser(det)
852+ }
853+
854+ lastDetection.value = det
855+ detectionCount.value = repository.getTotalDetectionCount()
856+ _detectionRefreshEvent .tryEmit(Unit )
857+
858+ if (BuildConfig .DEBUG ) {
859+ Log .w(TAG , " CELLULAR ANOMALY: ${anomaly.type.displayName} - ${anomaly.description} " )
860+ }
861+ } catch (e: Exception ) {
862+ Log .e(TAG , " Error saving cellular detection: ${e.message} " , e)
850863 }
851864 }
852865 }
@@ -1051,18 +1064,23 @@ class ScanningService : Service() {
10511064 ? : det.ssid?.let { repository.getDetectionBySsid(it) }
10521065
10531066 if (existing == null ) {
1054- repository.insertDetection(det)
1055-
1056- if (anomaly.severity == ThreatLevel .CRITICAL ||
1057- anomaly.severity == ThreatLevel .HIGH ) {
1058- alertUser(det)
1059- }
1060-
1061- lastDetection.value = det
1062- detectionCount.value = repository.getTotalDetectionCount()
1063-
1064- if (BuildConfig .DEBUG ) {
1065- Log .w(TAG , " WIFI ANOMALY: ${anomaly.type.displayName} - ${anomaly.description} " )
1067+ try {
1068+ repository.insertDetection(det)
1069+
1070+ if (anomaly.severity == ThreatLevel .CRITICAL ||
1071+ anomaly.severity == ThreatLevel .HIGH ) {
1072+ alertUser(det)
1073+ }
1074+
1075+ lastDetection.value = det
1076+ detectionCount.value = repository.getTotalDetectionCount()
1077+ _detectionRefreshEvent .tryEmit(Unit )
1078+
1079+ if (BuildConfig .DEBUG ) {
1080+ Log .w(TAG , " WIFI ANOMALY: ${anomaly.type.displayName} - ${anomaly.description} " )
1081+ }
1082+ } catch (e: Exception ) {
1083+ Log .e(TAG , " Error saving WiFi detection: ${e.message} " , e)
10661084 }
10671085 }
10681086 }
@@ -1129,11 +1147,16 @@ class ScanningService : Service() {
11291147 detection?.let { det ->
11301148 val existing = det.macAddress?.let { repository.getDetectionByMacAddress(it) }
11311149 if (existing == null ) {
1132- repository.insertDetection(det)
1133- alertUser(det)
1134- lastDetection.value = det
1135- detectionCount.value = repository.getTotalDetectionCount()
1136- Log .w(TAG , " DRONE DETECTED: ${drone.manufacturer} at ${drone.estimatedDistance} " )
1150+ try {
1151+ repository.insertDetection(det)
1152+ alertUser(det)
1153+ lastDetection.value = det
1154+ detectionCount.value = repository.getTotalDetectionCount()
1155+ _detectionRefreshEvent .tryEmit(Unit )
1156+ Log .w(TAG , " DRONE DETECTED: ${drone.manufacturer} at ${drone.estimatedDistance} " )
1157+ } catch (e: Exception ) {
1158+ Log .e(TAG , " Error saving drone detection: ${e.message} " , e)
1159+ }
11371160 }
11381161 }
11391162 }
@@ -1154,18 +1177,23 @@ class ScanningService : Service() {
11541177 // Use timestamp-based unique ID for RF anomalies
11551178 val existing = repository.getDetectionBySsid(det.deviceName ? : " " )
11561179 if (existing == null ) {
1157- repository.insertDetection(det)
1158-
1159- if (anomaly.severity == ThreatLevel .CRITICAL ||
1160- anomaly.severity == ThreatLevel .HIGH ) {
1161- alertUser(det)
1162- }
1163-
1164- lastDetection.value = det
1165- detectionCount.value = repository.getTotalDetectionCount()
1166-
1167- if (BuildConfig .DEBUG ) {
1168- Log .w(TAG , " RF ANOMALY: ${anomaly.type.displayName} - ${anomaly.description} " )
1180+ try {
1181+ repository.insertDetection(det)
1182+
1183+ if (anomaly.severity == ThreatLevel .CRITICAL ||
1184+ anomaly.severity == ThreatLevel .HIGH ) {
1185+ alertUser(det)
1186+ }
1187+
1188+ lastDetection.value = det
1189+ detectionCount.value = repository.getTotalDetectionCount()
1190+ _detectionRefreshEvent .tryEmit(Unit )
1191+
1192+ if (BuildConfig .DEBUG ) {
1193+ Log .w(TAG , " RF ANOMALY: ${anomaly.type.displayName} - ${anomaly.description} " )
1194+ }
1195+ } catch (e: Exception ) {
1196+ Log .e(TAG , " Error saving RF detection: ${e.message} " , e)
11691197 }
11701198 }
11711199 }
@@ -1249,17 +1277,22 @@ class ScanningService : Service() {
12491277 // Use frequency as unique identifier
12501278 val existing = det.ssid?.let { repository.getDetectionBySsid(it) }
12511279 if (existing == null ) {
1252- repository.insertDetection(det)
1280+ try {
1281+ repository.insertDetection(det)
12531282
1254- if (anomaly.severity == ThreatLevel .CRITICAL ||
1255- anomaly.severity == ThreatLevel .HIGH ) {
1256- alertUser(det)
1257- }
1283+ if (anomaly.severity == ThreatLevel .CRITICAL ||
1284+ anomaly.severity == ThreatLevel .HIGH ) {
1285+ alertUser(det)
1286+ }
12581287
1259- lastDetection.value = det
1260- detectionCount.value = repository.getTotalDetectionCount()
1288+ lastDetection.value = det
1289+ detectionCount.value = repository.getTotalDetectionCount()
1290+ _detectionRefreshEvent .tryEmit(Unit )
12611291
1262- Log .w(TAG , " ULTRASONIC: ${anomaly.type.displayName} - ${anomaly.frequency} Hz" )
1292+ Log .w(TAG , " ULTRASONIC: ${anomaly.type.displayName} - ${anomaly.frequency} Hz" )
1293+ } catch (e: Exception ) {
1294+ Log .e(TAG , " Error saving ultrasonic detection: ${e.message} " , e)
1295+ }
12631296 }
12641297 }
12651298 }
@@ -1855,22 +1888,30 @@ class ScanningService : Service() {
18551888 // ==================== Detection Handling ====================
18561889
18571890 private suspend fun handleDetection (detection : Detection ) {
1858- // Use upsert - this will update seen count if existing, or insert if new
1859- val isNew = repository.upsertDetection(detection)
1860-
1861- if (isNew) {
1862- // New detection
1863- detectionCount.value++
1864- lastDetection.value = detection
1865-
1866- Log .d(TAG , " New detection: ${detection.deviceType} - ${detection.macAddress ? : detection.ssid} " )
1867-
1868- // Alert user
1869- alertUser(detection)
1870- } else {
1871- // Existing detection - update lastDetection to refresh UI
1872- lastDetection.value = detection
1873- Log .d(TAG , " Updated detection: ${detection.deviceType} - ${detection.macAddress ? : detection.ssid} " )
1891+ try {
1892+ // Use upsert - this will update seen count if existing, or insert if new
1893+ val isNew = repository.upsertDetection(detection)
1894+
1895+ if (isNew) {
1896+ // New detection
1897+ detectionCount.value++
1898+ lastDetection.value = detection
1899+
1900+ Log .d(TAG , " New detection: ${detection.deviceType} - ${detection.macAddress ? : detection.ssid} " )
1901+
1902+ // Alert user
1903+ alertUser(detection)
1904+ } else {
1905+ // Existing detection - update lastDetection to refresh UI
1906+ lastDetection.value = detection
1907+ Log .d(TAG , " Updated detection: ${detection.deviceType} - ${detection.macAddress ? : detection.ssid} " )
1908+ }
1909+
1910+ // Emit refresh event to ensure UI updates even if Room Flow doesn't trigger
1911+ _detectionRefreshEvent .tryEmit(Unit )
1912+ } catch (e: Exception ) {
1913+ Log .e(TAG , " Error handling detection: ${e.message} " , e)
1914+ logError(" Detection" , 1001 , " Failed to save detection: ${e.message} " )
18741915 }
18751916 }
18761917
0 commit comments