---
# System prepended metadata

title: Notification
tags: [Notification, Android, kotlin]

---

# Notification 

### 實作點擊按鈕發送Notification


### step 1 建立Notification channel
* 先定義初始化function
    * API大於26才需要提供channel ID，所以會加入版本判斷
* 透過NotificationChannel把資訊帶入，傳入id，Name，Importance。第三個是可以定義通知的效果，其中差異可以參考原始碼的說明
* 最後透過NotificationManager創建Notification channel
```kotlin=
    private val CHANNEL_ID = "channelID"
    private val CHANNEL_NAME = "channelName"
    private val NOFITICATION_ID = 0
    
    //初始化channel
    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID, CHANNEL_NAME,
                NotificationManager.IMPORTANCE_HIGH
            ).apply {
                lightColor = Color.GREEN
                enableLights(true)
            }
            val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            manager.createNotificationChannel(channel)
        }
    }
    
    /**
     * A notification with no importance: does not show in the shade.
     */
    public static final int IMPORTANCE_NONE = 0;

    /**
     * Min notification importance: only shows in the shade, below the fold.  This should
     * not be used with {@link Service#startForeground(int, Notification) Service.startForeground}
     * since a foreground service is supposed to be something the user cares about so it does
     * not make semantic sense to mark its notification as minimum importance.  If you do this
     * as of Android version {@link android.os.Build.VERSION_CODES#O}, the system will show
     * a higher-priority notification about your app running in the background.
     */
    public static final int IMPORTANCE_MIN = 1;

    /**
     * Low notification importance: Shows in the shade, and potentially in the status bar
     * (see {@link #shouldHideSilentStatusBarIcons()}), but is not audibly intrusive.
     */
    public static final int IMPORTANCE_LOW = 2;

    /**
     * Default notification importance: shows everywhere, makes noise, but does not visually
     * intrude.
     */
    public static final int IMPORTANCE_DEFAULT = 3;

    /**
     * Higher notification importance: shows everywhere, makes noise and peeks. May use full screen
     * intents.
     */
    public static final int IMPORTANCE_HIGH = 4;

    /**
     * Unused.
     */
    public static final int IMPORTANCE_MAX = 5;
    
```
### step 2 將要傳送的message丟進channel
* 用NotificationCompat.Builder把要通知的訊息包在裡面
* 基本上設定標題、內容、圖示、優先權、點選通知後自動清除
```kotlin=
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("this is title")
            .setContentText("this is content")
            .setSmallIcon(R.drawable.ic_baseline_airline_seat_individual_suite_24)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .build()
```
### step 3 發送通知

```kotlin=
val notificationManager = NotificationManagerCompat.from(this)

        findViewById<Button>(R.id.btn_send).setOnClickListener {
            notificationManager.notify(NOFITICATION_ID,notification)
        }
```

### 使用者點選通知時的事件
* 宣告PendingIntent
```kotlin=
        //intent要執行的class
        val intent = Intent(this, MainActivity::class.java)
        //宣告一個PendingIntent，它要執行的內容為上述的Intent
        val pendingIntent = TaskStackBuilder.create(this).run {
            addNextIntentWithParentStack(intent)
            //當要執行的Intent已經存在，則會覆蓋掉使用最新的狀態..
            getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT)
        }
        
```
* 加入到NotificationCompat Builder中
```kotlin=
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("this is title")
            .setContentText("this is content")
            .setSmallIcon(R.drawable.ic_baseline_airline_seat_individual_suite_24)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setAutoCancel(true)
            .setContentIntent(pendingIntent)
            .build()
```

### 完整code
```kotlin=

class MainActivity : AppCompatActivity() {

    private val CHANNEL_ID = "channelID"
    private val CHANNEL_NAME = "channelName"
    private val NOFITICATION_ID = 0


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

        val intent = Intent(this, MainActivity::class.java)
        val pendingIntent = TaskStackBuilder.create(this).run {
            addNextIntentWithParentStack(intent)
            getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT)
        }

        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("this is title")
            .setContentText("this is content")
            .setSmallIcon(R.drawable.ic_baseline_airline_seat_individual_suite_24)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setAutoCancel(true)
            .setContentIntent(pendingIntent)
            .build()

        val notificationManager = NotificationManagerCompat.from(this)

        findViewById<Button>(R.id.btn_send).setOnClickListener {
            notificationManager.notify(NOFITICATION_ID,notification)
        }

    }

    //初始化channel
    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID, CHANNEL_NAME,
                NotificationManager.IMPORTANCE_HIGH
            ).apply {
                lightColor = Color.GREEN
                enableLights(true)
            }
            val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            manager.createNotificationChannel(channel)
        }
    }
}
```
參考資料
[Philipp Lackner's channel](https://www.youtube.com/watch?v=urn355_ymNA)

###### tags: `Notification` `kotlin` `Android`