ตั้งเวลาปลุก

การปลุก (อิงตามAlarmManager ) จะบอกให้คุณทราบถึงวิธีการ การดำเนินการที่อิงตามเวลานอกเหนือจากอายุการใช้งานของแอปพลิเคชัน ตัวอย่างเช่น คุณสามารถใช้การปลุกเพื่อเริ่มการดำเนินการที่ยาวนาน เช่น เป็นการเริ่มบริการวันละครั้งเพื่อดาวน์โหลดพยากรณ์อากาศ

การปลุกมีลักษณะดังต่อไปนี้

  • เมตริกเหล่านี้ให้คุณเริ่มการทำงานของ Intent ในเวลาที่กำหนดและ/หรือตามช่วงเวลา

  • คุณสามารถใช้ Chromecast ร่วมกับ Broadcast Receiver เพื่อกำหนดเวลา jobs หรือ WorkRequests เพื่อดำเนินการอื่นๆ การดำเนินงาน

  • โดยจะทำงานนอกแอปพลิเคชัน คุณจึงใช้เพื่อทริกเกอร์ได้ เหตุการณ์หรือการทำงานใดๆ แม้ในขณะที่แอปของคุณไม่ได้ทำงานอยู่ และแม้ว่าอุปกรณ์ หลับสบาย

  • ซึ่งช่วยลดความต้องการทรัพยากรของแอปให้เหลือน้อยที่สุด คุณจะกำหนดเวลาได้ โดยไม่ต้องอาศัยตัวจับเวลาหรือบริการที่กำลังทำงานอย่างต่อเนื่อง

ตั้งปลุกที่ไม่แน่นอน

เมื่อแอปตั้งการปลุกที่ไม่แม่นยำ ระบบจะส่งการปลุกในเวลาใดเวลาหนึ่ง ในอนาคต การปลุกในเวลาที่ไม่แน่นอนให้การรับประกันบางประการเกี่ยวกับช่วงเวลาของ ส่งสัญญาณเตือนโดยปฏิบัติตามข้อจำกัดการประหยัดแบตเตอรี่ เช่น Doze

นักพัฒนาแอปสามารถใช้ประโยชน์จากการรับประกัน API ต่อไปนี้เพื่อปรับแต่งช่วงเวลาของ การส่งการแจ้งเตือนที่ไม่แม่นยำ

ส่งการปลุกหลังเวลาที่กำหนด

หากแอปเรียกใช้ set() setInexactRepeating(), หรือ setAndAllowWhileIdle() สัญญาณเตือนจะไม่ดังก่อนเวลาทริกเกอร์ที่ระบุ

ใน Android 12 (API ระดับ 31) ขึ้นไป ระบบจะเรียกใช้การปลุกภายใน 1 ชั่วโมงของเวลาทริกเกอร์ที่ระบุ ยกเว้นว่าจะมีข้อจำกัดในการประหยัดแบตเตอรี่ เช่น โหมดประหยัดแบตเตอรี่ หรือ Doze

ส่งสัญญาณเตือนในกรอบเวลา

หากแอปโทรหา setWindow() การปลุกจะไม่ส่งเสียงก่อนที่จะให้สัญญาณ เวลาในการทริกเกอร์ การปลุกจะเป็น เว้นแต่มีข้อจำกัดในการประหยัดแบตเตอรี่มีผลบังคับใช้ แสดงภายในกรอบเวลาที่ระบุ โดยเริ่มต้นจากทริกเกอร์ที่กำหนด

หากแอปกำหนดเป้าหมายเป็น Android 12 ขึ้นไป ระบบอาจหน่วงเวลา การเรียกใช้การปลุกในเวลาที่แน่นอนที่มีกรอบเวลานานอย่างน้อย 10 นาที สำหรับ ด้วยเหตุนี้ ค่าพารามิเตอร์ windowLengthMillis ภายใต้ 600000 จึงถูกตัดเป็น 600000

ตั้งปลุกซ้ำในช่วงเวลาที่สม่ำเสมอโดยประมาณ

หากแอปเรียกใช้ setInexactRepeating() ระบบจะตั้งปลุกหลายรายการ:

  1. การปลุกครั้งแรกจะดังภายในกรอบเวลาที่ระบุ โดยเริ่มตั้งแต่ เวลาทริกเกอร์ที่กำหนด
  2. การปลุกครั้งต่อๆ ไปมักจะส่งเสียงเตือนหลังจากกรอบเวลาที่ระบุไว้ ผ่านไปแล้ว เวลาระหว่างการเรียกใช้การปลุกติดต่อกัน 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

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

สิ่งที่ต่างจาก USE_EXACT_ALARM คือสิทธิ์ SCHEDULE_EXACT_ALARM ต้องเป็น ที่ได้รับจากผู้ใช้ ทั้งผู้ใช้และระบบสามารถเพิกถอน สิทธิ์SCHEDULE_EXACT_ALARM

