๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/Android

[Android] Notifications - Action ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์•Œ๋ฆผ Cancel

interfacer_han 2024. 6. 14. 03:35

#1 ์ด์ „ ๊ธ€

 

[Android] Notifications - PendingIntent

#1 ์ด์ „ ๊ธ€ [Android] Notifications - ๊ธฐ์ดˆ#1 ๊ฐœ์š” ์•Œ๋ฆผ ๊ฐœ์š”  |  Views  |  Android Developers์ด ํŽ˜์ด์ง€๋Š” Cloud Translation API๋ฅผ ํ†ตํ•ด ๋ฒˆ์—ญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์•Œ๋ฆผ ๊ฐœ์š” ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ •๋ฆฌํ•˜๊ธฐ ๋‚ด ํ™˜๊ฒฝ์„ค์ •์„ ๊ธฐ์ค€

kenel.tistory.com

์œ„ ๊ฒŒ์‹œ๊ธ€์˜ ์™„์„ฑ๋œ ์•ฑ์„ ์ผ๋ถ€ ์ˆ˜์ •ํ•ด์„œ, ์•Œ๋ฆผ์˜ Action ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ์•Œ๋ฆผ์ด ์ œ๊ฑฐ(Cancel)๋˜๊ฒŒ ๋งŒ๋“ค์–ด๋ณธ๋‹ค.

 

#2 PendingIntent.getBroadcast()

Intent๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์ปดํฌ๋„ŒํŠธ(Activity, Service, BroadcastReceiver, ContentProvider) ๊ฐ„ ํ†ต์‹ ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”์‹œ์ง€ ๊ฐ์ฒด๋ผ๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์ž. ์ด์ „ ๊ฒŒ์‹œ๊ธ€์—์„  ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ PendingIntent๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค
 

private fun getThirdActivityAction(): NotificationCompat.Action {
    val intent = Intent(this, ThirdActivity::class.java)
    val pendingIntent: PendingIntent = PendingIntent.getActivity(
        this, myRequestCode2, intent, PendingIntent.FLAG_IMMUTABLE
    )
    return NotificationCompat.Action.Builder(0, "Go Third", pendingIntent).build()
}

Activity๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ Intent๋ฅผ ๋งŒ๋“ค๊ณ , ํ•ด๋‹น Intent ๊ฐ์ฒด๋ฅผ PendingIntent.getActivity()์— ๋„ฃ์–ด PendingIntent๋ฅผ ์™„์„ฑํ–ˆ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด PendingIntent๊ฐ€ Notification์˜ Action ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์‹คํ–‰๋˜๊ฒŒ๋” ๋งŒ๋“ค์—ˆ๋‹ค. ์ตœ์ข…์ ์œผ๋กœ, ํ•ด๋‹น PendingIntent์— ๋‹ด๊ธด Intent์— ์˜ํ•ด Activity๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
 
์œ„ ์ฝ”๋“œ๋ฅผ ์‚ด์ง ๋ฐ”๊พธ๋ฉด, PendingIntent์— ๋‹ด๊ธด Intent๊ฐ€ BroadcastReceiver๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด์ž.
 

private fun getThirdActivityAction(): NotificationCompat.Action {
    val intent = Intent(this, NotificationReceiver::class.java)
        .putExtra("notificationId", notificationId)
        .putExtra("activityToStart", ThirdActivity::class.java)

    val pendingIntent = PendingIntent.getBroadcast(
        this, myRequestCode2, intent, PendingIntent.FLAG_IMMUTABLE
    )
    return NotificationCompat.Action.Builder(0, "Go Third", pendingIntent).build()
}

Intent ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ, ์ƒ์„ฑ์ž์— Activity ๋Œ€์‹  BroadcastReceiver๋ฅผ ์ผ๋‹ค. ๊ทธ๋ฆฌ๊ณ  PendingIntent.getActivity() ๋Œ€์‹  PendingIntent.getBroadcast()๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. getActivity()์™€ getBroadcast() ๋ชจ๋‘ Context, requestCode, Intent, Flag๋ฅผ ์ธ์ž๋กœ์„œ ์š”๊ตฌํ•˜๋ฉฐ PendingIntent ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ์ ์—์„œ ๋™์ผํ•˜๋‚˜, Intent์— ์ง€์ •๋œ ๊ฒƒ์ด Activity์ธ์ง€ BroadcastReceiver์ธ์ง€๋งŒ์ด ๋‹ค๋ฅด๋‹ค. ํ•œ ๋งˆ๋””๋กœ ์ „์ž๋Š” Activity๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ PendingIntent๋ฅผ ๋งŒ๋“ค๊ณ , ํ›„์ž๋Š” BroadcastReceiver๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ PendingIntent๋ฅผ ๋งŒ๋“ ๋‹ค.
 

#3 ์ฝ”๋“œ ์ˆ˜์ •

#3-1 MainActivity.kt ์ˆ˜์ •

...

class MainActivity : AppCompatActivity() {

