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) } } }