[Android/Kotlin] AlarmManager + Notification - 지정한 시간에 알림 생성

Notepad96

·

2022. 9. 15. 23:09

300x250

 

 

1. 요약

 

결과

 

이번 글에서는 AlarmManager와 Notification을 활용하여 지정된 시간에 알림을 생성하는 방법에 관하여 기술한다.

 

AlarmManager는 지정한 시간 혹은 일정 시간 이후 정의한 동작을 하도록 정의할 수 있으며 자세한 내용은 아래 이전에 작성한 글을 참고하면 된다.

 

 

[Android/Kotlin] AlarmManager - 알람 등록

1. 요약 이번 글에서는 AlarmManager를 사용하여 Alarm을 정의하고 등록하는 방법에 관하여 기술한다. AlarmManager를 통하여 Alarm을 등록하면 특정 시간에 Alarm을 발생하도록 할 수도 있으며, 지정한 시간

notepad96.tistory.com

 

 

 

Notification은 알림 창을 보이게 하여 특정 이벤트를 알리거나 애플리케이션을 실행하도록 할 수 있다.

 

여기서 AlarmManager와 같이 사용함으로써 지정된 시간의 동작으로 Notification을 생성하도록 하면 지정한 시간에 알림을 발생하는 동작을 할 수 있게 된다.

 

Notification의 관한 자세한 내용 또한, 아래 이전에 작성한 글을 참고하면 된다.

 

 

 

[Android/Kotlin] 알림(Notification) 만들기

1. 요약 이번 글에서는 알림(Notification)을 생성하는 방법에 관하여 기술한다. 단, 이번 글의 내용만으로는 흔히 우리가 사용하는 Application에서 발생하는 Notification은 이것만으로는 똑같이 구현해

notepad96.tistory.com

 

 

 

 

2. 레이아웃

2-1. activity_main.xml

메인 레이아웃으로서 Alarm을 On/Off 할 수 있도록 Switch 1개를 사용하며, Alarm의 On/Off 시 Log를 나타낼 수  있도록 TextView 1개로 구성하였다.

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:padding="10dp"
    tools:context=".MainActivity">
    
        <Switch
            android:id="@+id/switch01"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="16sp"
            android:text="Time" />

    <TextView
        android:id="@+id/logText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="16sp"/>

</LinearLayout>

 

 

 

 

3. 코드 및 설명

3-1. MainActivity.kt

메인 액티비티로서 alarmManager와 pendingIntent를 초기화해준다.

 

여기서 alarmManager는 Alarm을 발생시키도록 할 수 있는 객체이며 pendingIntent는 Alarm이 발생했을 receiver로 보낼 미리 정의한 intent이다.

 

 

 

Switch 버튼의 Check 상태가 변하는 이벤트가 발생할 때마다 동작하기 위하여 setOnCheckedChangeListener를 정의하였다.

 

또한, 값이 변화할 때마다 SharedPreferences를 사용하여 Boolean 타입의 alarm 값을 저장하여 On/Off 상태를 유지할 수 있도록 하였다.

 

 

package com.notepad96.alarmnotification

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.os.SystemClock
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import com.notepad96.alarmnotification.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    val binding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) }
    lateinit var setting: SharedPreferences

    companion object {
        const val REQUEST_CODE = 101
    }
    object view {
        lateinit var instance: MainActivity
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        view.instance = this
        setting = getSharedPreferences("setting", MODE_PRIVATE)
        binding.switch01.isChecked = setting.getBoolean("alarm", false)

        val alarmManager = binding.root.context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val pendingIntent = Intent(binding.root.context, MyAlarmReceiver::class.java).let {
            it.putExtra("code", REQUEST_CODE)
            it.putExtra("count", 10)
            PendingIntent.getBroadcast(binding.root.context, REQUEST_CODE, it, 0)
        }

        binding.switch01.setOnCheckedChangeListener { _, isCheck ->
            setting.edit {
                putBoolean("alarm", isCheck)
            }
            if(isCheck) {
                alarmManager.set(
                    AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    SystemClock.elapsedRealtime() + 1000 * 10,
                    pendingIntent
                )
                appendLog("Alarm Start")
            } else {
                alarmManager.cancel(pendingIntent)
                appendLog("Alarm Cancel")
            }
        }
    }

    fun appendLog(str: String) {
        binding.logText.text = "${binding.logText.text}\n${str}"
    }
}

 

 

 

