From 2fb30cab46d5823e8e1ee8420fd84484f44e6e03 Mon Sep 17 00:00:00 2001 From: Sadaqat Hussain Date: Thu, 21 May 2026 16:13:22 +0500 Subject: [PATCH] =?UTF-8?q?fix(android):=20defer=20wakelock=20toggle=20whe?= =?UTF-8?q?n=20no=20activity=20is=20attached=20=20=20=20Wakelock.toggle()/?= =?UTF-8?q?isEnabled()=20threw=20NoActivityException=20whenever=20they=20?= =?UTF-8?q?=20=20were=20called=20with=20no=20foreground=20activity=20attac?= =?UTF-8?q?hed=20(e.g.=20the=20app=20is=20=20=20backgrounded=20or=20mid=20?= =?UTF-8?q?lifecycle=20transition),=20surfacing=20as=20non-fatal=20=20=20c?= =?UTF-8?q?rashes=20in=20apps=20that=20toggle=20the=20wakelock=20off=20the?= =?UTF-8?q?=20foreground=20path.=20=20=20=20Instead=20of=20throwing,=20the?= =?UTF-8?q?=20requested=20wakelock=20state=20is=20now=20tracked=20in=20=20?= =?UTF-8?q?=20Kotlin=20and=20re-applied=20once=20an=20activity=20(re)attac?= =?UTF-8?q?hes=20=E2=80=94=20matching=20how=20the=20=20=20Windows/Linux/we?= =?UTF-8?q?b=20implementations=20track=20state.=20The=20activity=20setter?= =?UTF-8?q?=20only=20=20=20re-asserts=20FLAG=5FKEEP=5FSCREEN=5FON=20when?= =?UTF-8?q?=20wakelock=20was=20actually=20enabled,=20so=20it=20=20=20won't?= =?UTF-8?q?=20clear=20the=20flag=20for=20apps=20that=20set=20it=20on=20the?= =?UTF-8?q?ir=20own=20window.=20The=20=20=20now-unused=20NoActivityExcepti?= =?UTF-8?q?on=20class=20is=20removed.=20=20=20=20Bumps=20wakelock=5Fplus?= =?UTF-8?q?=20to=201.6.2=20and=20updates=20the=20CHANGELOG.=20=20=20=20Fix?= =?UTF-8?q?es=20#131,=20#102,=20#6.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(android): defer wakelock toggle when no activity is attached Wakelock.toggle()/isEnabled() threw NoActivityException whenever they were called with no foreground activity attached (e.g. the app is backgrounded or mid lifecycle transition), surfacing as non-fatal crashes in apps that toggle the wakelock off the foreground path. Instead of throwing, the requested wakelock state is now tracked in Kotlin and re-applied once an activity (re)attaches — matching how the Windows/Linux/web implementations track state. The activity setter only re-asserts FLAG_KEEP_SCREEN_ON when wakelock was actually enabled, so it won't clear the flag for apps that set it on their own window. The now-unused NoActivityException class is removed. Bumps wakelock_plus to 1.6.2 and updates the CHANGELOG. Fixes #131, #102, #6. --- .gitignore | 3 +- wakelock_plus/CHANGELOG.md | 3 ++ .../plus/wakelock/Wakelock.kt | 47 ++++++++++--------- wakelock_plus/pubspec.yaml | 2 +- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 88efa4b..eeb418a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ .buildlog/ .history .svn/ -.metadata \ No newline at end of file +.metadata +CLAUDE.md diff --git a/wakelock_plus/CHANGELOG.md b/wakelock_plus/CHANGELOG.md index da5027c..5713e1d 100644 --- a/wakelock_plus/CHANGELOG.md +++ b/wakelock_plus/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.6.2] +* Android: Fixed `NoActivityException` ("wakelock requires a foreground activity") being thrown when `toggle`/`enabled` were called with no foreground activity attached (e.g. while the app is backgrounded or during a lifecycle transition). The requested wakelock state is now remembered and re-applied once an activity (re)attaches instead of throwing. + ## [1.6.1] * [#133](https://github.com/fluttercommunity/wakelock_plus/pull/133): wakelock_plus Flutter 3.38 downgrade. Thanks [diegotori](https://github.com/diegotori). - Library now requires Dart version `3.10` or higher, restoring previous compatibility. diff --git a/wakelock_plus/android/src/main/kotlin/dev/fluttercommunity/plus/wakelock/Wakelock.kt b/wakelock_plus/android/src/main/kotlin/dev/fluttercommunity/plus/wakelock/Wakelock.kt index 8ba445a..36e5027 100644 --- a/wakelock_plus/android/src/main/kotlin/dev/fluttercommunity/plus/wakelock/Wakelock.kt +++ b/wakelock_plus/android/src/main/kotlin/dev/fluttercommunity/plus/wakelock/Wakelock.kt @@ -6,34 +6,35 @@ import android.app.Activity import android.view.WindowManager internal class Wakelock { - var activity: Activity? = null - - private val enabled - get() = activity!!.window.attributes.flags and - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON != 0 + // The desired wakelock state. Tracked independently of [activity] so that a + // toggle requested while no activity is attached (e.g. the app is in the + // background or mid lifecycle transition) is remembered and re-applied once an + // activity (re)attaches, instead of throwing a NoActivityException. + private var enableWakelock = false - fun toggle(message: ToggleMessage) { - if (activity == null) { - throw NoActivityException() + var activity: Activity? = null + set(value) { + field = value + // Re-assert the wakelock on the newly attached activity's window, but only + // when it was actually requested. If the user never enabled it (or last + // disabled it), leave the flag alone — the activity may keep the screen on + // for its own reasons. + if (enableWakelock) applyWakelock() } - val activity = this.activity!! - val enabled = this.enabled - - if (message.enable!!) { - if (!enabled) activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) - } else if (enabled) { - activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + private fun applyWakelock() { + val window = activity?.window ?: return + if (enableWakelock) { + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) } } - fun isEnabled(): IsEnabledMessage { - if (activity == null) { - throw NoActivityException() - } - - return IsEnabledMessage(enabled = enabled) + fun toggle(message: ToggleMessage) { + enableWakelock = message.enable!! + applyWakelock() } -} -class NoActivityException : Exception("wakelock requires a foreground activity") + fun isEnabled(): IsEnabledMessage = IsEnabledMessage(enabled = enableWakelock) +} diff --git a/wakelock_plus/pubspec.yaml b/wakelock_plus/pubspec.yaml index a555046..7a4ea90 100644 --- a/wakelock_plus/pubspec.yaml +++ b/wakelock_plus/pubspec.yaml @@ -2,7 +2,7 @@ name: wakelock_plus description: >-2 Plugin that allows you to keep the device screen awake, i.e. prevent the screen from sleeping on Android, iOS, macOS, Windows, Linux, and web. -version: 1.6.1 +version: 1.6.2 repository: https://github.com/fluttercommunity/wakelock_plus/tree/main/wakelock_plus environment: