The rotation service now responds to screen on/off events via a dedicated ScreenOnRotationService, reducing background work and avoiding perpetual wakeful states. Manifest and receiver logic were adjusted to align with the new behavior and energy constraints. Scheduling and enablement now consistently use timed-based rules and screen-on preferences, with the boot and alarm paths updated to honor these settings. This avoids unnecessary foreground services and keeps the app compliant with Doze and battery optimizations. Immich image handling improvements include throttled progress updates, larger cache allowances, and a connectivity-aware automatic download check to avoid unwanted network usage. - Use ScreenOnRotationService for screen-on based rotation scheduling - Centralize enablement via timed-enabled paths and AlarmManager windowing - Improve Immich cache and progress reporting with connectivity checks
107 lines
3.6 KiB
Kotlin
107 lines
3.6 KiB
Kotlin
package de.wechselbild.wallpaper
|
|
|
|
import android.app.NotificationChannel
|
|
import android.app.NotificationManager
|
|
import android.app.PendingIntent
|
|
import android.app.Service
|
|
import android.content.BroadcastReceiver
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.IntentFilter
|
|
import android.os.Build
|
|
import android.os.IBinder
|
|
import androidx.core.app.NotificationCompat
|
|
import androidx.core.content.ContextCompat
|
|
import java.util.concurrent.Executors
|
|
import java.util.concurrent.atomic.AtomicBoolean
|
|
|
|
class ScreenOnRotationService : Service() {
|
|
private val worker = Executors.newSingleThreadExecutor()
|
|
private val rotating = AtomicBoolean(false)
|
|
private val changedWhileScreenOff = AtomicBoolean(false)
|
|
private val screenReceiver = object : BroadcastReceiver() {
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
if (!WallpaperStore.screenOnEnabled(context)) return
|
|
when (intent.action) {
|
|
Intent.ACTION_SCREEN_OFF -> rotate(context, preparedForScreenOn = true)
|
|
Intent.ACTION_SCREEN_ON -> {
|
|
if (!changedWhileScreenOff.getAndSet(false)) rotate(context, preparedForScreenOn = false)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun rotate(context: Context, preparedForScreenOn: Boolean) {
|
|
if (!rotating.compareAndSet(false, true)) return
|
|
worker.execute {
|
|
try {
|
|
if (WallpaperStore.applyNext(context, automatic = true) && preparedForScreenOn) {
|
|
changedWhileScreenOff.set(true)
|
|
}
|
|
} finally { rotating.set(false) }
|
|
}
|
|
}
|
|
|
|
override fun onCreate() {
|
|
super.onCreate()
|
|
createChannel()
|
|
val launch = packageManager.getLaunchIntentForPackage(packageName)
|
|
val pending = PendingIntent.getActivity(this, 0, launch, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
|
|
val notification = NotificationCompat.Builder(this, CHANNEL)
|
|
.setSmallIcon(android.R.drawable.ic_menu_gallery)
|
|
.setContentTitle(getString(R.string.wallpaper_service_title))
|
|
.setContentText(getString(R.string.wallpaper_service_text))
|
|
.setOngoing(true)
|
|
.setSilent(true)
|
|
.setContentIntent(pending)
|
|
.build()
|
|
startForeground(NOTIFICATION_ID, notification)
|
|
val filter = IntentFilter().apply {
|
|
addAction(Intent.ACTION_SCREEN_OFF)
|
|
addAction(Intent.ACTION_SCREEN_ON)
|
|
}
|
|
if (Build.VERSION.SDK_INT >= 33) {
|
|
registerReceiver(screenReceiver, filter, Context.RECEIVER_NOT_EXPORTED)
|
|
} else {
|
|
@Suppress("DEPRECATION")
|
|
registerReceiver(screenReceiver, filter)
|
|
}
|
|
}
|
|
|
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
if (!WallpaperStore.screenOnEnabled(this)) {
|
|
stopSelf()
|
|
return START_NOT_STICKY
|
|
}
|
|
return START_STICKY
|
|
}
|
|
|
|
override fun onBind(intent: Intent?): IBinder? = null
|
|
|
|
override fun onDestroy() {
|
|
runCatching { unregisterReceiver(screenReceiver) }
|
|
worker.shutdown()
|
|
super.onDestroy()
|
|
}
|
|
|
|
companion object {
|
|
private const val CHANNEL = "wechselbild_screen_on"
|
|
private const val NOTIFICATION_ID = 4217
|
|
|
|
fun start(context: Context) {
|
|
ContextCompat.startForegroundService(context, Intent(context, ScreenOnRotationService::class.java))
|
|
}
|
|
|
|
fun stop(context: Context) {
|
|
context.stopService(Intent(context, ScreenOnRotationService::class.java))
|
|
}
|
|
}
|
|
|
|
private fun createChannel() {
|
|
if (Build.VERSION.SDK_INT >= 26) {
|
|
val channel = NotificationChannel(CHANNEL, getString(R.string.wallpaper_channel_name), NotificationManager.IMPORTANCE_LOW)
|
|
getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
|
|
}
|
|
}
|
|
}
|