หากต้องการตรวจสอบว่ามีการให้สิทธิ์แก่แอปของคุณหรือไม่ ให้โทร canScheduleExactAlarms() ก่อนพยายามตั้งปลุก เมื่อสิทธิ์SCHEDULE_EXACT_ALARM ถูกเพิกถอนสำหรับแอปของคุณ แอปของคุณจะหยุดทำงาน และการปลุกในเวลาที่แน่นอนทั้งหมดในอนาคต ถูกยกเลิก และยังหมายความว่าค่าที่แสดงผลโดย canScheduleExactAlarms() จะยังคงมีผลตลอดวงจรของแอป

เมื่อให้สิทธิ์ SCHEDULE_EXACT_ALARMS แก่แอปของคุณ ระบบจะส่ง ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED ออกอากาศ แอปของคุณควรใช้การออกอากาศ รีซีฟเวอร์ที่ทำหน้าที่ ดังต่อไปนี้:

  1. ยืนยันว่าแอปของคุณยังคงมีสิทธิ์เข้าถึงพิเศษของแอป โดยโทร canScheduleExactAlarms() การตรวจสอบนี้จะปกป้องแอปของคุณจากกรณีที่ผู้ใช้ให้สิทธิ์แอปของคุณ แล้วก็เพิกถอนสิทธิ์นั้นหลังจากนั้นเกือบจะทันที
  2. ตั้งเวลาปลุกที่แน่นอนที่แอปต้องการใหม่ โดยอิงตามสถานะปัจจุบันของแอป ตรรกะนี้ควรคล้ายกับสิ่งที่แอปของคุณทำเมื่อได้รับ ACTION_BOOT_COMPLETED ออกอากาศ

ขอให้ผู้ใช้ให้สิทธิ์ SCHEDULE_EXACT_ALARM

วันที่ ตัวเลือกนี้มีชื่อว่า &quot;อนุญาตให้ตั้งปลุกและช่วยเตือน&quot;
รูปที่ 1 "นาฬิกาปลุกและ ช่วยเตือน" สิทธิ์เข้าถึงพิเศษของแอป ในการตั้งค่าระบบ ซึ่งผู้ใช้สามารถอนุญาตให้แอปตั้งค่า การตั้งปลุก

หากจำเป็น คุณสามารถส่งผู้ใช้ไปที่การปลุกและ หน้าจอการช่วยเตือนในระบบ การตั้งค่า ดังที่แสดงในรูปที่ 1 โดยทำตามขั้นตอนต่อไปนี้

  1. ใน UI ของแอป ให้อธิบายให้ผู้ใช้ทราบว่าทำไมแอปของคุณจึงต้องตั้งเวลา การปลุก
  2. เรียกใช้ Intent ที่มีเมธอด ACTION_REQUEST_SCHEDULE_EXACT_ALARM การดำเนินการผ่าน Intent

ตั้งปลุกซ้ำ

การปลุกซ้ำช่วยให้ระบบแจ้งเตือนแอปที่เกิดซ้ำ กำหนดการ

การปลุกที่ออกแบบมาไม่ดีอาจทำให้แบตเตอรี่หมดเร็วและทำให้อุปกรณ์ทำงานหนักเกินไป เซิร์ฟเวอร์ ด้วยเหตุนี้ ใน Android 4.4 (API ระดับ 19) ขึ้นไปทั้งหมด การปลุกซ้ำเป็นการปลุกที่ไม่แน่ชัด

การปลุกซ้ำมีลักษณะดังต่อไปนี้

  • ประเภทการปลุก สำหรับการสนทนาเพิ่มเติม โปรดดูที่เลือกประเภทการปลุก

  • เวลาทริกเกอร์ หากเวลาทริกเกอร์ที่คุณระบุเป็นเวลาที่ผ่านมาแล้ว ทริกเกอร์ทันที

  • ช่วงเวลาของการปลุก เช่น วันละครั้ง ทุกชั่วโมง หรือทุก 5 นาที

  • ความตั้งใจที่รอดำเนินการที่จะเริ่มทำงานเมื่อมีการเรียกให้ปลุก เมื่อคุณตั้งค่า การปลุกครั้งที่ 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 ครั้ง (แบบไม่ซ้ำ) ใน 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 จะ ที่จะทำงานต่อได้โดยที่ผู้ใช้ไม่ต้องเริ่มการปลุกอีกครั้งด้วยตนเอง

