WakeLock เป็นกลไกของ Android ที่ป้องกันไม่ให้อุปกรณ์เข้าสู่โหมดสลับ โดยการรักษา CPU หรือหน้าจอให้ทำงานอยู่ งานเบื้องหลัง เช่น การดาวน์โหลดไฟล์ การเล่นเสียง หรือการบันทึกข้อมูล จำเป็นต้องใช้ WakeLock เพื่อให้การทำงานสำเร็จอย่างต่อเนื่องโดยไม่ถูกรบกวน ตามข้อกำหนดของ Android Developers, 2025 การใช้ WakeLock อย่างไม่เหมาะสมจะทำให้แบตเตอรี่หมดเร็วและอาจทำให้แอปถูกบล็อกใน Google Play
ประเด็นสำคัญ
WakeLock คือล็อกระบบที่ป้องกันไม่ให้ Android วางอุปกรณ์ในโหมดพลังงานต่ำ โดยปกติหลังจากผู้ใช้ไม่มีการเคลื่อนไหวไม่กี่วินาที Android จะปิดหน้าจอและทำให้ CPU เข้าสู่สถานะหลับลึก (deep sleep) ระงับเธรดเบื้องหลัง WakeLock ป้องกันการเปลี่ยนแปลงนี้โดยการรักษา CPU ให้ทำงานอยู่
กลไก WakeLock ถูกจัดการผ่านบริการระบบ PowerManager ซึ่งเข้าถึงได้ผ่านเมธอด getSystemService(Context.POWER_SERVICE) นักพัฒนาจะสร้างออบเจ็กต์ WakeLock ระบุประเภทของล็อก และต้องปล่อยมันหลังจากงานเสร็จสิ้น มิฉะนั้นแบตเตอรี่ของอุปกรณ์จะหมดอย่างรวดเร็ว ระบบไม่ปล่อย WakeLock โดยอัตโนมัติ — นั่นคือความรับผิดชอบของแอป
ทุกครั้งที่ Android ออกรุ่นหลัก Google จะเพิ่มการควบคุม WakeLock ให้เข้มงวดขึ้น เริ่มตั้งแต่ Android 9 (API 28) แอปในเบื้องหลังไม่สามารถรับ WakeLock โดยไม่มีเหตุผลที่ถูกต้อง และระบบจะติดตามแอปที่ใช้ล็อกในทางที่ผิดและสามารถปล่อยพวกมันแบบบังคับได้ ใน Android 12+ มีการนำข้อจำกัดเพิ่มเติมในการเข้าถึง PowerManager สำหรับแอปเบื้องหลัง
WakeLock จำเป็นในสถานการณ์ที่งานไม่สามารถถูกขัดจังหวะโดยอุปกรณ์เข้าสู่โหมดหลับ: การดาวน์โหลดไฟล์ขนาดใหญ่ผ่านการเชื่อมต่อที่ไม่เสถียร การบันทึกวิดีโอ การคำนวณยาวโดยไม่มีการโต้ตอบของผู้ใช้ หากไม่มีล็อกการนอนหลับ CPU จะเข้าสู่โหมดหลับลึก เธรดทั้งหมดจะถูกหยุดชะงัก และงานจะไม่สมบูรณ์
อย่างไรก็ตาม Google แนะนำอย่างยิ่งให้ลดการใช้ WakeLock ในกรณีส่วนใหญ่ งานเดียวกันสามารถแก้ไขได้ด้วย Foreground Service พร้อมการแจ้งเตือน WorkManager หรือ JobScheduler กลไกเหล่านี้พิจารณาสถานะแบตเตอรี่และเครือข่าย ซึ่งช่วยยืดอายุแบตเตอรี่ของอุปกรณ์
WakeLock ทำงานผ่านบริการระบบ PowerManager ซึ่งจัดการสถานะพลังงานของอุปกรณ์ เมื่อแอปร้องขอการล็อกผ่าน powerManager.newWakeLock() ระบบจะเพิ่มระดับกิจกรรมของ CPU ป้องกันการหลับลึก หลังจากเรียก wakeLock.release() ระบบจะกลับสู่โหมดประหยัดพลังงานปกติ
สิ่งสำคัญคือต้องเข้าใจว่า WakeLock ไม่ได้ป้องกันโหมดประหยัดพลังงานทั้งหมด โหมด Doze (โหมดสลับของ Android 6+) อาจไม่สนใจ WakeLock ในบางช่วง — แอปที่ถือ WakeLock จะไม่ได้รับการเข้าถึงเครือข่ายระหว่างหน้าต่างการบำรุงรักษาของ Doze ซึ่งหมายความว่าแม้ WakeLock ที่ทำงานอยู่ก็ไม่รับประกันการดำเนินการเครือข่ายในช่วงที่สองของ Doze
แต่ละ WakeLock เชื่อมโยงกับ PowerManager.WakeLock ฝั่ง framework ระบบจะนับล็อกที่ทำงานอยู่ที่ระดับกระบวนการ: หากกระบวนการหนึ่งถือ WakeLock หลายตัว พวกมันจะสะสมและการปล่อยจะเกิดขึ้นหลังจากเรียก release() สำหรับแต่ละล็อกเท่านั้น Android ยังรองรับ การหมดเวลาของเวกล็อก — การปล่อยอัตโนมัติหลังจากช่วงเวลาที่กำหนด อย่างไรก็ตาม ไม่แนะนำให้พึ่งพาการหมดเวลา: งานอาจเสร็จก่อนเวลาและระยะเวลาในการถือที่เพิ่มขึ้นจะลดอายุแบตเตอรี่
เมื่ออุปกรณ์เข้าสู่โหมดสลับ (ปุ่มเปิด/ปิด) Android จะปล่อย SCREEN_DIM_WAKE_LOCK และ SCREEN_BRIGHT_WAKE_LOCK ทั้งหมดแบบบังคับ แต่คง PARTIAL_WAKE_LOCK ไว้ ซึ่งหมายความว่าล็อกหน้าจอไม่สามารถรักษาจอแสดงผลให้เปิดอยู่ได้ — มีเพียง PARTIAL_WAKE_LOCK เท่านั้นที่สามารถทำงานต่อหลังจากกดปุ่มเปิด/ปิด
Android มี WakeLock หลายประเภท แต่ละประเภทควบคุมส่วนประกอบเฉพาะของอุปกรณ์ การเลือกประเภทจะกำหนดว่าส่วนประกอบฮาร์ดแวร์ใดยังคงทำงานอยู่หลังจากการล็อก การเลือกประเภทผิดจะนำไปสู่การใช้พลังงานมากเกินไปเนื่องจากการรักษาโมดูลที่ไม่จำเป็นให้ทำงานอยู่
| ประเภท | CPU | หน้าจอ | แป้นพิมพ์ | เมื่อใดควรใช้ |
|---|---|---|---|---|
| PARTIAL_WAKE_LOCK | เปิด | ปิด | ปิด | ดาวน์โหลดไฟล์, การคำนวณ |
| SCREEN_DIM_WAKE_LOCK | เปิด | สลัว | ปิด | เครื่องเล่นวิดีโอ, การนำเสนอ |
| SCREEN_BRIGHT_WAKE_LOCK | เปิด | สว่าง | ปิด | เกม (เลิกใช้แล้ว) |
| FULL_WAKE_LOCK | เปิด | สว่าง | สว่าง | เลิกใช้แล้ว (deprecated) |
PARTIAL_WAKE_LOCK เป็นประเภทที่ใช้บ่อยที่สุดและแนะนำ มันทำให้ CPU ทำงานอยู่แต่ยอมให้หน้าจอและไฟแบ็คไลท์ของแป้นพิมพ์ปิดได้ นี่เป็นตัวเลือกที่เหมาะสมที่สุดสำหรับงานเบื้องหลัง: การโหลดข้อมูล, การประมวลผลภาพ, การซิงโครไนซ์ หน้าจอจะปิดหลังจากหมดเวลาของระบบ ช่วยประหยัดแบตเตอรี่ในขณะที่ทำงานที่ผู้ใช้มองไม่เห็น
SCREEN_DIM_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK และ FULL_WAKE_LOCK ถูกทำเครื่องหมายว่าเลิกใช้แล้วตั้งแต่ Android 7 (API 24) มันทำให้หน้าจอเปิดอยู่ ซึ่งทำให้แบตเตอรี่หมดมาก Google แนะนำให้ใช้ FLAG_KEEP_SCREEN_ON ผ่าน Activity.getWindow().addFlags() แทน — แฟล็กนี้ทำงานเฉพาะเมื่อ Activity ทำงานอยู่และไม่ต้องการสิทธิ์ WAKE_LOCK ในขณะที่ระบบจัดการระยะเวลาในการเปิดหน้าจอโดยอัตโนมัติ
WakeLock เป็นหนึ่งในปัจจัยหลักที่ทำให้แบตเตอรี่หมดบน Android ทุกวินาทีที่ถือล็อกการนอนหลับใช้พลังงานเพิ่มเติมเนื่องจาก CPU ไม่สามารถเปลี่ยนไปยังสถานะ C ที่ประหยัดพลังงานได้ การวิจัยของ Google Power Dashboard แสดงให้เห็นว่าแอปที่ปล่อย WakeLock อย่างไม่เหมาะสมสามารถเพิ่มการใช้พลังงานของอุปกรณ์ได้ 30–50% ในโหมดสแตนด์บาย
ระบบติดตามแอปที่ใช้ WakeLock ในทางที่ผิดผ่านส่วนประกอบ Battery Historian นักพัฒนาสามารถวิเคราะห์โปรไฟล์การใช้พลังงานและระบุการรั่วไหลของล็อก — สถานการณ์ที่สร้าง WakeLock แต่ไม่ได้ปล่อย Google Play Console แสดงสถิติ WakeLock สำหรับแอปที่เผยแพร่ และเวลาในการถือที่สูงอาจนำไปสู่รีวิวที่ไม่ดี
โหมด Doze และ App Standby จำกัดการทำงานของ WakeLock เพิ่มเติม ในช่วงแรกของ Doze (Light Doze) ระบบอนุญาตให้ WakeLock ในหน้าต่างการบำรุงรักษาสั้น ๆ ในช่วงที่สอง (Deep Doze) WakeLock จะถูกรวมกับล็อกอื่นและทำงานในหน้าต่างร่วม หากแอปถือ WakeLock นานกว่า 10 นาทีโดยไม่มีการโต้ตอบจากผู้ใช้ ระบบอาจปล่อยมันแบบบังคับและเพิ่มแอปลงใน บัญชีดำ การปรับแต่งแบตเตอรี่
การใช้ WakeLock อย่างถูกต้องคือความสมดุลระหว่างความจำเป็นในการทำงานให้เสร็จและการดูแลแบตเตอรี่ของอุปกรณ์ Google แนะนำให้ปฏิบัติตามหลักการหลายประการ: ปล่อย WakeLock ในบล็อก finally หรือผ่าน acquire(timeout) เสมอ ใช้ประเภทล็อกที่จำเป็นน้อยที่สุด และหลีกเลี่ยงการถือเป็นเวลานานหากไม่จำเป็นจริง ๆ
WakeLock ควรถูกปล่อยในบล็อกโค้ดเดียวกับที่สร้างขึ้น เพื่อรับประกันการปล่อยเมื่อมีข้อยกเว้น ใช้โครงสร้าง try-finally หรือบล็อก use ของ Kotlin บน Android 10+ ระบบจะแสดงคำเตือนใน logcat หาก WakeLock ถูกถือเกิน 60 วินาที: "WakeLock held for more than 60 seconds" — นี่คือสัญญาณของการรั่วไหลที่อาจเกิดขึ้น
เมธอด acquire(long timeout) จะปล่อย WakeLock โดยอัตโนมัติหลังจากเวลาที่กำหนดในหน่วยมิลลิวินาที นี่คือการป้องกันในกรณีที่โค้ดการปล่อยไม่ทำงานเนื่องจากข้อยกเว้นหรือบั๊ก ขอแนะนำให้ระบุการหมดเวลาเท่ากับเวลาการทำงานสูงสุดที่คาดหวังของงานบวกส่วนเผื่อ 10–20%
ก่อนเรียก release() ควรตรวจสอบว่า WakeLock ถูกถืออยู่ในขณะนี้หรือไม่ การเรียก release() อีกครั้งโดยไม่มีการ acquire() ก่อนจะทำให้เกิด RuntimeException: WakeLock under-locked ขอแนะนำให้เก็บแฟล็กสถานะ (isHeld) และตรวจสอบ wakeLock.isHeld() ก่อนปล่อย
มาดูการสร้างและปล่อย WakeLock ใน Kotlin อย่างถูกต้อง ตัวอย่างสาธิตการโหลดข้อมูลแบบอะซิงโครนัสโดยถือ PARTIAL_WAKE_LOCK การปล่อยที่รับประกันในบล็อก try-finally และการหมดเวลาที่ระบุเพื่อป้องกันการรั่วไหล บริการนี้ใช้ CoroutineScope กับตัวจัดสรร IO สำหรับการทำงานเบื้องหลัง
class DownloadService : Service() {
private lateinit var wakeLock: PowerManager.WakeLock
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
override fun onCreate() {
super.onCreate()
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"download:wakelock"
)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
wakeLock.acquire(60000)
scope.launch {
try {
downloadFile()
} finally {
if (wakeLock.isHeld()) {
wakeLock.release()
}
}
}
return START_NOT_STICKY
}
private suspend fun downloadFile() {
// การจำลองการดาวน์โหลดไฟล์
delay(30000)
}
override fun onDestroy() {
super.onDestroy()
scope.cancel()
if (wakeLock.isHeld()) {
wakeLock.release()
}
}
override fun onBind(intent: Intent): IBinder? = null
}
ในการใช้ WakeLock ต้องเพิ่มสิทธิ์ใน AndroidManifest.xml สิทธิ์ WAKE_LOCK เป็นสิทธิ์ปกติ — ไม่ต้องขอจากผู้ใช้ขณะรันไทม์และจะได้รับโดยอัตโนมัติเมื่อติดตั้งแอป อย่างไรก็ตาม Google Play อาจปฏิเสธการเผยแพร่หากแอปไม่มีกรณีการใช้งานที่ชัดเจนสำหรับ WakeLock
<uses-permission
android:name="android.permission.WAKE_LOCK" />
<uses-permission
android:name="android.permission.DEVICE_POWER" />
WakeLock เป็นกลไกระดับต่ำ และ Google แนะนำให้แทนที่ด้วย API ที่ทันสมัยกว่าเมื่อเป็นไปได้ ทางเลือกหลักคือ Foreground Service ที่มีการแจ้งเตือน ซึ่งจะถือล็อก CPU โดยอัตโนมัติตลอดระยะเวลาของบริการ ระบบจัดการ WakeLock สำหรับ Foreground Service เอง ทำให้นักพัฒนาไม่ต้องรับและปล่อยอย่างชัดเจน
WorkManager เป็นเครื่องมือที่สำคัญอันดับสองสำหรับงานเบื้องหลัง มันรับประกันการทำงานแม้เมื่ออุปกรณ์เข้าสู่โหมด Doze และหลังจากรีบูต WorkManager รองรับ การถือล็อก (hold lock) ภายใน — นักพัฒนาไม่ต้องทำงานกับ PowerManager อย่างชัดเจน งานจะทำงานในหน้าต่างการบำรุงรักษาของ Doze ด้วยการจัดการล็อกการนอนหลับอัตโนมัติ
สำหรับงานที่เกิดซ้ำซึ่งต้องการเวลาที่แม่นยำ ใช้ AlarmManager กับ setAndAllowWhileIdle() ซึ่งสามารถปลุกอุปกรณ์จาก Doze ได้ อย่างไรก็ตาม AlarmManager เหมาะสำหรับการดำเนินการสั้นเท่านั้น — มันไม่ได้ออกแบบมาสำหรับการถือ WakeLock เป็นเวลานาน หากงานใช้เวลานานกว่า 10 วินาที ให้รวม AlarmManager กับ BroadcastReceiver ที่เริ่ม Foreground Service
คำถามที่พบบ่อย
WakeLock คือล็อกระบบที่ป้องกันอุปกรณ์ Android เข้าสู่โหมดสลับ มันรักษา CPU หรือหน้าจอให้ทำงานอยู่ ช่วยให้งานเบื้องหลัง (ดาวน์โหลด, คำนวณ) ทำงานได้อย่างต่อเนื่อง มันถูกจัดการผ่านบริการระบบ PowerManager
ประเภทหลักคือ: PARTIAL_WAKE_LOCK (CPU ทำงาน, หน้าจอปิด) — แนะนำ; SCREEN_DIM_WAKE_LOCK (CPU + หน้าจอสลัว); SCREEN_BRIGHT_WAKE_LOCK (CPU + หน้าจอสว่าง) SCREEN_DIM, SCREEN_BRIGHT และ FULL_WAKE_LOCK เลิกใช้แล้วและถูกแทนที่ด้วย FLAG_KEEP_SCREEN_ON
ใช่ ต้องประกาศ android.permission.WAKE_LOCK ใน manifest นี่คือสิทธิ์ปกติที่ได้รับโดยอัตโนมัติเมื่อติดตั้ง — ไม่ต้องขอขณะรันไทม์ หากไม่มีสิทธิ์นี้ การเรียก newWakeLock() จะคืนค่า null หรือโยน SecurityException
หากไม่เรียก release() อุปกรณ์จะไม่สามารถเข้าสู่โหมดสลับได้ แบตเตอรี่ จะหมดเร็วกว่ามาก (มากถึง 50% การใช้เพิ่มเติม) ระบบจะบันทึกการรั่วไหลใน logcat และ Battery Historian จะแสดงเวลาในการถือ WakeLock ที่ผิดปกติ ซึ่งนำไปสู่รีวิวที่ไม่ดีจากผู้ใช้
สำหรับงานที่ยาวนาน ใช้ Foreground Service พร้อมการแจ้งเตือน — ระบบจัดการ WakeLock เอง สำหรับงานที่เลื่อนออกไปและรับประกัน ใช้ WorkManager ซึ่งรองรับ WakeLock ภายใน สำหรับงานสั้นตามกำหนดการ ใช้ AlarmManager
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