AlarmManager
) ช่วยให้คุณดำเนินการตามเวลาได้นอกช่วงอายุการใช้งานของแอปพลิเคชัน
เช่น คุณสามารถใช้การปลุกเพื่อเริ่มการดำเนินการที่ใช้เวลานาน เช่น การเริ่มบริการวันละครั้งเพื่อดาวน์โหลดพยากรณ์อากาศ
โดยการปลุกจะมีลักษณะดังนี้
ซึ่งช่วยให้คุณเรียกใช้ Intent ในเวลาและ/หรือช่วงเวลาที่กำหนดได้
คุณสามารถใช้ร่วมกับ BroadcastReceiver เพื่อกำหนดเวลางานหรือ WorkRequest เพื่อดำเนินการอื่นๆ ได้
โดยจะทำงานภายนอกแอปพลิเคชันของคุณ คุณจึงใช้เพื่อทริกเกอร์เหตุการณ์หรือการดำเนินการได้แม้ว่าแอปจะไม่ได้ทำงานอยู่ และแม้ว่าอุปกรณ์จะเข้าสู่โหมดสลีปก็ตาม
ซึ่งจะช่วยให้คุณลดข้อกำหนดด้านทรัพยากรของแอปได้ คุณสามารถกำหนดเวลา การดำเนินการได้โดยไม่ต้องอาศัยตัวจับเวลาหรือบริการที่ทำงานอย่างต่อเนื่อง
ตั้งปลุกแบบไม่ตรงเวลา
เมื่อแอปตั้งการปลุกที่ไม่แน่นอน ระบบจะส่งการปลุกในเวลาใดเวลาหนึ่ง ในอนาคต การปลุกที่ไม่แน่นอนจะรับประกันเวลาในการส่งการปลุกบางอย่าง ขณะเดียวกันก็เคารพข้อจำกัดในการประหยัดแบตเตอรี่ เช่น Doze
นักพัฒนาแอปสามารถใช้ประโยชน์จากการรับประกัน API ต่อไปนี้เพื่อปรับแต่งเวลาในการนำส่งการปลุกที่ไม่แน่นอน
ส่งเสียงปลุกหลังจากเวลาที่ระบุ
หากแอปของคุณเรียกใช้ set()
,
setInexactRepeating()
,
หรือ setAndAllowWhileIdle()
,
สัญญาณเตือนจะไม่ดังก่อนเวลาทริกเกอร์ที่ระบุ
ใน Android 12 (API ระดับ 31) ขึ้นไป ระบบจะเรียกใช้การปลุกภายใน 1 ชั่วโมงของเวลาทริกเกอร์ที่ระบุ เว้นแต่จะมีการจำกัดการประหยัดแบตเตอรี่ เช่น โหมดประหยัดแบตเตอรี่หรือโหมดพักแอป
ส่งการแจ้งเตือนในช่วงเวลาที่กำหนด
หากแอปเรียกใช้ setWindow()
การปลุกจะไม่ดังก่อนเวลาทริกเกอร์ที่ระบุ
หากไม่มีข้อจำกัดในการประหยัดแบตเตอรี่ การปลุกจะ
ส่งภายในกรอบเวลาที่ระบุ โดยเริ่มจากเวลาทริกเกอร์ที่ระบุ
หากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป ระบบจะหน่วงเวลา
การเรียกใช้การปลุกที่ไม่แน่นอนแบบช่วงเวลาอย่างน้อย 10 นาที ด้วยเหตุนี้ ค่าพารามิเตอร์ windowLengthMillis
ภายใต้ 600000
จึงถูกตัดให้เหลือ 600000
ส่งการปลุกซ้ำในช่วงเวลาที่สม่ำเสมอโดยประมาณ
หากแอปเรียกใช้ setInexactRepeating()
ระบบจะเรียกใช้การปลุกหลายรายการ
- นาฬิกาปลุกแรกจะดังขึ้นภายในกรอบเวลาที่ระบุ โดยเริ่มจาก เวลาทริกเกอร์ที่ระบุ
- โดยปกติแล้ว นาฬิกาปลุกที่ตั้งไว้หลังจากนั้นจะดังขึ้นหลังจากช่วงเวลาที่ระบุผ่านไปแล้ว เวลาที่ผ่านไประหว่างการเรียกใช้การปลุก 2 ครั้งติดต่อกันอาจแตกต่างกันไป
ตั้งปลุกในเวลาที่แน่นอน
ระบบจะเรียกใช้การปลุกที่แน่นอนในเวลาที่แน่นอนในอนาคต
แอปส่วนใหญ่สามารถกำหนดเวลางานและกิจกรรมได้โดยใช้การปลุกที่ไม่แน่นอนเพื่อทำกรณีการใช้งานทั่วไปหลายอย่างให้เสร็จสมบูรณ์ หากฟังก์ชันหลักของแอปต้องใช้การปลุกในเวลาที่แน่นอน เช่น แอปนาฬิกาปลุกหรือแอปปฏิทิน คุณก็ใช้การปลุกในเวลาที่แน่นอนแทนได้
กรณีการใช้งานที่ไม่จำเป็นต้องใช้การปลุกในเวลาที่แน่นอน
รายการต่อไปนี้แสดงเวิร์กโฟลว์ทั่วไปที่อาจไม่กำหนดให้ใช้การตั้งปลุกในเวลาที่แน่นอน
- การกำหนดเวลาการดำเนินการในช่วงอายุการใช้งานของแอป
- คลาส
Handler
มีเมธอดดีๆ หลายอย่างสำหรับจัดการการดำเนินการตามเวลา เช่น การทำงานบางอย่างทุกๆ n วินาทีขณะที่แอปทำงานอยู่ ดังนี้postAtTime()
และpostDelayed()
โปรดทราบว่า API เหล่านี้ขึ้นอยู่กับเวลาทำงานของระบบ ไม่ใช่เรียลไทม์ - งานพื้นหลังที่กำหนดเวลาไว้ เช่น การอัปเดตแอปและการอัปโหลดบันทึก
WorkManager
เป็นวิธีกำหนดเวลาการทำงานเป็นระยะๆ ที่ต้องคำนึงถึงเวลา คุณระบุช่วงเวลาการทำซ้ำและflexInterval
(ขั้นต่ำ 15 นาที) เพื่อ กำหนดเวลาเรียกใช้แบบละเอียดสำหรับงานได้- การดำเนินการที่ผู้ใช้ระบุซึ่งควรเกิดขึ้นหลังจากเวลาที่เฉพาะเจาะจง (แม้ว่าระบบจะอยู่ในสถานะไม่ได้ใช้งาน)
- ใช้การปลุกที่ไม่แน่นอน โดยเฉพาะการโทร
setAndAllowWhileIdle()
- การดำเนินการที่ผู้ใช้ระบุซึ่งควรเกิดขึ้นหลังจากเวลาที่เฉพาะเจาะจง
- ใช้การปลุกที่ไม่แน่นอน โดยเฉพาะการโทร
set()
- การกระทําที่ผู้ใช้ระบุซึ่งอาจเกิดขึ้นภายในกรอบเวลาที่ระบุ
- ใช้การปลุกที่ไม่แน่นอน โดยเฉพาะการโทร
setWindow()
โปรดทราบว่าหากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป ความยาวของหน้าต่างที่เล็กที่สุด ที่อนุญาตคือ 10 นาที
วิธีตั้งปลุกในเวลาที่แน่นอน
แอปของคุณตั้งการปลุกในเวลาที่แน่นอนได้โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้ วิธีการเหล่านี้ จะเรียงตามลำดับเพื่อให้วิธีการที่อยู่ใกล้ด้านล่างของรายการมากขึ้นจะใช้สำหรับงานที่ต้องดำเนินการอย่างเร่งด่วน แต่ต้องใช้ทรัพยากรของระบบมากกว่า
setExact()
เรียกใช้การปลุกในเวลาที่แม่นยำเกือบที่สุดในอนาคต ตราบใดที่ไม่ได้ใช้มาตรการประหยัดแบตเตอรี่อื่นๆ
ใช้วิธีนี้เพื่อตั้งการปลุกในเวลาที่แน่นอน เว้นแต่ว่างานของแอปจะ มีความสำคัญต่อเวลาสำหรับผู้ใช้
setExactAndAllowWhileIdle()
เรียกใช้การปลุกในเวลาที่แม่นยำในอนาคต แม้ว่าจะมีการใช้มาตรการประหยัดแบตเตอรี่ก็ตาม
setAlarmClock()
เรียกใช้การปลุกในเวลาที่แน่นอนในอนาคต เนื่องจากนาฬิกาปลุกเหล่านี้ มองเห็นได้ชัดเจนสำหรับผู้ใช้ ระบบจึงไม่ปรับเวลาการนำส่ง ระบบจะระบุว่าการปลุกเหล่านี้มีความสำคัญมากที่สุด และจะออกจากโหมดประหยัดพลังงาน หากจำเป็นเพื่อส่งเสียงปลุก
การใช้ทรัพยากรของระบบ
เมื่อระบบทริกเกอร์การปลุกที่ตรงกันซึ่งแอปของคุณตั้งค่าไว้ อุปกรณ์จะใช้ทรัพยากรเป็นจำนวนมาก เช่น อายุการใช้งานแบตเตอรี่ โดยเฉพาะอย่างยิ่งหากอยู่ในโหมดประหยัดพลังงาน นอกจากนี้ ระบบยังจัดกลุ่มคำขอเหล่านี้เป็นชุดได้ยาก เพื่อใช้ทรัพยากรอย่างมีประสิทธิภาพมากขึ้น
เราขอแนะนำอย่างยิ่งให้คุณสร้างการปลุกที่ไม่แน่นอนทุกครั้งที่
เป็นไปได้ หากต้องการทำงานนานขึ้น ให้กำหนดเวลาโดยใช้
WorkManager
หรือ
JobScheduler
จาก
BroadcastReceiver
ของนาฬิกาปลุก หากต้องการทำงานขณะที่อุปกรณ์อยู่ในโหมดพัก ให้สร้างการปลุกในเวลาที่ไม่แน่นอนโดยใช้ setAndAllowWhileIdle()
แล้วเริ่มงานจากการปลุก
ประกาศสิทธิ์การปลุกในเวลาที่แน่นอนที่เหมาะสม
หากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป คุณต้องได้รับสิทธิ์เข้าถึงพิเศษของแอป "การปลุกและการช่วยเตือน"
โดยประกาศสิทธิ์
SCHEDULE_EXACT_ALARM
ในไฟล์ Manifest ของแอป ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
<manifest ...> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
หากแอปกำหนดเป้าหมายเป็น Android 13 (API ระดับ 33) ขึ้นไป คุณจะมีตัวเลือกในการ
ประกาศสิทธิ์ SCHEDULE_EXACT_ALARM
หรือสิทธิ์ USE_EXACT_ALARM
<manifest ...> <uses-permission android:name="android.permission.USE_EXACT_ALARM"/> <application ...> ... </application> </manifest>
แม้ว่าสิทธิ์ SCHEDULE_EXACT_ALARM
และ USE_EXACT_ALARM
จะส่งสัญญาณความสามารถเดียวกัน แต่จะมีการให้สิทธิ์ที่แตกต่างกันและรองรับกรณีการใช้งานที่แตกต่างกัน แอปของคุณควรใช้การปลุกในเวลาที่แน่นอน และประกาศสิทธิ์ SCHEDULE_EXACT_ALARM
หรือ USE_EXACT_ALARM
เฉพาะในกรณีที่ฟังก์ชันที่แสดงต่อผู้ใช้ในแอปของคุณต้องใช้การดำเนินการที่มีเวลาแน่นอน
USE_EXACT_ALARM
- ให้สิทธิ์โดยอัตโนมัติ
- ผู้ใช้เพิกถอนไม่ได้
- ขึ้นอยู่กับนโยบายของ Google Play ที่กำลังจะมีผลบังคับใช้
- กรณีการใช้งานที่จำกัด
SCHEDULE_EXACT_ALARM
- ได้รับจากผู้ใช้
- กรณีการใช้งานที่หลากหลายมากขึ้น
- แอปควรยืนยันว่าสิทธิ์ไม่ได้ถูกเพิกถอน
ระบบไม่ได้ให้สิทธิ์ SCHEDULE_EXACT_ALARM
ล่วงหน้าสำหรับการติดตั้งแอปใหม่ที่กำหนดเป้าหมายเป็น Android 13 (API ระดับ 33) ขึ้นไป
หากผู้ใช้โอนข้อมูลแอป
ไปยังอุปกรณ์ที่ใช้ Android 14 ผ่านการดำเนินการสำรองและกู้คืน ระบบจะปฏิเสธสิทธิ์ SCHEDULE_EXACT_ALARM
ในอุปกรณ์ใหม่ อย่างไรก็ตาม หากแอปที่มีอยู่มีสิทธิ์นี้อยู่แล้ว ระบบจะให้สิทธิ์ล่วงหน้าเมื่ออุปกรณ์อัปเกรดเป็น Android 14
หมายเหตุ: หากตั้งปลุกในเวลาที่แน่นอนโดยใช้ออบเจ็กต์
OnAlarmListener
เช่น API setExact
ก็ไม่จำเป็นต้องมีสิทธิ์ SCHEDULE_EXACT_ALARM
การใช้สิทธิ์ SCHEDULE_EXACT_ALARM
SCHEDULE_EXACT_ALARM
ต่างจาก USE_EXACT_ALARM
ตรงที่ผู้ใช้ต้องให้สิทธิ์ SCHEDULE_EXACT_ALARM
ทั้งผู้ใช้และระบบสามารถเพิกถอนสิทธิ์
SCHEDULE_EXACT_ALARM
ได้
หากต้องการตรวจสอบว่าแอปได้รับสิทธิ์หรือไม่ ให้เรียกใช้
canScheduleExactAlarms()
ก่อนที่จะพยายามตั้งปลุกในเวลาที่แน่นอน เมื่อมีการเพิกถอนSCHEDULE_EXACT_ALARM
สิทธิ์
สำหรับแอปของคุณ แอปจะหยุดทำงาน และการปลุกในเวลาที่แน่นอนทั้งหมดในอนาคต
จะถูกยกเลิก ซึ่งหมายความว่าค่าที่ฟังก์ชัน
canScheduleExactAlarms()
แสดงผลจะยังคงใช้ได้ตลอดวงจรของแอป
เมื่อแอปได้รับสิทธิ์ SCHEDULE_EXACT_ALARMS
ระบบจะส่งการออกอากาศ
ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
ให้แอป แอปของคุณควรใช้ Broadcast
Receiver ที่ทำสิ่งต่อไปนี้
- ยืนยันว่าแอปของคุณยังคงมีสิทธิ์เข้าถึงแอปพิเศษ โดยโทรไปที่
canScheduleExactAlarms()
การตรวจสอบนี้จะปกป้องแอปของคุณในกรณีที่ผู้ใช้ให้สิทธิ์แก่แอป แล้วเพิกถอนสิทธิ์นั้นในเวลาต่อมาแทบจะทันที - ตั้งเวลาการปลุกในเวลาที่แน่นอนที่แอปของคุณต้องการใหม่ โดยอิงตามสถานะปัจจุบันของแอป
ตรรกะนี้ควรคล้ายกับสิ่งที่แอปทำเมื่อได้รับ
ACTION_BOOT_COMPLETED
การออกอากาศ
ขอให้ผู้ใช้ให้สิทธิ์ SCHEDULE_EXACT_ALARM
หากจำเป็น คุณสามารถส่งผู้ใช้ไปยังหน้าจอการปลุกและการช่วยเตือนในการตั้งค่าระบบ ตามที่แสดงในรูปที่ 1 โดยทำตามขั้นตอนต่อไปนี้
- ใน UI ของแอป ให้อธิบายแก่ผู้ใช้ว่าทำไมแอปของคุณจึงต้องตั้งเวลาปลุกที่แน่นอน
- เรียกใช้ Intent ที่มี
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
การดำเนินการของ Intent
ตั้งปลุกซ้ำ
การปลุกซ้ำช่วยให้ระบบแจ้งเตือนแอปของคุณตามกำหนดเวลาที่เกิดซ้ำได้
การปลุกที่ออกแบบมาไม่ดีอาจทำให้แบตเตอรี่หมดและสร้างภาระงานอย่างหนักในเซิร์ฟเวอร์ ด้วยเหตุนี้ ใน Android 4.4 (API ระดับ 19) ขึ้นไป การปลุกที่ทำซ้ำทั้งหมดจึงเป็นการปลุกที่ไม่แน่นอน
การปลุกซ้ำมีลักษณะดังนี้
ประเภทการปลุก ดูข้อมูลเพิ่มเติมได้ที่เลือกประเภทการปลุก
เวลาทริกเกอร์ หากเวลาทริกเกอร์ที่คุณระบุอยู่ในอดีต นาฬิกาปลุกจะ ทริกเกอร์ทันที
ช่วงเวลาของนาฬิกาปลุก เช่น วันละครั้ง ทุกชั่วโมง หรือทุก 5 นาที
PendingIntent ที่เริ่มทำงานเมื่อมีการทริกเกอร์การปลุก เมื่อตั้งปลุกที่ 2 ซึ่งใช้ PendingIntent เดียวกัน ระบบจะแทนที่การปลุกเดิม
หากต้องการยกเลิก PendingIntent()
ให้ส่ง
FLAG_NO_CREATE
ไปยัง PendingIntent.getService()
เพื่อรับอินสแตนซ์ของ Intent (หากมี) จากนั้นส่ง Intent นั้นไปยัง
AlarmManager.cancel()
Kotlin
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager val pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE) if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent) }
Java
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = PendingIntent.getService(context, requestId, intent, PendingIntent.FLAG_NO_CREATE); if (pendingIntent != null && alarmManager != null) { alarmManager.cancel(pendingIntent); }
เลือกประเภทการปลุก
สิ่งแรกที่ควรพิจารณาในการใช้นาฬิกาปลุกที่ตั้งซ้ำคือประเภทของนาฬิกาปลุก
นาฬิกาปลุกมี 2 ประเภทหลักๆ ได้แก่ "เวลาจริงที่ผ่านไป" และ "นาฬิกาเวลาจริง" (RTC) เวลาจริงที่ผ่านไปใช้ "เวลาตั้งแต่ระบบบูต" เป็นข้อมูลอ้างอิง และนาฬิกาเวลาจริงใช้เวลา UTC (นาฬิกาติดผนัง) ซึ่งหมายความว่า เวลาจริงที่ผ่านไปเหมาะกับการตั้งปลุกตามเวลาที่ผ่านไป (เช่น การปลุกที่ดังทุกๆ 30 วินาที) เนื่องจากไม่ได้รับผลกระทบจาก เขตเวลาหรือภาษา ประเภทนาฬิกาแบบเรียลไทม์เหมาะสำหรับนาฬิกาปลุกที่ ขึ้นอยู่กับภาษาปัจจุบันมากกว่า
ทั้ง 2 ประเภทมีเวอร์ชัน "ปลุก" ซึ่งจะสั่งให้ปลุก CPU ของอุปกรณ์หาก หน้าจอปิดอยู่ เพื่อให้มั่นใจว่าการปลุกจะทำงานตามเวลาที่กำหนด วิธีนี้มีประโยชน์หากแอปของคุณมีทรัพยากร Dependency ที่ขึ้นอยู่กับเวลา เช่น หากมีช่วงเวลาที่จำกัดในการดำเนินการใดๆ หากคุณไม่ได้ใช้ เวอร์ชันปลุกของประเภทการปลุก นาฬิกาปลุกที่ตั้งซ้ำทั้งหมดจะดัง เมื่ออุปกรณ์ตื่นขึ้นในครั้งถัดไป
หากคุณเพียงต้องการให้การปลุกทำงานในช่วงเวลาที่เฉพาะเจาะจง (เช่น ทุกครึ่งชั่วโมง) ให้ใช้ประเภทเวลาจริงที่ผ่านไปประเภทใดประเภทหนึ่ง โดยทั่วไปแล้ว ตัวเลือกนี้ เป็นตัวเลือกที่ดีกว่า
หากต้องการให้การปลุกทำงานในเวลาที่เฉพาะเจาะจงของวัน ให้เลือกประเภทนาฬิกาแบบเรียลไทม์ที่อิงตามนาฬิกา อย่างไรก็ตาม โปรดทราบว่าวิธีนี้อาจมีข้อเสียบางประการ แอปอาจแปลเป็นภาษาอื่นๆ ได้ไม่ดี และหากผู้ใช้เปลี่ยนการตั้งค่าเวลาของอุปกรณ์ อาจทำให้แอปมีลักษณะการทำงานที่ไม่คาดคิด การใช้นาฬิกาปลุกแบบเรียลไทม์ยังปรับขนาดได้ไม่ดีตามที่กล่าวไว้ข้างต้น เราขอแนะนำให้คุณใช้นาฬิกาปลุก "เวลาจริงที่ผ่านไป" หากทำได้
รายการประเภทมีดังนี้
ELAPSED_REALTIME
: เรียกใช้ PendingIntent ตามระยะเวลาตั้งแต่เริ่มระบบอุปกรณ์ แต่จะไม่ปลุกอุปกรณ์ เวลาที่ผ่านไปรวมถึงเวลาที่อุปกรณ์อยู่ในโหมดสลีปELAPSED_REALTIME_WAKEUP
: ปลุกอุปกรณ์และเรียกใช้ PendingIntent หลังจากผ่านระยะเวลาที่ระบุ นับตั้งแต่การบูตอุปกรณ์RTC
: เรียกใช้ PendingIntent ในเวลาที่ระบุ แต่จะไม่ปลุกอุปกรณ์RTC_WAKEUP
: ปลุกอุปกรณ์เพื่อเรียกใช้ PendingIntent ในเวลาที่ระบุ
ตัวอย่างการปลุกตามเวลาจริงที่ผ่านไป
ตัวอย่างการใช้ ELAPSED_REALTIME_WAKEUP
ปลุกอุปกรณ์เพื่อส่งเสียงปลุกในอีก 30 นาที และทุกๆ 30 นาทีหลังจากนั้น
Kotlin
// Hopefully your alarm will have a lower frequency than this! alarmMgr?.setInexactRepeating( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent )
Java
// Hopefully your alarm will have a lower frequency than this! alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);
ปลุกอุปกรณ์เพื่อตั้งปลุกแบบครั้งเดียว (ไม่ซ้ำ) ใน 1 นาที
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } alarmMgr?.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60 * 1000, alarmIntent);
ตัวอย่างการปลุกของนาฬิกาแบบเรียลไทม์
ตัวอย่างการใช้
RTC_WAKEUP
ปลุกอุปกรณ์เพื่อส่งเสียงปลุกเวลาประมาณ 14:00 น. และ ทำซ้ำวันละครั้งในเวลาเดียวกัน
Kotlin
// Set the alarm to start at approximately 2:00 p.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 14) } // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr?.setInexactRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, alarmIntent )
Java
// Set the alarm to start at approximately 2:00 p.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 14); // With setInexactRepeating(), you have to use one of the AlarmManager interval // constants--in this case, AlarmManager.INTERVAL_DAY. alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
ปลุกอุปกรณ์เพื่อตั้งปลุกเวลา 08:30 น. และทุกๆ 20 นาทีหลังจากนั้น
Kotlin
private var alarmMgr: AlarmManager? = null private lateinit var alarmIntent: PendingIntent ... alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent -> PendingIntent.getBroadcast(context, 0, intent, 0) } // Set the alarm to start at 8:30 a.m. val calendar: Calendar = Calendar.getInstance().apply { timeInMillis = System.currentTimeMillis() set(Calendar.HOUR_OF_DAY, 8) set(Calendar.MINUTE, 30) } // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr?.setRepeating( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, 1000 * 60 * 20, alarmIntent )
Java
private AlarmManager alarmMgr; private PendingIntent alarmIntent; ... alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); // Set the alarm to start at 8:30 a.m. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 8); calendar.set(Calendar.MINUTE, 30); // setRepeating() lets you specify a precise custom interval--in this case, // 20 minutes. alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60 * 20, alarmIntent);
เลือกระดับความแม่นยำของนาฬิกาปลุก
ดังที่ได้อธิบายไว้ก่อนหน้านี้ การเลือกประเภทการปลุกมักเป็นขั้นตอนแรกในการ
สร้างการปลุก ความแตกต่างอีกประการคือความแม่นยำของนาฬิกาปลุกที่คุณต้องการ
สำหรับแอปส่วนใหญ่
setInexactRepeating()
เป็นตัวเลือกที่เหมาะสม เมื่อใช้วิธีนี้ Android จะซิงค์การปลุกที่ทำซ้ำหลายรายการที่ไม่แน่นอนและเรียกใช้
พร้อมกัน ซึ่งจะช่วยลดการเปลืองแบตเตอรี่
หลีกเลี่ยงการใช้การปลุกในเวลาที่แน่นอนหากเป็นไปได้ อย่างไรก็ตาม สำหรับแอปที่พบได้น้อยซึ่งมีข้อกำหนดด้านเวลาที่เข้มงวด คุณสามารถตั้งการปลุกที่แน่นอนได้โดยการเรียกใช้ setRepeating()
setInexactRepeating()
คุณไม่สามารถระบุช่วงเวลาที่กำหนดเองได้เหมือนกับที่ทำได้ใน
setRepeating()
คุณต้องใช้ค่าคงที่ช่วงเวลาอย่างใดอย่างหนึ่ง เช่น
INTERVAL_FIFTEEN_MINUTES
,
INTERVAL_DAY
เป็นต้น ดูรายการทั้งหมดได้ที่ AlarmManager
ยกเลิกการปลุก
คุณอาจต้องรวมความสามารถในการยกเลิกการปลุกไว้ด้วย ทั้งนี้ขึ้นอยู่กับแอป
หากต้องการยกเลิกการปลุก ให้เรียกใช้ cancel()
ใน Alarm Manager โดยส่ง PendingIntent
ที่คุณไม่ต้องการ
ให้ทริกเกอร์อีกต่อไป เช่น
Kotlin
// If the alarm has been set, cancel it. alarmMgr?.cancel(alarmIntent)
Java
// If the alarm has been set, cancel it. if (alarmMgr!= null) { alarmMgr.cancel(alarmIntent); }
ตั้งปลุกเมื่ออุปกรณ์รีสตาร์ท
โดยค่าเริ่มต้น ระบบจะยกเลิกการปลุกทั้งหมดเมื่ออุปกรณ์ปิด
หากต้องการป้องกันไม่ให้เกิดเหตุการณ์นี้ คุณสามารถออกแบบแอปพลิเคชัน
ให้รีสตาร์ทการปลุกที่ทำซ้ำโดยอัตโนมัติหากผู้ใช้รีบูตอุปกรณ์ ซึ่งจะช่วยให้ AlarmManager
ทำงานต่อไปได้โดยที่ผู้ใช้ไม่ต้องรีสตาร์ทการปลุกด้วยตนเอง
มีขั้นตอนดังนี้
ตั้งค่าสิทธิ์
RECEIVE_BOOT_COMPLETED
ในไฟล์ Manifest ของแอปพลิเคชัน ซึ่งจะช่วยให้แอปได้รับACTION_BOOT_COMPLETED
ที่ออกอากาศหลังจากที่ระบบบูตเสร็จสิ้น (การดำเนินการนี้จะใช้ได้ก็ต่อเมื่อผู้ใช้ได้เปิดแอปอย่างน้อย 1 ครั้งแล้วเท่านั้น)<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
ใช้
BroadcastReceiver
เพื่อรับการออกอากาศKotlin
class SampleBootReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == "android.intent.action.BOOT_COMPLETED") { // Set the alarm here. } } }
Java
public class SampleBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { // Set the alarm here. } } }
เพิ่มตัวรับลงในไฟล์ Manifest ของแอปด้วยตัวกรอง Intent ที่ กรองตาม
ACTION_BOOT_COMPLETED
การดำเนินการ<receiver android:name=".SampleBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> </intent-filter> </receiver>
โปรดทราบว่าในไฟล์ Manifest ตัวรับสัญญาณการบูตจะตั้งค่าเป็น
android:enabled="false"
ซึ่งหมายความว่าจะไม่มีการเรียกใช้ตัวรับ เว้นแต่แอปพลิเคชันจะเปิดใช้โดยชัดแจ้ง ซึ่งจะป้องกันไม่ให้มีการเรียกใช้ ตัวรับสัญญาณการบูตโดยไม่จำเป็น คุณเปิดใช้ตัวรับ (เช่น หากผู้ใช้ตั้งนาฬิกาปลุก) ได้ดังนี้Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
เมื่อเปิดใช้ตัวรับสัญญาณด้วยวิธีนี้แล้ว ตัวรับสัญญาณจะยังคงเปิดใช้ต่อไปแม้ว่าผู้ใช้จะรีบูตอุปกรณ์ก็ตาม กล่าวคือ การเปิดใช้ตัวรับสัญญาณโดยใช้โปรแกรมจะลบล้างการตั้งค่า Manifest แม้จะรีบูตก็ตาม ตัวรับจะยังคง เปิดใช้จนกว่าแอปจะปิดใช้ คุณปิดใช้ตัวรับได้ (เช่น หากผู้ใช้ยกเลิกการปลุก) โดยทำดังนี้
Kotlin
val receiver = ComponentName(context, SampleBootReceiver::class.java) context.packageManager.setComponentEnabledSetting( receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP )
Java
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
เรียกใช้การปลุกขณะที่อุปกรณ์อยู่ในโหมดพัก
อุปกรณ์ที่ใช้ Android 6.0 (API ระดับ 23) รองรับโหมด พักเครื่อง ซึ่งช่วยยืดอายุการใช้งานแบตเตอรี่ของอุปกรณ์ นาฬิกาปลุกจะไม่ทำงานเมื่ออุปกรณ์อยู่ในโหมดพักเครื่อง ระบบจะเลื่อนการปลุกที่กำหนดเวลาไว้จนกว่าอุปกรณ์จะออกจากโหมดพักเครื่อง หากต้องการ ทำงานให้เสร็จแม้ในขณะที่อุปกรณ์ไม่ได้ใช้งาน คุณมีตัวเลือกหลายอย่าง ดังนี้
ตั้งปลุกที่แน่นอน
ใช้ WorkManager API ซึ่งสร้างขึ้นเพื่อทำงานในเบื้องหลัง คุณสามารถระบุให้ระบบเร่งดำเนินการกับงานของคุณเพื่อให้งานเสร็จโดยเร็วที่สุด ดูข้อมูลเพิ่มเติมได้ที่ กำหนดเวลางานด้วย WorkManager
แนวทางปฏิบัติแนะนำ
ทุกตัวเลือกที่คุณเลือกในการออกแบบนาฬิกาปลุกที่ปลุกซ้ำอาจส่งผลต่อวิธีที่แอปใช้ (หรือละเมิด) ทรัพยากรของระบบ ตัวอย่างเช่น ลองนึกถึง แอปยอดนิยมที่ซิงค์กับเซิร์ฟเวอร์ หากการดำเนินการซิงค์อิงตามเวลา และอินสแตนซ์ทั้งหมดของแอปซิงค์เวลา 23:00 น. ภาระงานใน เซิร์ฟเวอร์อาจทำให้เกิดเวลาในการตอบสนองสูงหรือแม้แต่ "การปฏิเสธการให้บริการ" ทำตามแนวทางปฏิบัติแนะนำต่อไปนี้ในการใช้นาฬิกาปลุก
เพิ่มความสุ่ม (Jitter) ให้กับคำขอเครือข่ายที่ ทริกเกอร์อันเป็นผลมาจากสัญญาณเตือนที่ทำซ้ำ
ดำเนินการใดๆ ในพื้นที่เมื่อมีการปลุก "งานในเครื่อง" หมายถึงสิ่งที่ไม่ต้องใช้เซิร์ฟเวอร์หรือข้อมูลจากเซิร์ฟเวอร์
ในขณะเดียวกัน ให้ตั้งเวลาปลุกที่มีคำขอเครือข่ายให้ ทำงานในช่วงเวลาแบบสุ่ม
ตั้งความถี่ในการปลุกให้น้อยที่สุด
อย่าปลุกอุปกรณ์โดยไม่จำเป็น (ลักษณะการทำงานนี้จะกำหนดโดย ประเภทการปลุก ตามที่อธิบายไว้ในเลือกประเภทการปลุก)
อย่าตั้งเวลาทริกเกอร์ของนาฬิกาปลุกให้แม่นยำกว่าที่จำเป็น
ใช้
setInexactRepeating()
แทนsetRepeating()
เมื่อคุณใช้setInexactRepeating()
Android จะซิงค์การปลุกที่ทำซ้ำจากแอปหลายแอปและเรียกใช้ พร้อมกัน ซึ่งจะช่วยลดจำนวนครั้งทั้งหมดที่ระบบต้องปลุก อุปกรณ์ จึงช่วยลดการใช้แบตเตอรี่ ตั้งแต่ Android 4.4 (API ระดับ 19) เป็นต้นไป การปลุกที่ทำซ้ำทั้งหมดจะเป็นการปลุกที่ไม่แน่นอน โปรดทราบว่าแม้ว่าsetInexactRepeating()
จะดีกว่าsetRepeating()
แต่ก็ยังอาจทำให้เซิร์ฟเวอร์ทำงานหนักเกินไปได้หากอินสแตนซ์ของแอปทุกรายการเข้าถึงเซิร์ฟเวอร์ในเวลาใกล้เคียงกัน ดังนั้น สำหรับคำขอเครือข่าย ให้เพิ่มความสุ่มลงใน การปลุกตามที่ได้กล่าวไว้ก่อนหน้านี้หากเป็นไปได้ ให้หลีกเลี่ยงการตั้งเวลาปลุกตามเวลาของนาฬิกา
การปลุกซ้ำที่อิงตามเวลาทริกเกอร์ที่แน่นอนจะปรับขนาดได้ไม่ดี ใช้
ELAPSED_REALTIME
หาก ทำได้ เราจะอธิบายประเภทการปลุกต่างๆ โดยละเอียดในส่วนต่อไปนี้