Daniel Beleza
Daniel Beleza

Reputation: 419

Implement countdown timer in Glance widget

I need to implement a countdown timer in a Glance widget, that should be updated every second. At the bare minimum, every minute.

What would be the best approach for this using Jetpack Compose Glance widgets? First time I play with this.

I've been trying to do something like

object : CountDownTimer(startTime, 1000) {
            private var coroutineScope: CoroutineScope? = null

            override fun onTick(millisUntilFinished: Long) {
                if (coroutineScope == null) {
                    coroutineScope = CoroutineScope(coroutineContext)
                }
                coroutineScope?.launch {
                    onTick?.invoke(millisUntilFinished) // calls GlanceWidget.updateAll(context)
                }

            }

            override fun onFinish() {
                coroutineScope?.cancel()
                onFinish?.invoke()
            }
        }

Upvotes: 0

Views: 233

Answers (1)

Divyesh Rudani
Divyesh Rudani

Reputation: 249

class CountdownGlanceWidget : GlanceAppWidget() {

    override suspend fun onUpdate(context: Context, glanceId: GlanceId) {
        val remainingTime = getRemainingTime()
        updateAppWidget(context, glanceId, remainingTime)
    }

    private suspend fun updateAppWidget(context: Context, glanceId: GlanceId, remainingTime: String) {
        update(context, glanceId) {
            CountdownWidgetContent(remainingTime)
        }
    }
}

@Composable
fun CountdownWidgetContent(remainingTime: String) {
    Text(
        text = remainingTime,
        style = TextStyle(fontSize = 24.sp, color = ColorProvider(R.color.black))
    )
}

fun getRemainingTime(): String {
    // Replace with your logic to compute remaining time
    val targetTimeMillis = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(10)
    val currentTimeMillis = SystemClock.elapsedRealtime()
    val remainingMillis = targetTimeMillis - currentTimeMillis

    val minutes = TimeUnit.MILLISECONDS.toMinutes(remainingMillis)
    val seconds = TimeUnit.MILLISECONDS.toSeconds(remainingMillis) % 60

    return String.format("%02d:%02d", minutes, seconds)
}


class CountdownUpdateWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        val context = applicationContext
        val glanceIds = GlanceAppWidgetManager(context).getGlanceIds(CountdownGlanceWidget::class.java)
        for (glanceId in glanceIds) {
            CountdownGlanceWidget().updateAll(context)
        }
        return Result.success()
    }
}

fun scheduleWidgetUpdate(context: Context) {
    val workRequest = PeriodicWorkRequestBuilder<CountdownUpdateWorker>(1, TimeUnit.MINUTES).build()
    WorkManager.getInstance(context).enqueue(workRequest)
}


class MyApp : Application(), Configuration.Provider {

    override fun onCreate() {
        super.onCreate()
        scheduleWidgetUpdate(this)
    }

    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setMinimumLoggingLevel(android.util.Log.INFO)
            .build()
}

Upvotes: -1

Related Questions