// ===== Same fix at Kotlin-source level (if you build from the source) =====
// --- new file: widget/IconAlarm.kt ---
package com.luachitim.widget
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.util.Log
import com.luachitim.util.DayClock
import com.luachitim.util.storedInIsrael
object IconAlarm {
@Volatile @JvmField var visible = false
private fun pending(ctx: Context) = PendingIntent.getBroadcast(
ctx, 7005,
Intent(ctx, MidnightIconReceiver::class.java).setAction("com.luachitim.action.ICON_TICK"),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
/** One-shot alarm for the next day change (midnight or tzeit, by the setting). */
fun schedule(ctx: Context) = runCatching {
val am = ctx.getSystemService(AlarmManager::class.java) ?: return@runCatching
if (!isDynamicIconEnabled()) { am.cancel(pending(ctx)); return@runCatching }
val delay = DayClock.millisToNextChange(storedInIsrael(), capMs = 86_400_000L)
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + delay + 3_000, pending(ctx))
}.onFailure { Log.w("LuachItim", "icon alarm schedule failed", it) }
}
// --- MidnightIconReceiver.onReceive: accept any action, don't swap icon while app is on screen ---
override fun onReceive(context: Context, intent: Intent) {
runCatching {
initAndroidPlatform(context)
if (!IconAlarm.visible) applyDynamicIconForToday(context) // schedules next alarm
else IconAlarm.schedule(context) // MainActivity.onStop will swap
LuachPageWidgetProvider.requestUpdate(context)
LuachDateWidgetProvider.requestUpdate(context)
LuachWidgetProvider.requestUpdate(context)
}
}
// --- DynamicAppIcon.kt ---
// applyDynamicIconForToday(): right after `if (!isDynamicIconEnabled()) return` add:
// IconAlarm.schedule(context)
// revertToDefaultIcon(): at the end add:
// IconAlarm.schedule(context) // cancels, since the feature is now off
// --- LuachApplication.onCreate: DON'T swap the icon here (that's the launch "crash") ---
// initAndroidPlatform(this)
// IconAlarm.schedule(this) // instead of applyDynamicIconForToday(this)
// --- MainActivity ---
override fun onStart() { super.onStart(); /*...*/ IconAlarm.visible = true }
override fun onStop() {
/*...*/ super.onStop()
IconAlarm.visible = false
if (!isChangingConfigurations) runCatching { applyDynamicIconForToday(this) }
}
// --- AndroidManifest.xml ---
//
// and in MidnightIconReceiver's intent-filter add:
//
//