【Android】WorkManagerを使ってPUSH通知を飛ばす

## はじめに
Androidアプリでアプリからなんらかの操作を契機にPUSH通知を飛ばす（いわゆるローカルプッシュ）について調べる機会があったため、忘れないように記事に残そうと思いこちらを書きました。
## WorkManagerとは何か
非同期的なタスクをスケジュールとして設定・実行してくれるAPIになります。
スケジュールとしても設定方法がいくつかあり、一回限りの実行や繰り返しの実行も設定可能です。
アプリの状態に関わらずタスクをスケジュールし実行できるため、アプリ⇔サーバーが定期的にやり取りするような処理を実行したいときに使われるみたいです。
詳しくは[公式サイト](https://developer.android.com/topic/libraries/architecture/workmanager?hl=ja)を参照ください。

今回はそのWorkManagerの一回限りのスケジュール・実行を使ってPUSH通知を行っていきます。
## 実装
### 依存関係の追加
アプリレベルのgradleに以下の依存関係を追加します。
```build.gradle.kts
dependencies {
    val version = "2.9.0"
    implementation("android.arch.work:work-runtime-ktx:$version")
}
```
バージョンは[こちら](https://developer.android.com/jetpack/androidx/releases/work?hl=ja)を確認して設定してください。
### Workerの作成
WorkManagerで実行したい処理をもつWorkerクラスを作成します。
Workerクラスは、Workerを継承して作成し、実行したい処理は、オーバーライドしたdoWorkメソッドに書いていきます。
今回はdoWorkにPush通知の処理を書いていきます。
``` PushNotificationWorker.kt
class PushNotificationWorker(
    context: Context,
    workerParameters: WorkerParameters
    ) : Worker(context, params) {
    override fun doWork(): Result {
        // Push通知処理
        val channelId = "push_notification_channel"
        val notificationId = 1
        val notificationManager: NotificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Push Notification Channel"
            val descriptionText = "This is the push notification channel"
            val importance = NotificationManager.IMPORTANCE_HIGH
            val channel = NotificationChannel(channelId, name, importance).also {
                it.description = descriptionText
            }

            notificationManager.createNotificationChannel(channel)
        }

        val builder = NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle("Push Notification")
            .setContentText("This is a push notification")
            .setPriority(NotificationCompat.PRIORITY_HIGH)

        notificationManager.notify(notificationId, builder.build())

        // doWorkの処理の最後にResultを返す
        return Result.success()
    }
}
```
### WorkManagerを使ってタスクをリクエスト
WorkManagerを使い、先ほど作成したPushNotificationWorkerを１回限りのリクエストを実行する処理を書いていきます。
今回はシンプルにボタンをタップしたらWorkMangerでリクエストするというふうに実装します。
```MainActivity.kt
class MainActivity : AppCompatActivity() {
    private val wokManager = WorkManager.getInstance(this)

    override fun onResume() {
        super.onResume()

        // PUSH通知を行うために権限を確認
        if (checkNotificationPermission()) {
            // 権限がある場合はWoekManagerのOneTimeWorkRequestを使いWorkerの実行をリクエスト
            val button = findViewById<View>(R.id.button)
            button.setOnClickListener {
                wokManager.enqueue(OneTimeWorkRequest.from(PushNotificationWorker::class.java))
            }
        } else {
            // 権限がない場合は権限取得を行なう
            requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
        }
    }

    private fun checkNotificationPermission(): Boolean {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
            return true
        }

        return ActivityCompat.checkSelfPermission(
            this,
            android.Manifest.permission.POST_NOTIFICATIONS
        ) == android.content.pm.PackageManager.PERMISSION_GRANTED
    }
```

上記でWorkMangerを使用したPUSH通知の実装の出来上がりです。
## おわりに
今回は簡単にWorkMangerを使用したPUSH通知機能についてコードを交えて記事をまとめてみました。
手順としてはそんなに難しくなく、サンプルとして動かすのは大変ではなかったです。

今回の調査では、WorkerクラスにHiltを使って依存注入する方法も調べて実装もしてみたのですが、
それはまた別で記事にしたいと思います。（実はこの部分で割と時間を食いました。。）
→ 上記について、[こちら](https://qiita.com/Nkot117/items/6f028d8d5a70b1dbed36)で記事にしました。
  気になる方はこちらの記事も見ていただければと思います！
## 参考
[WorkManager でタスクのスケジュールを設定する](https://developer.android.com/topic/libraries/architecture/workmanager?hl=ja)
[WorkManager](https://developer.android.com/jetpack/androidx/releases/work?hl=ja)
[【Android】Hiltを使ってWorkerにDIする](https://qiita.com/Nkot117/items/6f028d8d5a70b1dbed36)