มีขั้นตอนดังนี้

  1. ตั้งค่าRECEIVE_BOOT_COMPLETED สิทธิ์ในไฟล์ Manifest ของแอปพลิเคชัน วิธีนี้ช่วยให้แอปของคุณได้รับ ACTION_BOOT_COMPLETED ที่จะออกอากาศหลังจากระบบบูตเสร็จสิ้น (วิธีนี้จะใช้ได้ต่อเมื่อ ได้เปิดให้บริการโดยผู้ใช้แล้วอย่างน้อย 1 ครั้ง) ดังนี้

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. ใช้ 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.
            }
        }
    }
    
  3. เพิ่มตัวรับสัญญาณลงในไฟล์ 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);
    

เรียกใช้การปลุกขณะที่อุปกรณ์อยู่ในโหมด Doze

อุปกรณ์ที่ใช้การสนับสนุน Android 6.0 (API ระดับ 23) Doze ช่วยยืดอายุการใช้งานแบตเตอรี่ของอุปกรณ์ การปลุกจะไม่ส่งเสียงเมื่ออุปกรณ์เปิดอยู่ โหมด Doze ระบบจะเลื่อนการปลุกที่กำหนดเวลาไว้จนกว่าอุปกรณ์จะออกจาก Doze หากคุณจำเป็นต้องทำดังนี้ สามารถทำงานได้อย่างสมบูรณ์ แม้ในขณะที่อุปกรณ์ไม่มีการใช้งาน มีหลายตัวเลือกดังนี้ ว่าง:

แนวทางปฏิบัติแนะนำ

ทุกตัวเลือกที่คุณเลือกในการออกแบบการปลุกซ้ำอาจส่งผลตามมา วิธีที่แอปของคุณใช้ (หรือละเมิด) ทรัพยากรระบบ ตัวอย่างเช่น สมมติว่า แอปยอดนิยมที่ซิงค์กับเซิร์ฟเวอร์ หากการดำเนินการซิงค์อ้างอิงตามนาฬิกา และทุกๆ อินสแตนซ์ของแอปจะซิงค์เวลา 23:00 น. ของการโหลด อาจทำให้ใช้เวลาในการตอบสนองนาน "ปฏิเสธการให้บริการ" ทำตามแนวทางปฏิบัติแนะนำต่อไปนี้ในการใช้การปลุก

  • เพิ่มการสุ่ม (Jitter) ลงในคําขอเครือข่าย ทริกเกอร์เนื่องจากการปลุกซ้ำ:

    • ทำงานเฉพาะที่เมื่อมีสัญญาณเตือน "งานในพื้นที่" หมายถึงอะไรก็ได้ ไม่มีการเข้าถึงเซิร์ฟเวอร์หรือต้องการข้อมูลจากเซิร์ฟเวอร์

    • และในขณะเดียวกัน ให้ตั้งเวลาปลุกที่มีคำขอจากเครือข่ายให้ ไฟที่ระยะเวลาแบบสุ่ม

  • รักษาความถี่ในการตั้งปลุกให้น้อยที่สุด

  • อย่าปลุกระบบอุปกรณ์โดยไม่จำเป็น (ลักษณะการทำงานนี้จะกำหนดโดย ประเภทการปลุก ตามที่อธิบายไว้ในเลือกประเภทการปลุก)

  • อย่าทำให้เวลาเรียกใช้การปลุกแม่นยำกว่าที่ควรจะเป็น

    ใช้ setInexactRepeating() แทนที่จะเป็น setRepeating() เมื่อคุณใช้ setInexactRepeating() Android ซิงค์ข้อมูลการปลุกซ้ำจากแอปหลายรายการและไฟไหม้ ได้ในเวลาเดียวกัน ซึ่งจะช่วยลดจำนวนครั้งทั้งหมดที่ระบบต้องปลุกระบบ อุปกรณ์จะช่วยลดการใช้แบตเตอรี่ สำหรับ Android 4.4 (API ระดับ 19) การปลุกซ้ำทั้งหมดเป็นการปลุกที่ไม่แน่นอน หมายเหตุ ขณะที่ setInexactRepeating() คือการปรับปรุงจาก setRepeating(), แอปก็ยังคงทำให้เซิร์ฟเวอร์ทำงานหนักหากอินสแตนซ์ของแอปหนึ่งๆ ไปถึงเซิร์ฟเวอร์ ในเวลาเดียวกัน ดังนั้น สำหรับคำขอเครือข่าย ให้เพิ่มการสุ่มลงใน ตามที่คุณพูดถึงก่อนหน้านี้

  • หลีกเลี่ยงการตั้งปลุกตามเวลาของนาฬิกาหากเป็นไปได้

    การปลุกซ้ำที่ยึดตามเวลาทริกเกอร์ที่แม่นยำจะปรับขนาดได้ไม่ดีนัก ใช้ ELAPSED_REALTIME หาก คุณสามารถทำได้ การปลุกแบบอื่น ซึ่งอธิบายไว้ในรายละเอียดเพิ่มเติมในส่วนต่อไปนี้