AlarmManager
) ช่วยให้คุณดำเนินการตามเวลานอกอายุการใช้งานของแอปพลิเคชันได้
ตัวอย่างเช่น คุณสามารถใช้การปลุกเพื่อเริ่มการดำเนินการที่ยาวนาน เช่น
เป็นการเริ่มบริการวันละครั้งเพื่อดาวน์โหลดพยากรณ์อากาศ
การปลุกมีลักษณะดังต่อไปนี้
ซึ่งช่วยให้คุณเรียกใช้ Intent ในเวลาและ/หรือช่วงเวลาที่กำหนด
คุณสามารถใช้ Chromecast ร่วมกับ Broadcast Receiver เพื่อกำหนดเวลา jobs หรือ WorkRequests เพื่อดำเนินการอื่นๆ การดำเนินงาน
เหตุการณ์ทำงานนอกแอปพลิเคชัน คุณจึงใช้เหตุการณ์เพื่อทริกเกอร์เหตุการณ์หรือการดําเนินการได้แม้ว่าแอปจะไม่ทํางานอยู่และอุปกรณ์จะอยู่ในโหมดสลีปก็ตาม
ซึ่งช่วยลดความต้องการทรัพยากรของแอปให้เหลือน้อยที่สุด คุณจะกำหนดเวลาได้ โดยไม่ต้องอาศัยตัวจับเวลาหรือบริการที่กำลังทำงานอย่างต่อเนื่อง
ตั้งปลุกแบบไม่แน่นอน
เมื่อแอปตั้งการปลุกที่ไม่แม่นยำ ระบบจะส่งการปลุกในเวลาใดเวลาหนึ่ง ในอนาคต การปลุกที่ไม่แน่นอนจะรับประกันบางอย่างเกี่ยวกับเวลาในการส่งการปลุก ขณะเดียวกันก็เคารพข้อจำกัดในการประหยัดแบตเตอรี่ เช่น โหมดสลีป
นักพัฒนาแอปสามารถใช้ประโยชน์จากการรับประกัน API ต่อไปนี้เพื่อปรับแต่งช่วงเวลาของ การส่งการแจ้งเตือนที่ไม่แม่นยำ
ส่งการปลุกหลังเวลาที่กำหนด
หากแอปเรียกใช้ set()
setInexactRepeating()
หรือ setAndAllowWhileIdle()
สัญญาณเตือนจะไม่ดังก่อนเวลาทริกเกอร์ที่ระบุ
ใน Android 12 (API ระดับ 31) ขึ้นไป ระบบจะเรียกใช้การปลุกภายใน 1 ชั่วโมงของเวลาทริกเกอร์ที่ระบุ ยกเว้นว่าจะมีข้อจำกัดในการประหยัดแบตเตอรี่ เช่น โหมดประหยัดแบตเตอรี่ หรือ Doze
ส่งการแจ้งเตือนในช่วงเวลาหนึ่ง
หากแอปโทรหา setWindow()
การปลุกจะไม่ส่งเสียงก่อนที่จะให้สัญญาณ
เวลาในการทริกเกอร์ การปลุกจะเป็น เว้นแต่มีข้อจำกัดในการประหยัดแบตเตอรี่มีผลบังคับใช้
แสดงภายในกรอบเวลาที่ระบุ โดยเริ่มต้นจากทริกเกอร์ที่กำหนด
หากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป ระบบอาจหน่วงเวลา
การเรียกใช้การปลุกในเวลาที่แน่นอนที่มีกรอบเวลานานอย่างน้อย 10 นาที ด้วยเหตุนี้ ค่าพารามิเตอร์ windowLengthMillis
ที่อยู่ต่ำกว่า 600000
จึงถูกตัดให้เหลือ 600000
ตั้งปลุกซ้ำในช่วงเวลาที่สม่ำเสมอโดยประมาณ
หากแอปเรียกใช้ setInexactRepeating()
ระบบจะเรียกใช้การแจ้งเตือนหลายรายการ ดังนี้
- การปลุกครั้งแรกจะดังภายในกรอบเวลาที่ระบุ โดยเริ่มตั้งแต่ เวลาทริกเกอร์ที่กำหนด
- การปลุกครั้งต่อๆ ไปมักจะส่งเสียงเตือนหลังจากกรอบเวลาที่ระบุไว้ ผ่านไปแล้ว เวลาระหว่างการเรียกใช้การปลุกติดต่อกัน 2 ครั้งอาจแตกต่างกัน
ตั้งปลุกในเวลาที่แน่นอน
ระบบจะเรียกใช้การปลุกที่แน่นอนในเวลาที่แน่นอนในอนาคต
แอปส่วนใหญ่กำหนดเวลางานและกิจกรรมโดยใช้การปลุกที่ไม่เหมือนกันเพื่อ กรอก Use Case ทั่วไปหลายๆ รายการ หากฟังก์ชันหลักของแอปขึ้นอยู่กับการปลุกที่มีเวลาแน่นอน เช่น สําหรับแอปนาฬิกาปลุกหรือแอปปฏิทิน คุณก็ใช้การปลุกในเวลาที่แน่นอนแทนได้
กรณีการใช้งานที่อาจไม่จําเป็นต้องใช้การปลุกในเวลาที่แน่นอน
รายการต่อไปนี้แสดงเวิร์กโฟลว์ทั่วไปที่อาจไม่ต้องการการปลุกในเวลาที่แน่นอน
- การกำหนดเวลาการดำเนินการตามช่วงเวลาตลอดอายุของแอป
- ชั้นเรียน
Handler
มีหลายเนื้อหา ในการจัดการการดำเนินงานด้านเวลา เช่น ทำงานบางอย่าง n วินาที ขณะที่แอปทำงานอยู่postAtTime()
และpostDelayed()
โปรดทราบว่า API เหล่านี้ใช้เวลาทำงานของระบบ ไม่ใช่แบบเรียลไทม์ - งานพื้นหลังที่กำหนดเวลาไว้ เช่น การอัปเดตแอปและการอัปโหลดบันทึก
WorkManager
มอบวิธีกำหนดเวลาสำหรับช่วงเวลาที่มีความละเอียดอ่อน ที่ทำงาน คุณสามารถระบุช่วงเวลาที่ทำงานซ้ำและflexInterval
(ขั้นต่ำ 15 นาที) เพื่อกำหนดรันไทม์แบบละเอียดสำหรับงาน- การดําเนินการที่ผู้ใช้ระบุซึ่งควรเกิดขึ้นหลังจากเวลาหนึ่งๆ (แม้ว่าระบบจะอยู่ในสถานะไม่มีการใช้งานก็ตาม)
- ใช้การปลุกที่ไม่แน่นอน กล่าวอย่างเจาะจงคือ
setAndAllowWhileIdle()
- การดําเนินการที่ผู้ใช้ระบุซึ่งควรเกิดขึ้นหลังจากเวลาหนึ่งๆ
- ใช้การปลุกในเวลาที่ไม่แน่นอน กล่าวอย่างเจาะจงคือ
set()
- การดําเนินการที่ผู้ใช้ระบุซึ่งอาจเกิดขึ้นภายในกรอบเวลาที่ระบุ
- ใช้การปลุกที่ไม่แน่นอน กล่าวอย่างเจาะจงคือ
setWindow()
โปรดทราบว่าหากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป ระยะเวลาของกรอบเวลาต่ำสุดที่อนุญาตคือ 10 นาที
วิธีตั้งปลุกในเวลาที่แน่นอน
แอปของคุณตั้งปลุกในเวลาที่แน่นอนได้โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้ วิธีการเหล่านี้ ถูกเรียงลำดับเพื่อให้รายการที่อยู่ใกล้ด้านล่างสุดแสดงรายการมากกว่า งานที่ต้องแข่งกับเวลา ต้องใช้ทรัพยากรระบบมากขึ้น
setExact()
เปิดการปลุกในเวลาที่เกือบจะแน่นอนในอนาคต ตราบใดที่มาตรการอื่นๆ ในการประหยัดแบตเตอรี่ไม่ได้มีผล
ใช้วิธีนี้เพื่อตั้งปลุกในเวลาที่แน่นอน เว้นแต่แอปจะทำงาน ในช่วงเวลาสำคัญสำหรับผู้ใช้
setExactAndAllowWhileIdle()
เปิดการปลุกในเวลาที่เกือบจะแน่นอนในอนาคต แม้ว่าจะมีมาตรการประหยัดแบตเตอรี่อยู่ก็ตาม
setAlarmClock()
เรียกใช้การปลุกในเวลาที่แน่นอนในอนาคต เพราะการตั้งปลุกเหล่านี้ ระบบจึงไม่เคยปรับเวลานำส่งผู้ใช้จะเห็นได้อย่างชัดเจน ระบบระบุว่าสัญญาณเตือนเหล่านี้เป็นการปลุกที่สำคัญที่สุดและใช้พลังงานต่ำ โหมดนี้หากจำเป็นต่อการส่งการแจ้งเตือน
การใช้ทรัพยากรระบบ
เมื่อระบบเรียกใช้การปลุกในเวลาที่แน่นอนที่แอปของคุณตั้งไว้ อุปกรณ์ ใช้ทรัพยากรอย่างมาก เช่น อายุการใช้งานแบตเตอรี่ โดยเฉพาะหากอุปกรณ์อยู่ใน โหมดประหยัดพลังงาน นอกจากนี้ ระบบไม่สามารถจัดกลุ่มคำขอเหล่านี้ เพื่อให้ใช้ทรัพยากรได้อย่างมีประสิทธิภาพมากขึ้น
เราขอแนะนําอย่างยิ่งให้คุณสร้างการแจ้งเตือนที่ไม่แน่นอนทุกครั้งที่เป็นไปได้ หากต้องการทำงานเป็นเวลานานขึ้น ให้กำหนดเวลาโดยใช้ WorkManager
หรือ JobScheduler
จาก BroadcastReceiver
ของนาฬิกาปลุก ทำงานในขณะที่
อุปกรณ์อยู่ใน Doze สร้างการปลุกที่ไม่แน่นอนโดยใช้
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
เช่น
setExact
API ไม่จําเป็นต้องใช้สิทธิ์ SCHEDULE_EXACT_ALARM
การใช้สิทธิ์ SCHEDULE_EXACT_ALARM
สิทธิ์ SCHEDULE_EXACT_ALARM
ต้องได้รับอนุญาตจากผู้ใช้ ซึ่งแตกต่างจาก USE_EXACT_ALARM
ทั้งผู้ใช้และระบบสามารถเพิกถอนสิทธิ์ SCHEDULE_EXACT_ALARM
ได้
หากต้องการตรวจสอบว่ามีการให้สิทธิ์แก่แอปของคุณหรือไม่ ให้โทร
canScheduleExactAlarms()
ก่อนพยายามตั้งปลุก เมื่อสิทธิ์SCHEDULE_EXACT_ALARM
ถูกเพิกถอนสำหรับแอปของคุณ แอปของคุณจะหยุดทำงาน และการปลุกในเวลาที่แน่นอนทั้งหมดในอนาคต
ถูกยกเลิก ซึ่งหมายความว่าค่าที่ canScheduleExactAlarms()
แสดงผลจะยังคงใช้งานได้ตลอดอายุของแอป
เมื่อให้สิทธิ์ SCHEDULE_EXACT_ALARMS
แก่แอปของคุณ
ระบบจะส่ง
ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
ออกอากาศ แอปของคุณควรใช้การออกอากาศ
รีซีฟเวอร์ที่ทำหน้าที่
ดังต่อไปนี้:
- ยืนยันว่าแอปของคุณยังมีสิทธิ์เข้าถึงแอปพิเศษ โดยโทร
canScheduleExactAlarms()
การตรวจสอบนี้จะปกป้องแอปของคุณจากกรณีที่ผู้ใช้ให้สิทธิ์แอปของคุณ แล้วก็เพิกถอนสิทธิ์นั้นหลังจากนั้นเกือบจะทันที - ตั้งเวลาการปลุกในเวลาที่แน่นอนที่แอปของคุณต้องใช้ใหม่โดยอิงตามสถานะปัจจุบันของแอป
ตรรกะนี้ควรคล้ายกับสิ่งที่แอปทำเมื่อได้รับการออกอากาศ
ACTION_BOOT_COMPLETED
ขอให้ผู้ใช้ให้สิทธิ์ SCHEDULE_EXACT_ALARM
หากจำเป็น คุณสามารถส่งผู้ใช้ไปที่การปลุกและ หน้าจอการช่วยเตือนในระบบ การตั้งค่า ดังที่แสดงในรูปที่ 1 โดยทำตามขั้นตอนต่อไปนี้
- ใน UI ของแอป ให้อธิบายให้ผู้ใช้ทราบว่าเหตุใดแอปจึงต้องตั้งเวลาการปลุกให้ตรงเวลา
- เรียกใช้ Intent ที่มีการดำเนินการของ Intent
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
ตั้งปลุกซ้ำ
การปลุกซ้ำช่วยให้ระบบแจ้งเตือนแอปของคุณตามกำหนดการที่เกิดซ้ำได้
การปลุกที่ออกแบบมาไม่ดีอาจทำให้แบตเตอรี่หมดเร็วและทำให้อุปกรณ์ทำงานหนักเกินไป เซิร์ฟเวอร์ ด้วยเหตุนี้ ใน Android 4.4 (API ระดับ 19) ขึ้นไปทั้งหมด การปลุกซ้ำเป็นการปลุกที่ไม่แน่นอน
การปลุกซ้ำมีลักษณะดังต่อไปนี้
ประเภทการปลุก ดูการพูดคุยเพิ่มเติมที่หัวข้อเลือกประเภทการปลุก
เวลาทริกเกอร์ หากเวลาทริกเกอร์ที่คุณระบุเป็นอดีต ระบบจะทริกเกอร์การปลุกทันที
ช่วงเวลาการปลุก เช่น วันละครั้ง ทุกชั่วโมง หรือทุก 5 นาที
Intent ที่รอดำเนินการซึ่งจะเริ่มทำงานเมื่อระบบทริกเกอร์การปลุก เมื่อคุณตั้งค่า การปลุกครั้งที่ 2 ที่ใช้ Intent ที่รอดำเนินการเดียวกัน การปลุกนี้จะแทนที่การปลุกเดิม
หากต้องการยกเลิก 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 ของอุปกรณ์ตื่นขึ้นหากหน้าจอปิดอยู่ เพื่อให้มั่นใจว่าการปลุกจะทำงานตามเวลาที่กำหนด วิธีนี้มีประโยชน์หากแอปของคุณมีเวลาเป็นปัจจัย เช่น หากมี หน้าต่างที่จำกัดสำหรับการดำเนินการบางอย่าง หากคุณไม่ได้ใช้การปลุกประเภท "ปลุกให้ตื่น" การปลุกซ้ำทั้งหมดจะทำงานเมื่ออุปกรณ์ตื่นขึ้นมาครั้งถัดไป
หากคุณต้องการเพียงแค่ให้นาฬิกาปลุกเริ่มทำงานที่ช่วงเวลาใดเวลาหนึ่ง (ตัวอย่างเช่น ทุกครึ่งชั่วโมง) ให้ใช้ประเภทแบบเรียลไทม์ที่ผ่านไป โดยทั่วไป ค่านี้ เป็นทางเลือกที่ดีกว่า
หากคุณต้องการให้นาฬิกาปลุกเริ่มทำงานในเวลาใดเวลาหนึ่งของวัน ให้เลือกการปลุก ประเภทต่างๆ ของนาฬิกาแบบเรียลไทม์ อย่างไรก็ตาม โปรดทราบว่าวิธีการนี้มีข้อเสียบางประการ แอปอาจแปลเป็นภาษาท้องถิ่นอื่นๆ ได้ไม่สอดคล้องกัน และหากผู้ใช้เปลี่ยนการตั้งค่าเวลาของอุปกรณ์ ก็อาจทําให้แอปทำงานผิดปกติได้ นอกจากนี้ การใช้การปลุกแบบนาฬิกาเรียลไทม์ก็ไม่เหมาะกับการปรับขนาดเช่นกัน ตามที่อธิบายไว้ข้างต้น เราขอแนะนำให้คุณใช้การปลุกแบบ "เวลาจริงที่ผ่านไป" หากทำได้
รายการประเภทมีดังนี้
ELAPSED_REALTIME
: เรียกใช้ Intent ที่รอดำเนินการตามระยะเวลานับตั้งแต่ที่อุปกรณ์บูต แต่จะไม่ปลุกอุปกรณ์ เวลาผ่านไปจะรวมเวลาที่อุปกรณ์อยู่ในโหมดสลีปด้วยELAPSED_REALTIME_WAKEUP
ปลุกอุปกรณ์และเริ่ม Intent ที่รอดำเนินการหลังจากระยะเวลาที่ระบุ ของเวลาผ่านไปนับตั้งแต่การบูตอุปกรณ์RTC
เริ่มการทำงานของ Intent ที่ค้างอยู่ในเวลาที่ระบุ แต่ไม่ปลุกระบบอุปกรณ์RTC_WAKEUP
: ตื่น ให้อุปกรณ์เริ่มการทำงานของ Intent ที่รอดำเนินการในเวลาที่กำหนด
ตัวอย่างการปลุกแบบเรียลไทม์ที่ผ่านไป
ต่อไปนี้คือตัวอย่างการใช้ 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);
ปลุกอุปกรณ์ให้ส่งเสียงปลุกตอน 8: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) รองรับโหมดDoze ซึ่งช่วยยืดอายุการใช้งานแบตเตอรี่ของอุปกรณ์ การปลุกจะไม่ทำงานเมื่ออุปกรณ์อยู่ในโหมดสลีป ระบบจะเลื่อนการปลุกที่ตั้งเวลาไว้จนกว่าอุปกรณ์จะออกจากโหมดสลีป หากคุณจำเป็นต้องทำดังนี้ สามารถทำงานได้อย่างสมบูรณ์ แม้ในขณะที่อุปกรณ์ไม่มีการใช้งาน มีหลายตัวเลือกดังนี้ ว่าง:
ใช้ WorkManager API ที่สร้างขึ้นเพื่อทำงาน งานที่ทำอยู่เบื้องหลัง คุณสามารถระบุว่าระบบควร เร่งการทำงานของคุณ เพื่อให้งานเสร็จโดยเร็วที่สุด สำหรับข้อมูลเพิ่มเติม โปรดดู กำหนดเวลางานด้วย WorkManager
แนวทางปฏิบัติแนะนำ
ตัวเลือกที่คุณเลือกในการออกแบบการปลุกซ้ำอาจมีผลต่อวิธีที่แอปใช้ (หรือละเมิด) ทรัพยากรระบบ ตัวอย่างเช่น สมมติว่าแอปยอดนิยมที่ซิงค์กับเซิร์ฟเวอร์ หากการดำเนินการซิงค์อ้างอิงตามนาฬิกา และทุกๆ อินสแตนซ์ของแอปจะซิงค์เวลา 23:00 น. ของการโหลด อาจทำให้ใช้เวลาในการตอบสนองนาน "ปฏิเสธการให้บริการ" ทำตามแนวทางปฏิบัติแนะนำต่อไปนี้ในการใช้การปลุก
เพิ่มการสุ่ม (Jitter) ลงในคําขอเครือข่าย ทริกเกอร์เนื่องจากการปลุกซ้ำ:
ทำงานเฉพาะที่เมื่อมีสัญญาณเตือน "งานในพื้นที่" หมายถึงอะไรก็ได้ ไม่มีการเข้าถึงเซิร์ฟเวอร์หรือต้องการข้อมูลจากเซิร์ฟเวอร์
และในขณะเดียวกัน ให้ตั้งเวลาปลุกที่มีคำขอจากเครือข่ายให้ ไฟที่ระยะเวลาแบบสุ่ม
รักษาความถี่ในการตั้งปลุกให้น้อยที่สุด
อย่าปลุกอุปกรณ์โดยไม่จำเป็น (ลักษณะการทำงานนี้ขึ้นอยู่กับประเภทการปลุกตามที่อธิบายไว้ในเลือกประเภทการปลุก)
อย่าตั้งค่าเวลาทริกเกอร์ของนาฬิกาปลุกให้แม่นยำเกินความจำเป็น
ใช้
setInexactRepeating()
instead ofsetRepeating()
เมื่อคุณใช้setInexactRepeating()
ระบบ Android จะซิงค์การปลุกซ้ำจากหลายแอปและเปิดการปลุกพร้อมกัน ซึ่งจะช่วยลดจำนวนครั้งที่ระบบต้องปลุกอุปกรณ์ จึงช่วยประหยัดแบตเตอรี่ ตั้งแต่ Android 4.4 (API ระดับ 19) เป็นต้นไป การปลุกซ้ำทั้งหมดจะเป็นการปลุกที่ไม่แน่นอน โปรดทราบว่าแม้ว่าsetInexactRepeating()
จะมีประสิทธิภาพดีกว่าsetRepeating()
แต่ก็ยังอาจทำให้เซิร์ฟเวอร์ทำงานหนักเกินไปได้หากอินสแตนซ์ทั้งหมดของแอปเข้าถึงเซิร์ฟเวอร์ในเวลาใกล้เคียงกัน ดังนั้น สําหรับคําขอเครือข่าย ให้เพิ่มความสุ่มให้กับการแจ้งเตือนดังที่ได้กล่าวไว้ก่อนหน้านี้หลีกเลี่ยงการตั้งปลุกตามเวลาของนาฬิกา หากเป็นไปได้
การปลุกซ้ำที่อิงตามเวลาทริกเกอร์ที่แน่นอนจะปรับขนาดได้ไม่ดี ใช้
ELAPSED_REALTIME
หากทำได้ การปลุกแบบอื่น ซึ่งอธิบายไว้ในรายละเอียดเพิ่มเติมในส่วนต่อไปนี้