아래는 알람을 등록하는 부분으로서 여기서는 알람을 On 하고 10초 후 알람이 발생하도록 하였다.

alarmManager.set(
    AlarmManager.ELAPSED_REALTIME_WAKEUP,
    SystemClock.elapsedRealtime() + 1000 * 10,
    pendingIntent
)

시간을 지정하는 방법에 관하여 자세한 내용을 알고 싶다면 글 상단 요약 부분에 있는 AlarmManager 글을 참고하면 될 것 같다.

 

 

추가적으로 appendLog 함수는 TextView의 Text를 추가하도록 하는 함수로서 알람을 On/Off 하였을 때 알 수 있도록 호출하여 TextView에 나타내도록 하였다.

 


 

3-2. MyAlarmReceiver.kt

Receiver를 정의한 부분으로서 Alarm이 발생하였을 때 어떤 동작을 할지 정의한다.

 

해당 부분을 정의하기 전 우선 Manifests 파일에 아래처럼 receiver를 등록해주어야 한다.

...
    </activity>
    <receiver android:name=".MyAlarmReceiver" android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
        </intent-filter>
    </receiver>
</application>

 

 

 

알람을 통하여 지정한 시간에 동작하도록 하였으므로 그 동작으로서 Notification(알림)을 발생시키면 원하는 시간에 알림을 발생시키도록 할 수 있게 된다.

 

알림을 정의하는 방법에 관해서는 알림 채널 생성 및 Builder를 구성한 후 빌드하도록 하는 것이며, 알림의 관한 자세한 설명이 필요할 경우 상단 요약 부분에 있는 Notification 글을 참고하면 될 것 같다.

 

package com.notepad96.alarmnotification

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat

class MyAlarmReceiver: BroadcastReceiver() {
    val CHANNEL_ID = "Test"
    override fun onReceive(context: Context, intent: Intent) {
        if(intent.extras?.get("code") == MainActivity.REQUEST_CODE) {
            var count = intent.getIntExtra("count", 0)
            Log.d("myLog", "$count")

            MainActivity.view.instance.appendLog("Alarm Check $count")


            createNotificationChannel(context)

            val intent = Intent(context, MainActivity::class.java).apply {
                flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            }
            val pendingIntent = PendingIntent.getActivity(context, 101, intent, 0)

            val contents = "Contents Contents Contents Contents Contents Contents Contents " +
                    "Contents Contents Contents Contents Contents Contents Contents "

            // Notification
            var builder01 = NotificationCompat.Builder(context, CHANNEL_ID).apply {
                setSmallIcon(R.drawable.ic_baseline_apple_24)
                setContentTitle("Title 1")  // Set Title
                setContentText(contents)   // Set Content
                priority = NotificationCompat.PRIORITY_DEFAULT  // Set PRIORITY
                setContentIntent(pendingIntent) // Notification Click Event
                setAutoCancel(true) // Remove After Click Notification
            }

            with(NotificationManagerCompat.from(context)) {
                notify(5, builder01.build())
            }
        }
    }

    private fun createNotificationChannel(context: Context?) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Notification_Ch"
            val descriptionText = "Test Notification"
            val channel = NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT).apply {
                description = descriptionText
            }

            val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
}

 

 

 

 

4. 전체 파일

 

 

GitHub - Notepad96/BlogExample02

Contribute to Notepad96/BlogExample02 development by creating an account on GitHub.

github.com

 

300x250