From bdd458a64f8111f3d446b716181d6ad5ce4eef10 Mon Sep 17 00:00:00 2001 From: AzenKain Date: Wed, 6 Aug 2025 18:32:18 +0700 Subject: [PATCH] UPDATE: Add wakelock --- app/src/main/AndroidManifest.xml | 13 ++--- .../fireflypsandorid/GolangServerService.kt | 56 +++++++++++++++---- .../example/fireflypsandorid/MainActivity.kt | 14 ++--- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f928d08..b7df893 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,13 +3,9 @@ xmlns:tools="http://schemas.android.com/tools"> - - - - - + + - + android:foregroundServiceType="dataSync" + android:exported="false" /> \ No newline at end of file diff --git a/app/src/main/java/com/example/fireflypsandorid/GolangServerService.kt b/app/src/main/java/com/example/fireflypsandorid/GolangServerService.kt index fd40889..9a369b7 100644 --- a/app/src/main/java/com/example/fireflypsandorid/GolangServerService.kt +++ b/app/src/main/java/com/example/fireflypsandorid/GolangServerService.kt @@ -8,29 +8,39 @@ import android.content.Context import android.content.Intent import android.os.Build import android.os.IBinder +import android.os.PowerManager import android.util.Log import androidx.core.app.NotificationCompat import libandroid.Libandroid class GolangServerService : Service() { + companion object { const val CHANNEL_ID = "GolangServerChannel" const val NOTIFICATION_ID = 1 private const val TAG = "GolangServerService" } + private var wakeLock: PowerManager.WakeLock? = null + override fun onCreate() { super.onCreate() createNotificationChannel() } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + Log.d(TAG, "onStartCommand called") + + // 1. Tạo intent để mở lại MainActivity khi người dùng click vào thông báo val notificationIntent = Intent(this, MainActivity::class.java) val pendingIntent = PendingIntent.getActivity( - this, 0, notificationIntent, - PendingIntent.FLAG_IMMUTABLE + this, + 0, + notificationIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) + // 2. Tạo notification val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Golang Server") .setContentText("Server đang chạy") @@ -38,13 +48,23 @@ class GolangServerService : Service() { .setContentIntent(pendingIntent) .build() + // 3. Chạy foreground startForeground(NOTIFICATION_ID, notification) - // Chạy server trong thread riêng để tránh ANR + // 4. Giữ CPU không sleep (tùy chọn, nhưng hữu ích) + try { + val powerManager = getSystemService(POWER_SERVICE) as PowerManager + wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "GolangServer::WakeLock") + wakeLock?.acquire() + Log.d(TAG, "✅ WakeLock acquired") + } catch (e: Exception) { + Log.e(TAG, "❌ WakeLock failed", e) + } + + // 5. Chạy server trong thread riêng Thread { try { val appDataPath = intent?.getStringExtra("appDataPath") - if (appDataPath != null) { Libandroid.setPathDataLocal(appDataPath) Log.d(TAG, "✅ Set path data: $appDataPath") @@ -55,7 +75,7 @@ class GolangServerService : Service() { Libandroid.setServerRunning(true) Log.d(TAG, "✅ Server started") } catch (e: Exception) { - Log.e(TAG, "❌ Error when start server:", e) + Log.e(TAG, "❌ Error starting server", e) } }.start() @@ -64,17 +84,30 @@ class GolangServerService : Service() { override fun onDestroy() { super.onDestroy() + Log.d(TAG, "onDestroy called") + + // 1. Tắt server try { val result = Libandroid.setServerRunning(false) Log.d(TAG, "Server shutdown result: $result") } catch (e: Exception) { Log.e(TAG, "Error shutting down server", e) } + + // 2. Giải phóng WakeLock nếu còn giữ + try { + wakeLock?.let { + if (it.isHeld) { + it.release() + Log.d(TAG, "✅ WakeLock released") + } + } + } catch (e: Exception) { + Log.e(TAG, "❌ Failed to release WakeLock", e) + } } - override fun onBind(intent: Intent?): IBinder? { - return null - } + override fun onBind(intent: Intent?): IBinder? = null private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -83,11 +116,12 @@ class GolangServerService : Service() { "Golang Server Channel", NotificationManager.IMPORTANCE_LOW ).apply { - description = "Notify Golang backend runing" + description = "Channel for running Golang backend in foreground" } - val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - notificationManager.createNotificationChannel(channel) + val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + manager.createNotificationChannel(channel) + Log.d(TAG, "✅ Notification channel created") } } } diff --git a/app/src/main/java/com/example/fireflypsandorid/MainActivity.kt b/app/src/main/java/com/example/fireflypsandorid/MainActivity.kt index 0c228cd..ac484f9 100644 --- a/app/src/main/java/com/example/fireflypsandorid/MainActivity.kt +++ b/app/src/main/java/com/example/fireflypsandorid/MainActivity.kt @@ -1,5 +1,6 @@ package com.example.fireflypsandorid +import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle import android.util.Log @@ -8,13 +9,11 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.Image -import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.* -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext @@ -26,7 +25,7 @@ import com.example.fireflypsandorid.ui.theme.FireflyPsAndoridTheme import java.io.* class MainActivity : ComponentActivity() { - private val TAG = "AppInit" + private val tag = "AppInit" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -58,17 +57,18 @@ class MainActivity : ComponentActivity() { input.copyTo(output) } } - Log.i(TAG, "✅ Copied $fileName to ${outFile.absolutePath}") + Log.i(tag, "✅ Copied $fileName to ${outFile.absolutePath}") } catch (e: Exception) { - Log.e(TAG, "❌ Failed to copy $fileName: ${e.message}") + Log.e(tag, "❌ Failed to copy $fileName: ${e.message}") } } else { - Log.i(TAG, "ℹ️ $fileName already exists at ${outFile.absolutePath}") + Log.i(tag, "ℹ️ $fileName already exists at ${outFile.absolutePath}") } } } +@SuppressLint("ImplicitSamInstance") @Composable fun ServerControlScreen(appDataPath: String, modifier: Modifier = Modifier) { val context = LocalContext.current @@ -128,7 +128,7 @@ fun ServerControlScreen(appDataPath: String, modifier: Modifier = Modifier) { } }, colors = ButtonDefaults.buttonColors( - containerColor = if (isServerRunning) Color(0xFFB71C1C) else Color(0xFFFF5722), + containerColor = if (isServerRunning) Color(0xFFB71C1C) else Color(0xFF2196F3), contentColor = Color.White ), shape = RoundedCornerShape(12.dp),