Android Studio: WorkManager で 毎分時間を表示

このプログラムは、未完成です。
WorkManager の例題として、毎分時間を表示してみます。

環境

```:app/build.gradle.kts
（省略）
dependencies {
    implementation("androidx.work:work-runtime-ktx:2.8.0")
（省略）
```

## 画面

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"

    android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

## プログラム

```MainViewModel.kt
package com.example.clock02


import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.Data
import java.util.concurrent.TimeUnit

class MainViewModel(application: Application) : AndroidViewModel(application) {
    private val workManager = WorkManager.getInstance(application)
    private val workRequest = OneTimeWorkRequest.Builder(ClockWorker::class.java)
        .setInitialDelay(1, TimeUnit.SECONDS)
        .addTag("clock_worker")
        .build()

    private val workInfoLiveData: LiveData<WorkInfo> = workManager.getWorkInfoByIdLiveData(workRequest.id)

    // MutableLiveData to observe the formatted date
    private val formattedDateLiveData = MutableLiveData<String>()

    init {
        workManager.enqueue(workRequest)
        // Observe the work status and update the LiveData
        workManager.getWorkInfoByIdLiveData(workRequest.id).observeForever { workInfo ->
            if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
                val formattedDate = workInfo.outputData.getString("formattedDate")
                formattedDateLiveData.postValue(formattedDate)
            }
        }
    }

    fun getWorkInfoLiveData(): LiveData<WorkInfo> {
        return workInfoLiveData
    }

    fun getFormattedDateLiveData(): LiveData<String> {
        return formattedDateLiveData
    }
}
```

```ClockWorker.kt
package com.example.clock02


import android.content.Context
import androidx.work.Data
import androidx.work.ListenableWorker
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.util.concurrent.TimeUnit

class ClockWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
    override fun doWork(): Result {
        try {
            println("*** ClockWorker *** aaa ***")
            val now = LocalDateTime.now()
            val df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
            val fdate = df.format(now)

            val outputData = Data.Builder().putString("formattedDate", fdate).build()
 println("*** ClockWorker *** ccc ***")
            // 次回の実行を1分後にスケジュールする
            val nextExecutionTime = now.plusMinutes(1)
            val timeDiff = nextExecutionTime.toInstant(ZoneOffset.UTC).toEpochMilli() - System.currentTimeMillis()
            val nextRequest = OneTimeWorkRequest.Builder(ClockWorker::class.java)
                .setInitialDelay(timeDiff, TimeUnit.MILLISECONDS)
                .build()

            WorkManager.getInstance(applicationContext).enqueue(nextRequest)

            return Result.success(outputData)
        } catch (e: Exception) {
            return Result.failure()
        }
    }
}
```

```MainActivity.kt
package com.example.clock02

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.Observer
import androidx.work.WorkInfo

class MainActivity : AppCompatActivity() {
    private lateinit var textView: TextView
    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        textView = findViewById(R.id.textView)

        println("*** check *** aaa ***")
        // MainViewModelのインスタンスを作成
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
println("*** check *** ccc ***")
        // WorkInfoを監視してUIを更新
        viewModel.getWorkInfoLiveData().observe(this, Observer { workInfo ->
            if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
                val formattedDate = workInfo.outputData.getString("formattedDate")
                println("*** check *** eee ***")
                textView.text = formattedDate
                println("*** check *** fff ***")
            } else if (workInfo != null && workInfo.state == WorkInfo.State.FAILED) {
                // エラーハンドリング
            }
        })
    }
}
```

## 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/318d7790-d6b0-b1c0-9dd7-e5e2aef22ccf.png)