AlarmManager
) ช่วยให้คุณดำเนินการตามเวลาได้นอกช่วงอายุการใช้งานของแอปพลิเคชัน
เช่น คุณสามารถใช้การปลุกเพื่อเริ่มการดำเนินการที่ใช้เวลานาน เช่น การเริ่มบริการวันละครั้งเพื่อดาวน์โหลดพยากรณ์อากาศ
โดยการปลุกจะมีลักษณะดังนี้
ซึ่งช่วยให้คุณเรียกใช้ Intent ในเวลาและ/หรือช่วงเวลาที่กำหนดได้
คุณสามารถใช้ร่วมกับ BroadcastReceiver เพื่อกำหนดเวลางานหรือ WorkRequest เพื่อดำเนินการอื่นๆ ได้
โดยจะทำงานภายนอกแอปพลิเคชันของคุณ คุณจึงใช้เพื่อทริกเกอร์เหตุการณ์หรือการดำเนินการได้แม้ว่าแอปจะไม่ได้ทำงานอยู่ หรือแม้ว่าอุปกรณ์จะเข้าสู่โหมดสลีปก็ตาม
ซึ่งจะช่วยให้คุณลดข้อกำหนดด้านทรัพยากรของแอปได้ คุณสามารถกำหนดเวลา การดำเนินการได้โดยไม่ต้องอาศัยตัวจับเวลาหรือบริการที่ทำงานอย่างต่อเนื่อง
ตั้งปลุกแบบไม่ตรงเวลา
เมื่อแอปตั้งการปลุกที่ไม่แน่นอน ระบบจะส่งการปลุกในเวลาใดเวลาหนึ่ง ในอนาคต การปลุกที่ไม่แน่นอนจะรับประกันเวลาในการส่งการปลุกบางอย่าง ขณะเดียวกันก็ปฏิบัติตามข้อจำกัดในการประหยัดแบตเตอรี่ เช่น โหมดพักเครื่อง
นักพัฒนาแอปสามารถใช้ประโยชน์จากการรับประกัน 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
หาก ทำได้ เราจะอธิบายประเภทการปลุกต่างๆ โดยละเอียดในส่วนต่อไปนี้