    ...
    private val notificationId = 777 // ์•Œ๋ฆผ ์ฑ„๋„ Id์™€๋Š” ๋˜ ๋‹ค๋ฅธ ์•Œ๋ฆผ ํ•˜๋‚˜ํ•˜๋‚˜์˜ Id. ๋™์ผํ•œ Id์˜ ์•Œ๋ฆผ์ด ์ƒํƒœ๋ฐ”์— ์žˆ์„ ๋•Œ, ๊ฐ™์€ Id์ธ ์•Œ๋ฆผ์„ ๋ฐœ์ƒ์‹œํ‚ค๋ฉด, ์›๋ž˜ ์žˆ๋˜ ์•Œ๋ฆผ์ด ์ตœ์‹  ์•Œ๋ฆผ์œผ๋กœ ๊ฐˆ์•„๋ผ์›Œ์ง„๋‹ค.

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
    }

    private fun displayNotification() {
        ...
    }

    private fun getSecondActivityPendingIntent(): PendingIntent {
        ...
    }

    private fun getThirdActivityAction(): NotificationCompat.Action {
        val intent = Intent(this, NotificationReceiver::class.java)
            .putExtra("notificationId", notificationId)
            .putExtra("activityToStart", ThirdActivity::class.java)

        val pendingIntent = PendingIntent.getBroadcast(
            this, myRequestCode2, intent, PendingIntent.FLAG_IMMUTABLE
        )
        return NotificationCompat.Action.Builder(0, "Go Third", pendingIntent).build()
    }

    private fun getFourthActivityAction(): NotificationCompat.Action {
        val intent = Intent(this, NotificationReceiver::class.java)
            .putExtra("notificationId", notificationId)
            .putExtra("activityToStart", FourthActivity::class.java)

        val pendingIntent = PendingIntent.getBroadcast(
            this, myRequestCode3, intent, PendingIntent.FLAG_IMMUTABLE
        )
        return NotificationCompat.Action.Builder(0, "Go Fourth", pendingIntent).build()
    }

    ...
}

displayNotification()์˜ ์ง€์—ญ ๋ณ€์ˆ˜์˜€๋˜ notificationId๋ฅผ ๋ฐ–์œผ๋กœ ๋นผ์–ด ๊ทธ ์œ ํšจ ๋ฒ”์œ„๋ฅผ MainActivity์˜ ์˜์—ญ๊นŒ์ง€ ๋„“ํ˜”๋‹ค. ๊ทธ๋ฆฌ๊ณ  getThirdActivityAction() ๋ฐ getFourthActivityAction()๋ฅผ #2์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ˆ˜์ •ํ•œ๋‹ค.
 

#3-2 NotificationReceiver.kt ์ƒ์„ฑ

// package com.example.notificationcancel

import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build

class NotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // Notification ์ทจ์†Œ
        val notificationId = intent.getIntExtra("notificationId", -1)
        notificationManager.cancel(notificationId)

        // Activity ์‹คํ–‰
        var activityToStart: Class<*>? = null
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            activityToStart = intent.getSerializableExtra("activityToStart", Class::class.java)
        } else {
            activityToStart = intent.getSerializableExtra("activityToStart") as Class<*>
        }

        val activityIntent = Intent(context, activityToStart)
        activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(activityIntent)
    }
}

์ด ํด๋ž˜์Šค๋Š” ํ˜ธ์ถœ(onReceive())๋˜๋ฉด, NotificationManager.cancel()๋กœ ์•Œ๋ฆผ์„ ์ œ๊ฑฐํ•˜๊ณ , ์ƒˆ๋กœ์šด Activity๋ฅผ ์‹œ์ž‘ํ•˜๋Š” 2๊ฐ€์ง€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. getSerializableExtra(name: String)์€ API 33๋ถ€ํ„ฐ Deprecated๋˜์—ˆ๊ธฐ์— ๋ถ„๊ธฐ(if)๋ฌธ์„ ๋„ฃ์—ˆ๋‹ค.
 

#3-3 AndroidManifest.xml์— ๋ฆฌ์‹œ๋ฒ„ ๋“ฑ๋ก

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <application
        ...>
        <receiver
            android:name=".NotificationReceiver"
            android:enabled="true"
            android:exported="true"></receiver>

        <activity
            android:name=".FourthActivity"
            android:exported="false" />
        <activity
            android:name=".ThirdActivity"
            android:exported="false" />
        <activity
            android:name=".SecondActivity"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

์ด ์ž‘์—…์„ ์žŠ์œผ๋ฉด ์•ˆ ๋œ๋‹ค.
 

#4 ์ž‘๋™ ํ™•์ธ

 

#5 ์š”์•ฝ

Intent์˜ ์—ญํ• ์€ Activity ์‹คํ–‰์— ๊ตญํ•œ๋˜์ง€ ์•Š๋Š”๋‹ค.
 

#6 ์™„์„ฑ๋œ ์•ฑ

 

android-practice/notifications/NotificationCancel at master ยท Kanmanemone/android-practice

Contribute to Kanmanemone/android-practice development by creating an account on GitHub.

github.com

'๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘ > Android' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Android] WorkManager - ๊ธฐ์ดˆ  (0) 2024.06.17
[Android] WorkManager - ๊ฐœ์š”  (0) 2024.06.14
[Android] Notifications - PendingIntent  (0) 2024.06.12
[Android] Notifications - ๊ธฐ์ดˆ  (0) 2024.06.12
[Android] Retrofit - Post  (0) 2024.06.11