WakeLock to mechanizm Androida, który zapobiega przejściu urządzenia w tryb uśpienia, utrzymując procesor lub ekran w stanie aktywnym. Zadania działające w tle, takie jak pobieranie plików, odtwarzanie audio lub zapis danych, wymagają WakeLock do gwarantowanego wykonania bez przerw. Zgodnie ze specyfikacją Android Developers, 2025, nieprawidłowe użycie WakeLock prowadzi do szybkiego rozładowania baterii i może być przyczyną zablokowania aplikacji w Google Play.
Najważniejsze
WakeLock to systemowa blokada, która zabrania Androidowi przejścia urządzenia w tryb obniżonego poboru energii. Zwykle Android po kilku sekundach bezczynności użytkownika wyłącza ekran i przełącza procesor w stan głębokiego uśpienia (deep sleep), w którym wątki działające w tle są wstrzymywane. WakeLock zapobiega temu przejściu, utrzymując CPU w trybie aktywnym.
Mechanizm WakeLock jest zarządzany przez systemowy serwis PowerManager, do którego dostęp uzyskuje się przez metodę getSystemService(Context.POWER_SERVICE). Programista tworzy obiekt WakeLock, określając typ blokady, i musi zagwarantować jego zwolnienie po zakończeniu zadania, w przeciwnym razie akumulator urządzenia będzie szybko się rozładowywać. System nie zwalnia WakeLock automatycznie — to odpowiedzialność aplikacji.
Z każdą główną wersją Androida Google zaostrza kontrolę nad WakeLock. Począwszy od Androida 9 (API 28), aplikacja w tle nie może uzyskać WakeLock bez ważnego powodu, a system śledzi aplikacje nadużywające blokad i może je przymusowo zwalniać. W Androidzie 12+ wprowadzono dodatkowe ograniczenia dostępu do PowerManager dla aplikacji działających w tle.
WakeLock jest wymagany w scenariuszach, gdzie zadanie nie może zostać przerwane przez przejście urządzenia w tryb uśpienia: pobieranie dużego pliku przez niestabilne połączenie, nagrywanie wideo, wykonywanie długotrwałych obliczeń bez udziału użytkownika. Bez blokady snu procesor przechodzi w głęboki sen, wszystkie wątki (threads) są zamrażane, a zadanie pozostaje niedokończone.
Google zdecydowanie zaleca jednak minimalizowanie użycia WakeLock. W większości przypadków to samo zadanie można rozwiązać za pomocą Foreground Service z powiadomieniem, WorkManager lub JobScheduler. Mechanizmy te uwzględniają stan baterii i sieci, co wydłuża czas pracy urządzenia na baterii.
WakeLock działa przez systemowy serwis PowerManager, który zarządza stanem zasilania urządzenia. Gdy aplikacja żąda blokady przez powerManager.newWakeLock(), system podnosi poziom aktywności CPU, zapobiegając przejściu w głęboki sen. Po wywołaniu wakeLock.release() system powraca do normalnego trybu oszczędzania energii.
Ważne jest, aby zrozumieć, że WakeLock nie zapobiega wszystkim trybom oszczędzania energii. Doze Mode (tryb uśpienia Android 6+) może ignorować WakeLock w określonych fazach — aplikacja z utrzymywanym WakeLock nie uzyska dostępu do sieci w oknach serwisowych Doze. Oznacza to, że nawet aktywny WakeLock nie gwarantuje wykonania operacji sieciowych podczas drugiej fazy Doze.
Każdy WakeLock jest powiązany z PowerManager.WakeLock po stronie frameworka. System prowadzi licznik aktywnych blokad na poziomie procesu: jeśli jeden proces utrzymuje kilka WakeLock, są one sumowane, a zwolnienie następuje dopiero po wywołaniu release() dla każdej blokady. Android obsługuje również wake lock timeouts — automatyczne zwalnianie po określonym interwale. Jednak poleganie na timeout nie jest zalecane: zadanie może zakończyć się wcześniej, a dodatkowy czas utrzymywania skróci żywotność baterii.
Podczas przejścia urządzenia w tryb uśpienia (przycisk zasilania) Android wymusza zwolnienie wszystkich SCREEN_DIM_WAKE_LOCK i SCREEN_BRIGHT_WAKE_LOCK, ale zachowuje PARTIAL_WAKE_LOCK. Oznacza to, że blokada ekranu nie może utrzymać urządzenia przed wyłączeniem wyświetlacza — tylko PARTIAL_WAKE_LOCK jest w stanie kontynuować działanie po naciśnięciu przycisku zasilania.
W Androidzie istnieje kilka typów WakeLock, z których każdy zarządza konkretnymi komponentami urządzenia. Wybór typu określa, które dokładnie komponenty sprzętowe pozostają aktywne po blokadzie. Nieprawidłowy wybór typu prowadzi do nadmiernego zużycia energii z powodu włączenia niepotrzebnych modułów.
| Typ | CPU | Ekran | Klawiatura | Kiedy używać |
|---|---|---|---|---|
| PARTIAL_WAKE_LOCK | Wł. | Wył. | Wył. | Pobieranie plików, obliczenia |
| SCREEN_DIM_WAKE_LOCK | Wł. | Przyciemniony | Wył. | Odtwarzacz wideo, prezentacja |
| SCREEN_BRIGHT_WAKE_LOCK | Wł. | Jasny | Wył. | Gry (przestarzałe) |
| FULL_WAKE_LOCK | Wł. | Jasny | Jasna | Przestarzałe (deprecated) |
PARTIAL_WAKE_LOCK to najczęściej używany i zalecany typ. Utrzymuje CPU w trybie aktywnym, ale pozwala wyłączyć ekran i podświetlenie klawiatury. To optymalny wybór dla zadań w tle: pobieranie danych, przetwarzanie obrazów, synchronizacja. Ekran gaśnie po systemowym czasie oczekiwania, co oszczędza baterię podczas wykonywania niewidocznej dla użytkownika pracy.
SCREEN_DIM_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK i FULL_WAKE_LOCK są oznaczone jako przestarzałe od Androida 7 (API 24). Utrzymują one ekran włączony, co prowadzi do znacznego zużycia baterii. Google zaleca używanie zamiast nich FLAG_KEEP_SCREEN_ON przez Activity.getWindow().addFlags() — ta flaga działa tylko przy aktywnej Activity i nie wymaga uprawnienia WAKE_LOCK, a system automatycznie zarządza czasem utrzymywania ekranu.
WakeLock to jeden z głównych „pożeraczy" baterii w Androidzie. Każda sekunda utrzymywania blokady snu zużywa dodatkową energię, ponieważ procesor nie może przejść w energooszczędny stan C-state. Badanie Google Power Dashboard pokazuje, że aplikacje z nieprawidłowo zwolnionymi WakeLock mogą zwiększyć zużycie energii urządzenia o 30–50% w trybie czuwania.
System śledzi aplikacje nadużywające WakeLock przez komponent Battery Historian. Programista może przeanalizować profil zużycia energii i wykryć „wycieki" blokad — sytuacje, w których WakeLock został utworzony, ale nie zwolniony. Google Play Console wyświetla statystyki WakeLock dla opublikowanych aplikacji, a długi czas utrzymywania może być przyczyną złych opinii.
Doze Mode i App Standby dodatkowo ograniczają działanie WakeLock. W pierwszej fazie Doze (Light Doze) system zezwala na WakeLock w krótkich oknach serwisowych. W drugiej fazie (Deep Doze) WakeLock jest łączony z innymi blokadami i wykonywany we wspólnym oknie. Jeśli aplikacja utrzymuje WakeLock dłużej niż 10 minut bez interakcji użytkownika, system może wymusić jego zwolnienie i umieścić aplikację na czarnej liście optymalizacji baterii.
Prawidłowe używanie WakeLock to równowaga między koniecznością wykonania zadania a dbałością o baterię urządzenia. Google zaleca przestrzeganie kilku zasad: zawsze zwalniaj WakeLock w finally lub przez acquire(timeout), używaj minimalnie niezbędnego typu blokady i unikaj długotrwałego utrzymywania bez konieczności.
WakeLock powinien być zwalniany w tym samym bloku kodu, w którym został utworzony. Dla gwarancji zwolnienia przy wyjątkach używa się konstrukcji try-finally lub bloku use w Kotlin. Na Androidzie 10+ system wyświetla ostrzeżenie w logcat, jeśli WakeLock jest utrzymywany dłużej niż 60 sekund: "WakeLock held for more than 60 seconds" — to sygnał możliwego wycieku.
Metoda acquire(long timeout) automatycznie zwalnia WakeLock po określonym czasie w milisekundach. To zabezpieczenie na wypadek, gdyby kod zwalniający nie został wykonany z powodu wyjątku lub błędu. Zaleca się zawsze podawać timeout równy maksymalnemu oczekiwanemu czasowi wykonania zadania plus 10–20% zapasu.
Przed wywołaniem release() należy sprawdzić, czy WakeLock jest aktualnie utrzymywany. Ponowne wywołanie release() bez wcześniejszego acquire() powoduje RuntimeException: WakeLock under-locked. Zaleca się przechowywanie flagi stanu (isHeld) i przed zwolnieniem sprawdzać wakeLock.isHeld().
Rozważmy poprawne tworzenie i zwalnianie WakeLock w Kotlin. Przykład demonstruje asynchroniczne pobieranie danych z utrzymywaniem PARTIAL_WAKE_LOCK, gwarantowanym zwolnieniem w bloku try-finally i określeniem timeout dla zabezpieczenia przed wyciekami. Serwis używa CoroutineScope z dyspozytorem IO do wykonania zadania w tle.
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() {
// Symulacja pobierania pliku
delay(30000)
}
override fun onDestroy() {
super.onDestroy()
scope.cancel()
if (wakeLock.isHeld()) {
wakeLock.release()
}
}
override fun onBind(intent: Intent): IBinder? = null
}
Do używania WakeLock należy dodać uprawnienie w AndroidManifest.xml. Uprawnienie WAKE_LOCK jest normalne (normal) — nie wymaga zapytania w runtime od użytkownika i jest przyznawane automatycznie podczas instalacji aplikacji. Niemniej jednak Google Play może odrzucić publikację, jeśli aplikacja nie ma oczywistego scenariusza użycia WakeLock.
<uses-permission
android:name="android.permission.WAKE_LOCK" />
<uses-permission
android:name="android.permission.DEVICE_POWER" />
WakeLock to niskopoziomowy mechanizm i Google zaleca, jeśli to możliwe, zastępowanie go bardziej nowoczesnymi API. Główną alternatywą jest Foreground Service z powiadomieniem, który automatycznie utrzymuje blokadę CPU na czas działania serwisu. System sam zarządza WakeLock dla Foreground Service, zwalniając programistę z konieczności jawnego przechwytywania i zwalniania.
WorkManager to drugi pod względem ważności narzędzie do zadań w tle. Gwarantuje wykonanie pracy nawet przy przejściu urządzenia w Doze i po ponownym uruchomieniu. WorkManager obsługuje utrzymywanie blokady (hold lock) wewnętrznie — programista nie musi jawnie pracować z PowerManager. Zadanie jest wykonywane w oknie serwisowym Doze z automatycznym zarządzaniem blokadą snu.
Do regularnych zadań wymagających dokładnego czasu używa się AlarmManager z setAndAllowWhileIdle(), który może obudzić urządzenie z Doze. Jednak AlarmManager nadaje się tylko do krótkich operacji — nie jest przeznaczony do długotrwałego utrzymywania WakeLock. Jeśli zadanie trwa dłużej niż 10 sekund, należy połączyć AlarmManager z BroadcastReceiver, który uruchamia Foreground Service.
Często zadawane pytania
WakeLock to systemowa blokada, która zapobiega przejściu urządzenia z Androidem w tryb uśpienia. Utrzymuje procesor lub ekran w stanie aktywnym, pozwalając zadaniom w tle (pobieranie, obliczenia) wykonywać się bez przerwy. Jest zarządzany przez systemowy serwis PowerManager.
Główne typy: PARTIAL_WAKE_LOCK (CPU aktywny, ekran wyłączony) — zalecany; SCREEN_DIM_WAKE_LOCK (CPU + przyciemniony ekran); SCREEN_BRIGHT_WAKE_LOCK (CPU + jasny ekran). SCREEN_DIM, SCREEN_BRIGHT i FULL_WAKE_LOCK są oznaczone jako przestarzałe i zastąpione przez FLAG_KEEP_SCREEN_ON.
Tak, w manifeście należy zadeklarować android.permission.WAKE_LOCK. To normalne uprawnienie (normal permission), które jest przyznawane automatycznie podczas instalacji — nie trzeba go żądać w runtime. Bez tego uprawnienia wywołanie newWakeLock() zwróci null lub zgłosi SecurityException.
Jeśli nie wywołasz release(), urządzenie nie będzie mogło przejść w tryb uśpienia. Bateria będzie się rozładowywać znacznie szybciej (do 50% dodatkowego zużycia). System zarejestruje wyciek w logcat, a Battery Historian pokaże anormalny czas utrzymywania WakeLock, co doprowadzi do złych opinii użytkowników.
Do długotrwałych zadań używaj Foreground Service z powiadomieniem — system sam zarządza WakeLock. Do odroczonych i gwarantowanych zadań używaj WorkManager, który obsługuje WakeLock wewnętrznie. Do krótkich zadań harmonogramowych — AlarmManager.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również