This commit is contained in:
Flatlogic Bot 2026-02-25 06:50:45 +00:00
parent cde29a9feb
commit c16e47476d
9 changed files with 182 additions and 20 deletions

View File

@ -13,8 +13,6 @@
<application
android:name=".YumeeApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
@ -49,6 +47,19 @@
</intent-filter>
</receiver>
<receiver
android:name=".widget.MonitorWidget"
android:exported="true"
android:label="Yumee Panels Status">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.yumee.panels.UPDATE_WIDGET" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>
</application>
</manifest>
</manifest>

View File

@ -1,7 +1,6 @@
package com.yumee.panels
import android.app.Application
import androidx.room.Room
import com.yumee.panels.data.local.YumeeDatabase
class YumeeApp : Application() {
@ -11,8 +10,6 @@ class YumeeApp : Application() {
override fun onCreate() {
super.onCreate()
database = Room.databaseBuilder(this, YumeeDatabase::class.java, "yumee_db")
.fallbackToDestructiveMigration()
.build()
database = YumeeDatabase.getDatabase(this)
}
}
}

View File

@ -1,5 +1,6 @@
package com.yumee.panels.data.local
import android.content.Context
import androidx.room.*
import kotlinx.coroutines.flow.Flow
@ -8,6 +9,9 @@ interface MonitorDao {
@Query("SELECT * FROM monitors")
fun getAllMonitors(): Flow<List<Monitor>>
@Query("SELECT * FROM monitors")
suspend fun getAllMonitorsSync(): List<Monitor>
@Query("SELECT * FROM monitors WHERE isActive = 1")
suspend fun getActiveMonitors(): List<Monitor>
@ -36,4 +40,21 @@ interface MonitorDao {
@Database(entities = [Monitor::class, MonitorLog::class], version = 1)
abstract class YumeeDatabase : RoomDatabase() {
abstract fun monitorDao(): MonitorDao
}
companion object {
@Volatile
private var INSTANCE: YumeeDatabase? = null
fun getDatabase(context: Context): YumeeDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
YumeeDatabase::class.java,
"yumee_database"
).build()
INSTANCE = instance
instance
}
}
}
}

View File

@ -2,10 +2,8 @@ package com.yumee.panels.service
import android.app.*
import android.content.*
import android.net.ConnectivityManager
import android.os.*
import androidx.core.app.NotificationCompat
import androidx.room.Room
import com.yumee.panels.MainActivity
import com.yumee.panels.R
import com.yumee.panels.data.local.*
@ -32,7 +30,7 @@ class MonitorService : Service() {
override fun onCreate() {
super.onCreate()
db = Room.databaseBuilder(applicationContext, YumeeDatabase::class.java, "yumee_db").build()
db = YumeeDatabase.getDatabase(applicationContext)
createNotificationChannel()
acquireWakeLock()
}
@ -49,18 +47,27 @@ class MonitorService : Service() {
serviceScope.launch {
while (isActive) {
val monitors = db.monitorDao().getActiveMonitors()
var updated = false
monitors.forEach { monitor ->
// Simplified: In a real app, track individual interval timers
// Here we check if it's time to ping based on lastChecked
if (System.currentTimeMillis() - monitor.lastChecked >= monitor.intervalSeconds * 1000) {
launch { pingMonitor(monitor) }
pingMonitor(monitor)
updated = true
}
}
delay(1000) // check every second
if (updated) {
updateWidget()
}
delay(1000)
}
}
}
private fun updateWidget() {
val intent = Intent("com.yumee.panels.UPDATE_WIDGET")
intent.setPackage(packageName)
sendBroadcast(intent)
}
private suspend fun pingMonitor(monitor: Monitor) {
val startTime = System.currentTimeMillis()
var isOnline = false
@ -81,7 +88,6 @@ class MonitorService : Service() {
responseTime = System.currentTimeMillis() - startTime
}
// Update database
val updatedMonitor = monitor.copy(
lastStatusCode = statusCode,
lastResponseTime = responseTime,
@ -107,7 +113,7 @@ class MonitorService : Service() {
private fun sendAlert(name: String, message: String) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val alertNotification = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground) // Placeholder
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Alert: $name")
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
@ -122,7 +128,7 @@ class MonitorService : Service() {
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Yumee Panels")
.setContentText(text)
.setSmallIcon(R.drawable.ic_launcher_foreground) // Placeholder
.setSmallIcon(R.mipmap.ic_launcher)
.setOngoing(true)
.setContentIntent(pendingIntent)
.build()
@ -152,4 +158,4 @@ class MonitorService : Service() {
wakeLock?.let { if (it.isHeld) it.release() }
super.onDestroy()
}
}
}

View File

@ -0,0 +1,56 @@
package com.yumee.panels.widget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.widget.RemoteViews
import com.yumee.panels.MainActivity
import com.yumee.panels.R
import com.yumee.panels.data.local.YumeeDatabase
import kotlinx.coroutines.*
class MonitorWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
if (intent.action == "com.yumee.panels.UPDATE_WIDGET") {
val appWidgetManager = AppWidgetManager.getInstance(context)
val appWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, MonitorWidget::class.java))
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
}
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val views = RemoteViews(context.packageName, R.layout.widget_layout)
// Launch app on click
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
views.setOnClickPendingIntent(R.id.widget_title, pendingIntent)
// Fetch counts from DB
CoroutineScope(Dispatchers.IO).launch {
val db = YumeeDatabase.getDatabase(context)
val allMonitors = db.monitorDao().getAllMonitorsSync()
val onlineCount = allMonitors.count { it.isOnline }
val offlineCount = allMonitors.count { !it.isOnline }
withContext(Dispatchers.Main) {
views.setTextViewText(R.id.widget_online_count, "Online: $onlineCount")
views.setTextViewText(R.id.widget_offline_count, "Offline: $offlineCount")
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#1A2130" />
<corners android:radius="12dp" />
<stroke android:width="2dp" android:color="#FFFFFF" />
</shape>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/widget_background"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/widget_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Yumee Panels"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:textSize="12sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/widget_online_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Online: 0"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:shadowColor="#FFFFFF"
android:shadowDx="0"
android:shadowDy="0"
android:shadowRadius="5" />
<TextView
android:id="@+id/widget_offline_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Offline: 0"
android:textColor="#FF4444"
android:textSize="14sp" />
</LinearLayout>
<ImageView
android:id="@+id/widget_refresh"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@android:drawable/stat_notify_sync"
android:contentDescription="Refresh" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="110dp"
android:minHeight="40dp"
android:updatePeriodMillis="1800000"
android:initialLayout="@layout/widget_layout"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen">
</appwidget-provider>

Binary file not shown.