AndroidのNotificationをKotlinで実装し、複数の通知を送る

# はじめに
Androidの通知(Notification)に関する使用方法を記載いたします。
内容は複数の通知を送ることです。
サンプルアプリをベースに説明いたします。

**開発環境は以下の通りです。**
- Android Studio Electric Eel | 2022.1.1 Patch 2
- Runtime version: 11.0.15+0-b2043.56-8887301 aarch64
- macOS 13.4
- Android Virtual Device - android12.0 / 1440 x 2560


# Notificationとは
[公式サイト](https://developer.android.com/guide/topics/ui/notifiers/notifications?hl=ja)に以下の記述があります。
>通知は、アプリの UI の外で Android が表示するメッセージであり、
> リマインダー、他の人からのメッセージ、
> アプリからのタイムリーな情報などをユーザーに提供します。
> ユーザーは通知をタップしてアプリを開いたり、通知から直接操作したりできます。

# サンプルアプリの動作内容
サンプルアプリの処理フローは以下の通りです。
1. 画面に表示している"押下"ボタンを押下
1. 通知を送信する

![スクリーンショット 2023-06-24 12.15.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2652946/9e534cbf-9371-556c-da21-7ee18fed29fa.png)



# 環境構築
Android Studio で作成されたほとんどのプロジェクトには、
NotificationCompat を使用するために必要な依存関係が含まれております。
しかし、念のためモジュール レベルの ``build.gradle`` ファイルに次の依存関係が
含まれていることを確認します。
``` build.gradle
dependencies {
    implementation "com.android.support:support-compat:28.0.0"
}
```

<br>

次に、``AndroidManifest``に以下のパーミッションを追記いたします。
```AndroidManifest.xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.VIBRATE" />
```
※　Android13以降は実行時の権限も取得しておく必要があります。
　　そのため、実行時の権限をリクエストしたい際は、
　　以下のリンクを参考にしてください。
　　[実行時の権限をリクエストする](https://developer.android.com/training/permissions/requesting?hl=ja)

<br>

最後に、通知に表示させるアイコンを作成します。
適当なファイルを右クリックし、``New``　→　``Vector Asset``をクリックします。
すると、以下の画面が表示されます。
![スクリーンショット 2023-06-24 13.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2652946/6673eeec-4dec-b1c8-6b18-d158271a3e53.png)
上記画面のNameを``ic_notification_icon``に設定し、
``Next``をクリックすることでアイコンを作成できます。

※ Nameやアイコンの画像は、自身が気に入ったモノにしていただいて結構です。


# 実装
環境構築が終わったので、実装に入っていきます。

最初に、画面のレイアウトについて記載している
``activity_main``ファイルを紹介します。
```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">

    <Button
        android:id="@+id/notificationButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="通知"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

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

<br>

次に、ボタンが押下された際に、
通知処理を呼ぶ処理が記載されている``MainActivity``ファイルを紹介します。
```MainActivity.kt
import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity(), View.OnClickListener {

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

        val noticeBotton = findViewById<Button>(R.id.notificationButton)
        noticeBotton.setOnClickListener(this)
    }

    /**
     * ボタンを押下された際、発火する
     * @param v View
     */
    override fun onClick(v: View?) {
        createNotificationChannelOne(this)
        createNotificationChannelTwo(this)
    }
}
```

<br>

最後に、通知を送信する処理を記載している``Notice``ファイルを紹介します。
```Notice.kt
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.app.NotificationCompat

// 通知チャネルのID
private val CHANNEL_ID = "my_channel_id"

// 通知の重要度
private val NOTIFICATION_PRIORITY = NotificationCompat.PRIORITY_DEFAULT

/**
 * 通知を作成し、送信する処理の一つ目
 * @param context コンテキスト
 */
fun createNotificationChannelOne(context: Context){
    // チャンネルをシステムに登録する
    val notificationManager: NotificationManager =
        context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    // NotificationChannelを作成する、ただしAPI26+の場合のみなので
    // NotificationChannelクラスは新しいもので、サポートライブラリにはありません。
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = "通知管理アプリ"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance)
        notificationManager.createNotificationChannel(channel)
    }

    // NotificationCompat.Builderを使用して通知を作成
    var builder = NotificationCompat.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_notification_icon)
        .setContentTitle("通知管理")
        .setContentText("通知を送信いたしました。")
        .setPriority(NOTIFICATION_PRIORITY)

    // 通知を表示
    notificationManager.notify(/* 通知ID */ 1, builder.build())
}


/**
 * 通知を作成し、送信する処理の二つ目
 * @param context コンテキスト
 */
fun createNotificationChannelTwo(context: Context){
    // チャンネルをシステムに登録する
    val notificationManager: NotificationManager =
        context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    // NotificationChannelを作成する、ただしAPI26+の場合のみなので
    // NotificationChannelクラスは新しいもので、サポートライブラリにはありません。
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = "通知管理アプリ"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance)
        notificationManager.createNotificationChannel(channel)
    }

    // NotificationCompat.Builderを使用して通知を作成
    var builder = NotificationCompat.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_notification_icon)
        .setContentTitle("通知管理")
        .setContentText("2個目の通知を送信いたしました。")
        .setPriority(NOTIFICATION_PRIORITY)

    // 通知を表示
    notificationManager.notify(/* 通知ID */ 2, builder.build())
}
```

以上で、ボタンが押下されると通知が複数送信されます。

# まとめ
今回は、通知を複数送信する処理について記載いたしましたが、
通知を押下すると、アプリ画面に遷移する処理や、
通知をグループ化する処理もあります。
そのため、余裕がございましたら、チャレンジをしてみてもよいかもしれません。

### 参考資料
[通知を作成する | Android デベロッパー](https://developer.android.com/training/notify-user/build-notification?hl=ja)
[通知の概要 | Android デベロッパー](https://developer.android.com/guide/topics/ui/notifiers/notifications?hl=ja)
[今さらだけど！ AndroidのNotificationをJavaで実装してみる](https://qiita.com/park3taro/items/455a21bc1a9119271d5d)
[実行時の権限をリクエストする](https://developer.android.com/training/permissions/requesting?hl=ja)
[Manifest.permission](https://developer.android.com/reference/android/Manifest.permission)
[Android での権限](https://developer.android.com/guide/topics/permissions/overview?hl=ja#runtime)