본문 바로가기
공부/Android Studio

[Android/Kotlin] AlarmManager 사용법

by 웅대 2023. 1. 5.
728x90
반응형

지금까지 ForegroundService와 WorkManager에 대해서 공부했다.

 

AlarmManager의 경우 비교적 짧은 시간동안 작업을 하고 정확한 시간에 끝낼 때 사용한다.

 

특정 시간이 지나면 시간이 다 된 것을 notification으로 알리는 앱을 만들어보려 한다.

 

뷰바인딩을 사용할 예정이므로 뷰바인딩을 세팅해준다.

https://growth-coder.tistory.com/30

 

[Android/Kotlin] activity와 fragment에서 view binding 사용법

view binding을 사용하면 view에 존재하는 값들에 접근할 수 있다. 이전에는 view에 존재하는 값들에 접근하기 위해서는 해당 ID를 사용해서 findViewById를 사용하였다. 이제는 view binding을 사용하면 쉽게

growth-coder.tistory.com

 

activity_main.xml에서 id가 button인 버튼을 만들어준다.

 

<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/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

BroadcastReceiver를 상속받은 AlarmPractice 클래스를 만들어주고 onReceive를 오버라이딩한다.


class AlarmPractice : BroadcastReceiver(){
    override fun onReceive(context: Context?, intent: Intent?) {
        TODO("Not yet implemented")
    }

}

 

기본적으로 context가 null이면 안되기 때문에 run 영역함수를 사용한다.

 

영역함수에 대한 내용은 다음 포스팅을 참고하면 도움이 될 것 같다.

https://growth-coder.tistory.com/44

 

[Kotlin] 영역 함수 (run, let, with, apply, also)

코틀린에는 영역 함수라는 것이 존재한다. 영역 함수를 사용하면 특정 객체에 대한 식이라는 것을 알 수 있어서 가독성이 좋아진다. 영역 함수 모두 사용하는 목적은 비슷하지만 사용 방식에 있

growth-coder.tistory.com

Application을 상속받은 App 클래스에 notification channel에 관한 코드를 적어준다.

 

class App : Application(){
    //만든 앱을 AndroidManifest의 application 안에 등록
    //android:name = ".App"
    companion object {
        const val ALARM_CHANNEL_ID = "alarmnotification"
    }
    override fun onCreate(){
        super.onCreate()
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
            getSystemService(NotificationManager::class.java).run{
                val alarmChannel = NotificationChannel(
                    ALARM_CHANNEL_ID, //아이디
                    "AlarmManager", //이름
                    NotificationManager.IMPORTANCE_LOW //중요도. 높을수록 사용자에게 알리는 강도가 높아짐

                )
                createNotificationChannel(alarmChannel)
            }
        }
    }
}

 

AndroidManifest에 등록해준다.

 

<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">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AlarmManagerForPosting"
        android:name = ".App"
        tools:targetApi="31">
        <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>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

 

 

 

notification 생성에 대한 내용은 ForegroundService에서 다루었는데 궁금하다면 아래 포스팅의 notification 부분을 참고하면 좋을 듯 하다.

 

https://growth-coder.tistory.com/48

 

[Android/Kotlin] Foreground Service 사용 방법

음악을 틀어놓고 웹 서핑을 한다거나 애플리케이션을 설치하면서 문자를 한다거나 이렇게 특정 동작을 수행 도중에 다른 동작도 수행할 일이 있을 수 있다. 위의 예시에서 음악, 앱 설치의 경우

growth-coder.tistory.com

const val ALARM_NOTI_ID = 1
//receiver를 만들고 나면 manifest application 안에 receiver를 등록해야한다.
//<receiver android:name=".AlarmPractice"/>
class AlarmPractice : BroadcastReceiver(){


    override fun onReceive(context: Context?, intent: Intent?) {
        context?.let{
            val intent = Intent(context, MainActivity::class.java)
            val pendingIntent = PendingIntent.getActivity(
                context, //context
                0, //request code
                intent, //flag
                PendingIntent.FLAG_IMMUTABLE //flag

            )
            val notiBuilder = NotificationCompat.Builder(context,App.ALARM_CHANNEL_ID)
                .setContentTitle("alarm manager")
                .setContentText("alarm complete")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentIntent(pendingIntent)

            context.getSystemService(NotificationManager::class.java)
                .notify(ALARM_NOTI_ID, notiBuilder.build())
        }
    }

}

 

이제 Receiver를 만들었으면 AndroidManifest에 등록을 해야한다.

 

application 안에 다음 코드를 작성해준다.

<receiver android:name=".AlarmPractice"/>

 

<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">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AlarmManagerForPosting"
        tools:targetApi="31">
        <receiver android:name=".AlarmPractice"/>
        <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>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

 

이제 메인 액티비티에서 버튼 클릭 이벤트를 설정해준다.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.button.setOnClickListener {
            val intent = Intent(this, AlarmPractice::class.java)
            val pendingIntent = PendingIntent.getBroadcast(
                this,
            0,
            intent,
            PendingIntent.FLAG_IMMUTABLE)
            getSystemService(AlarmManager::class.java).setExact(
                AlarmManager.RTC_WAKEUP,
                SystemClock.elapsedRealtime()+5*1000,// 현재 시각으로부터 5초 뒤
                pendingIntent
            )
        }
    }
}

 

이제 manifest에서 퍼미션을 설정해줘야한다.

 

퍼미션은 application 밖에서 설정해준다.

 

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

<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.SCHEDULE_EXACT_ALARM"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AlarmManagerForPosting"
        tools:targetApi="31">
        <receiver android:name=".AlarmPractice"/>
        <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>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

 

실행을 해서 버튼을 누르면 5초 뒤에 notification이 오는 것을 확인할 수 있다.

 

728x90
반응형

댓글