Refactor code structure for improved readability and maintainability
This commit is contained in:
2
cinny
2
cinny
Submodule cinny updated: 3efc68e893...d226b1810a
@@ -8,6 +8,8 @@
|
|||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32" />
|
||||||
|
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
|
||||||
|
|
||||||
<!-- AndroidTV support -->
|
<!-- AndroidTV support -->
|
||||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package wtf.ruv.paarrot
|
package wtf.ruv.paarrot
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
|
||||||
@@ -7,5 +9,17 @@ class MainActivity : TauriActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// Start the foreground sync service to keep the app alive for notifications
|
||||||
|
startSyncService()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startSyncService() {
|
||||||
|
val serviceIntent = Intent(this, SyncService::class.java)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
startForegroundService(serviceIntent)
|
||||||
|
} else {
|
||||||
|
startService(serviceIntent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package wtf.ruv.paarrot
|
package wtf.ruv.paarrot
|
||||||
|
|
||||||
|
import android.app.AlarmManager
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
@@ -7,8 +8,11 @@ import android.app.Service
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
|
import android.os.Looper
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
|
import android.os.SystemClock
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,9 +25,19 @@ class SyncService : Service() {
|
|||||||
private const val CHANNEL_ID = "paarrot_sync_channel"
|
private const val CHANNEL_ID = "paarrot_sync_channel"
|
||||||
private const val CHANNEL_NAME = "Background Sync"
|
private const val CHANNEL_NAME = "Background Sync"
|
||||||
private const val WAKE_LOCK_TAG = "Paarrot:SyncWakeLock"
|
private const val WAKE_LOCK_TAG = "Paarrot:SyncWakeLock"
|
||||||
|
private const val ALARM_REQUEST_CODE = 1001
|
||||||
|
private const val KEEP_ALIVE_INTERVAL_MS = 5 * 60 * 1000L // 5 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
private var wakeLock: PowerManager.WakeLock? = null
|
private var wakeLock: PowerManager.WakeLock? = null
|
||||||
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
private val keepAliveRunnable = object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
// Re-acquire wake lock periodically to prevent it from being released
|
||||||
|
ensureWakeLock()
|
||||||
|
handler.postDelayed(this, KEEP_ALIVE_INTERVAL_MS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? = null
|
override fun onBind(intent: Intent?): IBinder? = null
|
||||||
|
|
||||||
@@ -31,18 +45,35 @@ class SyncService : Service() {
|
|||||||
super.onCreate()
|
super.onCreate()
|
||||||
createNotificationChannel()
|
createNotificationChannel()
|
||||||
acquireWakeLock()
|
acquireWakeLock()
|
||||||
|
scheduleKeepAlive()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
startForeground(NOTIFICATION_ID, createNotification())
|
startForeground(NOTIFICATION_ID, createNotification())
|
||||||
|
ensureWakeLock()
|
||||||
return START_STICKY
|
return START_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
handler.removeCallbacks(keepAliveRunnable)
|
||||||
|
cancelAlarm()
|
||||||
releaseWakeLock()
|
releaseWakeLock()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||||
|
// Restart service if app is swiped away
|
||||||
|
val restartServiceIntent = Intent(applicationContext, SyncService::class.java)
|
||||||
|
restartServiceIntent.setPackage(packageName)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
startForegroundService(restartServiceIntent)
|
||||||
|
} else {
|
||||||
|
startService(restartServiceIntent)
|
||||||
|
}
|
||||||
|
super.onTaskRemoved(rootIntent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createNotificationChannel() {
|
private fun createNotificationChannel() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val channel = NotificationChannel(
|
val channel = NotificationChannel(
|
||||||
@@ -69,7 +100,7 @@ class SyncService : Service() {
|
|||||||
|
|
||||||
return NotificationCompat.Builder(this, CHANNEL_ID)
|
return NotificationCompat.Builder(this, CHANNEL_ID)
|
||||||
.setContentTitle("Paarrot")
|
.setContentTitle("Paarrot")
|
||||||
.setContentText("Syncing messages...")
|
.setContentText("Connected to Matrix")
|
||||||
.setSmallIcon(android.R.drawable.ic_dialog_info)
|
.setSmallIcon(android.R.drawable.ic_dialog_info)
|
||||||
.setContentIntent(pendingIntent)
|
.setContentIntent(pendingIntent)
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
@@ -77,16 +108,64 @@ class SyncService : Service() {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun scheduleKeepAlive() {
|
||||||
|
// Use handler for periodic wake lock refresh
|
||||||
|
handler.postDelayed(keepAliveRunnable, KEEP_ALIVE_INTERVAL_MS)
|
||||||
|
|
||||||
|
// Also set up alarm as backup
|
||||||
|
scheduleAlarm()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleAlarm() {
|
||||||
|
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
|
val intent = Intent(this, SyncService::class.java)
|
||||||
|
val pendingIntent = PendingIntent.getService(
|
||||||
|
this,
|
||||||
|
ALARM_REQUEST_CODE,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
|
|
||||||
|
// Schedule inexact repeating alarm to restart service periodically
|
||||||
|
alarmManager.setInexactRepeating(
|
||||||
|
AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||||
|
SystemClock.elapsedRealtime() + KEEP_ALIVE_INTERVAL_MS,
|
||||||
|
KEEP_ALIVE_INTERVAL_MS,
|
||||||
|
pendingIntent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelAlarm() {
|
||||||
|
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
|
val intent = Intent(this, SyncService::class.java)
|
||||||
|
val pendingIntent = PendingIntent.getService(
|
||||||
|
this,
|
||||||
|
ALARM_REQUEST_CODE,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
|
alarmManager.cancel(pendingIntent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun acquireWakeLock() {
|
private fun acquireWakeLock() {
|
||||||
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
|
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||||
wakeLock = powerManager.newWakeLock(
|
wakeLock = powerManager.newWakeLock(
|
||||||
PowerManager.PARTIAL_WAKE_LOCK,
|
PowerManager.PARTIAL_WAKE_LOCK,
|
||||||
WAKE_LOCK_TAG
|
WAKE_LOCK_TAG
|
||||||
).apply {
|
).apply {
|
||||||
acquire(10 * 60 * 1000L) // 10 minutes timeout
|
// Acquire indefinitely - the service manages its own lifecycle
|
||||||
|
acquire()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ensureWakeLock() {
|
||||||
|
wakeLock?.let {
|
||||||
|
if (!it.isHeld) {
|
||||||
|
it.acquire()
|
||||||
|
}
|
||||||
|
} ?: acquireWakeLock()
|
||||||
|
}
|
||||||
|
|
||||||
private fun releaseWakeLock() {
|
private fun releaseWakeLock() {
|
||||||
wakeLock?.let {
|
wakeLock?.let {
|
||||||
if (it.isHeld) {
|
if (it.isHeld) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user