WakeLock مکانیزمی در اندروید است که از انتقال دستگاه به حالت خواب جلوگیری میکند و پردازنده یا صفحه نمایش را در حالت فعال نگه میدارد. وظایف پسزمینه مانند دانلود فایلها، پخش صدا یا ضبط دادهها برای اجرای تضمینی بدون وقفه به WakeLock نیاز دارند. طبق مشخصات Android Developers, 2025، استفاده نادرست از WakeLock منجر به تخلیه سریع باتری میشود و میتواند باعث مسدود شدن برنامه در Google Play شود.
نکات اصلی
WakeLock یک قفل سیستمی است که اندروید را از انتقال دستگاه به حالت مصرف انرژی پایین منع میکند. معمولاً اندروید پس از چند ثانیه عدم فعالیت کاربر، صفحه را خاموش کرده و پردازنده را به حالت خواب عمیق (deep sleep) میبرد، که در آن نخهای پسزمینه متوقف میشوند. WakeLock از این انتقال جلوگیری میکند و CPU را در حالت فعال نگه میدارد.
مکانیزم WakeLock از طریق سرویس سیستمی PowerManager مدیریت میشود که از طریق متد getSystemService(Context.POWER_SERVICE) قابل دسترسی است. توسعهدهنده یک شی WakeLock با مشخص کردن نوع قفل ایجاد میکند و باید پس از اتمام کار آن را آزاد کند، در غیر این صورت باتری دستگاه به سرعت تخلیه میشود. سیستم WakeLock را به طور خودکار آزاد نمیکند — این مسئولیت برنامه است.
با هر نسخه اصلی اندروید، گوگل کنترل بر WakeLock را سختتر میکند. از اندروید 9 (API 28) به بعد، برنامه در پسزمینه بدون دلیل موجه نمیتواند WakeLock دریافت کند و سیستم برنامههایی که از قفلها سوءاستفاده میکنند را ردیابی کرده و میتواند آنها را به زور آزاد کند. در اندروید 12+ محدودیتهای اضافی برای دسترسی به PowerManager برای برنامههای پسزمینه اعمال شده است.
WakeLock در سناریوهایی مورد نیاز است که وظیفه نمیتواند با انتقال دستگاه به خواب قطع شود: دانلود فایل بزرگ از طریق اتصال ناپایدار، ضبط ویدئو، انجام محاسبات طولانی بدون مشارکت کاربر. بدون قفل خواب، پردازنده به خواب عمیق میرود، تمام نخها (threads) منجمد میشوند و وظیفه ناتمام میماند.
با این حال، گوگل به شدت توصیه میکند که استفاده از WakeLock را به حداقل برسانید. در بیشتر موارد، همان وظیفه را میتوان با Foreground Service با اعلان، WorkManager یا JobScheduler حل کرد. این مکانیزمها وضعیت باتری و شبکه را در نظر میگیرند که عمر باتری دستگاه را افزایش میدهد.
WakeLock از طریق سرویس سیستمی PowerManager که وضعیت تغذیه دستگاه را مدیریت میکند کار میکند. وقتی برنامه از طریق powerManager.newWakeLock() قفل درخواست میکند، سیستم سطح فعالیت CPU را افزایش داده و از انتقال به خواب عمیق جلوگیری میکند. پس از فراخوانی wakeLock.release() سیستم به حالت عادی صرفهجویی انرژی بازمیگردد.
درک این نکته مهم است که WakeLock از همه حالتهای صرفهجویی انرژی جلوگیری نمیکند. Doze Mode (حالت خواب اندروید 6+) ممکن است در فازهای خاصی WakeLock را نادیده بگیرد — برنامه با WakeLock نگهداشته شده در پنجرههای سرویس Doze به شبکه دسترسی نخواهد داشت. این بدان معناست که حتی WakeLock فعال نیز اجرای عملیات شبکه را در طول فاز دوم Doze تضمین نمیکند.
هر WakeLock با PowerManager.WakeLock در سمت فریمورک مرتبط است. سیستم شمارش قفلهای فعال را در سطح فرآیند حفظ میکند: اگر یک فرآیند چندین WakeLock را نگه دارد، آنها جمع میشوند و آزادسازی فقط پس از فراخوانی release() برای هر قفل انجام میشود. اندروید همچنین از wake lock timeouts پشتیبانی میکند — آزادسازی خودکار پس از بازه زمانی مشخص. با این حال، تکیه بر timeout توصیه نمیشود: وظیفه ممکن است زودتر تمام شود و زمان اضافی نگهداشت عمر باتری را کاهش میدهد.
هنگام انتقال دستگاه به حالت خواب (دکمه پاور)، اندروید به زور تمام SCREEN_DIM_WAKE_LOCK و SCREEN_BRIGHT_WAKE_LOCK را آزاد میکند اما PARTIAL_WAKE_LOCK را حفظ میکند. این بدان معناست که قفل صفحه نمیتواند دستگاه را از خاموش کردن نمایشگر بازدارد — فقط PARTIAL_WAKE_LOCK میتواند پس از فشار دکمه پاور به کار ادامه دهد.
در اندروید چندین نوع 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 از اندروید 7 (API 24) به عنوان منسوخ علامتگذاری شدهاند. آنها صفحه را روشن نگه میدارند که منجر به مصرف قابل توجه باتری میشود. گوگل به جای آنها استفاده از FLAG_KEEP_SCREEN_ON را از طریق Activity.getWindow().addFlags() توصیه میکند — این پرچم فقط با Activity فعال کار میکند و به مجوز WAKE_LOCK نیاز ندارد و سیستم به طور خودکار زمان نگهداشت صفحه را مدیریت میکند.
WakeLock یکی از اصلیترین «مصرفکنندگان» باتری در اندروید است. هر ثانیه نگهداشتن قفل خواب انرژی اضافی مصرف میکند زیرا پردازنده نمیتواند به حالت کم مصرف C-state منتقل شود. تحقیقات Google Power Dashboard نشان میدهد که برنامههایی با WakeLock به درستی آزاد نشده میتوانند مصرف انرژی دستگاه را در حالت آماده به کار 30–50% افزایش دهند.
سیستم برنامههایی که از WakeLock سوءاستفاده میکنند را از طریق مؤلفه Battery Historian ردیابی میکند. توسعهدهنده میتواند مشخصات مصرف انرژی را تحلیل کرده و «نشت» قفلها — موقعیتهایی که WakeLock ایجاد شده اما آزاد نشده — را شناسایی کند. Google Play Console آمار WakeLock را برای برنامههای منتشر شده نشان میدهد و زمان نگهداشت طولانی میتواند باعث نظرات منفی شود.
Doze Mode و App Standby به طور اضافی کار WakeLock را محدود میکنند. در فاز اول Doze (Light Doze) سیستم WakeLock را در پنجرههای سرویس کوتاه مجاز میداند. در فاز دوم (Deep Doze) WakeLock با سایر قفلها ترکیب شده و در یک پنجره مشترک اجرا میشود. اگر برنامه بیش از 10 دقیقه بدون تعامل کاربر WakeLock را نگه دارد، سیستم میتواند آن را به زور آزاد کرده و برنامه را در لیست سیاه بهینهسازی باتری قرار دهد.
استفاده صحیح از WakeLock تعادلی بین نیاز به انجام وظیفه و مراقبت از باتری دستگاه است. گوگل توصیه میکند چند اصل را رعایت کنید: همیشه WakeLock را در finally یا از طریق acquire(timeout) آزاد کنید، از حداقل نوع قفل لازم استفاده کنید و از نگهداشت طولانی مدت بدون ضرورت اجتناب کنید.
WakeLock باید در همان بلوک کدی که ایجاد شده آزاد شود. برای تضمین آزادسازی در هنگام استثناها از ساختار try-finally یا بلوک use در Kotlin استفاده میشود. در اندروید 10+ اگر WakeLock بیش از 60 ثانیه نگه داشته شود، سیستم هشداری در logcat نمایش میدهد: "WakeLock held for more than 60 seconds" — این سیگنالی از نشت احتمالی است.
متد acquire(long timeout) به طور خودکار WakeLock را پس از زمان مشخص شده به میلیثانیه آزاد میکند. این بیمهای برای مواردی است که کد آزادسازی به دلیل استثنا یا باگ اجرا نشود. توصیه میشود همیشه timeout برابر با حداکثر زمان مورد انتظار اجرای وظیفه به علاوه 10–20% ذخیره تعیین کنید.
قبل از فراخوانی release() باید بررسی کنید که آیا WakeLock در حال حاضر نگه داشته شده است. فراخوانی مجدد release() بدون acquire() قبلی باعث RuntimeException: WakeLock under-locked میشود. توصیه میشود پرچم وضعیت (isHeld) را ذخیره کرده و قبل از آزادسازی wakeLock.isHeld() را بررسی کنید.
بیایید ایجاد و آزادسازی صحیح WakeLock در Kotlin را بررسی کنیم. مثال دانلود ناهمگام داده با نگهداشتن PARTIAL_WAKE_LOCK، آزادسازی تضمینی در بلوک try-finally و تعیین timeout برای محافظت در برابر نشت را نشان میدهد. سرویس از 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 یک مجوز عادی (normal) است — نیازی به درخواست runtime از کاربر ندارد و هنگام نصب برنامه به طور خودکار اعطا میشود. با این حال، Google Play ممکن است انتشار را رد کند اگر برنامه سناریوی واضحی برای استفاده از WakeLock نداشته باشد.
<uses-permission
android:name="android.permission.WAKE_LOCK" />
<uses-permission
android:name="android.permission.DEVICE_POWER" />
WakeLock یک مکانیزم سطح پایین است و گوگل توصیه میکند در صورت امکان آن را با 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 یک قفل سیستمی است که از انتقال دستگاه اندروید به حالت خواب جلوگیری میکند. پردازنده یا صفحه را در حالت فعال نگه میدارد و به وظایف پسزمینه (دانلود، محاسبات) اجازه میدهد بدون وقفه اجرا شوند. از طریق سرویس سیستمی 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 اعلام شود. این یک مجوز عادی (normal permission) است که هنگام نصب به طور خودکار اعطا میشود — نیازی به درخواست در runtime نیست. بدون این مجوز، فراخوانی newWakeLock() null برمیگرداند یا SecurityException پرتاب میکند.
اگر release() فراخوانی نشود، دستگاه نمیتواند به حالت خواب برود. باتری به طور قابل توجهی سریعتر تخلیه میشود (تا 50% مصرف اضافی). سیستم نشت را در logcat ثبت میکند و Battery Historian زمان غیرعادی نگهداشت WakeLock را نشان میدهد که منجر به نظرات منفی کاربران میشود.
برای وظایف طولانی از Foreground Service با اعلان استفاده کنید — سیستم خود WakeLock را مدیریت میکند. برای وظایف به تأخیر افتاده و تضمینی از WorkManager استفاده کنید که WakeLock را در داخل خود پشتیبانی میکند. برای وظایف کوتاه زمانبندی — AlarmManager.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید