Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีใช้งาน AlarmManager ใน Android ด้วย Kotlin

ภาพรวม

ตัวอย่างนี้สาธิตการใช้ AlarmManager เพื่อตั้งเวลาปลุก (Alarm) ซ้ำทุกวันในเวลาที่ผู้ใช้เลือกผ่าน TimePicker

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

เปิด Android Studio เลือก File → New Project

ขั้นตอนที่ 2: Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".MainActivity">

    <TimePicker
        android:id="@+id/timePicker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" />

    <Button
        android:id="@+id/buttonAlarm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/timePicker"
        android:layout_centerInParent="true"
        android:layout_marginTop="10dp"
        android:text="Set Alarm" />

</RelativeLayout>

ขั้นตอนที่ 3: MainActivity.kt

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TimePicker
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.util.Calendar

class MainActivity : AppCompatActivity() {
    private lateinit var btnSetAlarm: Button
    private lateinit var timePicker: TimePicker

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

        timePicker = findViewById(R.id.timePicker)
        btnSetAlarm = findViewById(R.id.buttonAlarm)

        btnSetAlarm.setOnClickListener {
            val calendar = Calendar.getInstance()

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                calendar.set(
                    calendar.get(Calendar.YEAR),
                    calendar.get(Calendar.MONTH),
                    calendar.get(Calendar.DAY_OF_MONTH),
                    timePicker.hour,
                    timePicker.minute,
                    0
                )
            } else {
                @Suppress("DEPRECATION")
                val currentHour = timePicker.currentHour
                @Suppress("DEPRECATION")
                val currentMinute = timePicker.currentMinute
                calendar.set(
                    calendar.get(Calendar.YEAR),
                    calendar.get(Calendar.MONTH),
                    calendar.get(Calendar.DAY_OF_MONTH),
                    currentHour,
                    currentMinute,
                    0
                )
            }

            setAlarm(calendar.timeInMillis)
        }
    }

    private fun setAlarm(timeInMillis: Long) {
        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val intent = Intent(this, MyAlarm::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            this, 0, intent, 
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        alarmManager.setRepeating(
            AlarmManager.RTC_WAKEUP,
            timeInMillis,
            AlarmManager.INTERVAL_DAY,
            pendingIntent
        )

        Toast.makeText(this, "Alarm is set for daily", Toast.LENGTH_SHORT).show()
    }

    // Inner BroadcastReceiver สำหรับรับ Alarm
    private class MyAlarm : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            Log.d("Alarm Bell", "Alarm just fired")
            // ที่นี่สามารถเริ่ม Service หรือแสดง Notification ได้
        }
    }
}

ขั้นตอนที่ 4: Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.alarmmanager">

    <!-- สำหรับ Android 12+ ต้องการสิทธิ์ SCHEDULE_EXACT_ALARM -->
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />

    <application ... >
        <activity android:name=".MainActivity"> ... </activity>
        
        <!-- ต้องประกาศ Receiver ใน Manifest สำหรับ AlarmManager -->
        <receiver android:name=".MainActivity$MyAlarm" 
            android:exported="false" />
    </application>
</manifest>

หมายเหตุสำคัญ

  • Android 6.0+ (Doze Mode): ใช้ setExactAndAllowWhileIdle หรือ setAlarmClock สำหรับ Alarm ที่แม่นยำ
  • Android 12+: ต้องขอสิทธิ์ SCHEDULE_EXACT_ALARM จากผู้ใช้
  • PendingIntent.FLAG_IMMUTABLE จำเป็นสำหรับ Android 12+
  • Receiver ต้องประกาศใน Manifest (android:exported="false" เพื่อความปลอดภัย)
  • ในทางปฏิบัติ ควรใช้ WorkManager สำหรับงานที่ต้องการความน่าเชื่อถือสูง

การทดสอบ

รันแอป เลือกเวลาใน TimePicker กด "Set Alarm" จะมี Toast ยืนยัน ตรวจสอบ Logcat จะเห็น "Alarm just fired" เมื่อถึงเวลา