DEV Community

Super Funicular
Super Funicular

Posted on

Why an Android Phone Can Record All Night and Still Be Unreachable: Wi-Fi Power Save, WifiLock, and Four Deprecated APIs

Short answer: Android is allowed to power down the Wi-Fi radio when the device has been idle for a while, and the documented way to prevent that — WifiManager.WifiLock — has had every genuinely useful mode deprecated or restricted. The one mode still doing work, WIFI_MODE_FULL_LOW_LATENCY, is documented as active only while the screen is on and the acquiring app is in the foreground. That is exactly the state a screen-off camera is never in. The recording keeps running. Being reachable is a separate question with a separate answer.

If you run an old Android phone as a camera, you will eventually meet a failure that looks like nothing at all. You open the live view from the sofa and the page hangs. You try again and it loads instantly. Later you check the storage and the file from that exact minute is there, complete, perfectly watchable.

Nothing broke. The recorder never stopped. What went quiet was the radio.

This is a different problem from the one most "why did my phone camera stop" articles are about, and it has its own mechanism, its own API surface, and — unusually — an API surface that Android has spent the last several releases dismantling. This piece walks the primary documentation for that surface and says plainly what it does and does not promise.

I build a phone-as-camera app, so treat me as an interested party. Everything factual below is quoted from Google's own reference pages, linked at the bottom, and I have flagged the places where the documentation simply does not answer the question.

Why does my phone camera's live view stop loading when the screen is off?

Short answer: because keeping the camera alive and keeping the network alive are two different guarantees, and Android only gives you a strong one for the first. A foreground service keeps your process running and your camera session open. The Wi-Fi radio is governed by separate machinery. Google's own words, from the WifiManager.WifiLock class documentation: "Normally the Wi-Fi radio may turn off when the user has not used the device in a while." A phone bolted to a shelf with its screen off is, by every definition the system has, a device the user has not used in a while.

Does a foreground service keep the Wi-Fi radio awake on Android?

Short answer: no, and Android has never claimed it does. The foreground-service contract is about your process not being killed and your camera access not being revoked — see How an Android Phone Keeps Recording Video With the Screen Off for that half. There is no sentence anywhere in the foreground-service documentation that ties service type to radio power state. The radio has its own lock class, and that lock class is the subject of the rest of this article.

Three different things people call "the camera stopped"

It is worth separating them, because the fixes have nothing in common.

  1. The process died. Doze, App Standby, an OEM task-killer, a reboot after an update. The file stops growing. This is the territory of Why Does My Android Camera Stop Recording When the Screen Turns Off.
  2. Something took the camera away. Another app opened the lens and won on priority. The process is fine; the camera session is not. That is Can Two Apps Use the Same Android Camera at Once.
  3. Everything is running and you cannot reach it. The file is growing. The encoder is fine. The HTTP server inside the app is listening. The packets are just not getting picked up promptly, because the radio is conserving power.

Case 3 is the one with no symptom. There is no error, no notification, no gap in the recording. The only evidence is a page that takes an uncomfortable amount of time to load, and only sometimes.

What WifiManager.WifiLock actually promises

The class exists precisely for case 3. From the reference page:

"Allows an application to keep the Wi-Fi radio awake. Normally the Wi-Fi radio may turn off when the user has not used the device in a while. Acquiring a WifiLock will keep the radio on until the lock is released. Multiple applications may hold WifiLocks, and the radio will only be allowed to turn off when no WifiLocks are held in any application."

There is a matching warning against overuse — "a program whose network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely affecting battery life" — and one hard boundary that is easy to miss:

"Note that WifiLocks cannot override the user-level 'Wi-Fi Enabled' setting, nor Airplane Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device is idle."

So the class does not fight the user. It fights idleness. Good. Now look at what you are allowed to pass to it.

The four lock modes, and what happened to each

createWifiLock(int lockType, String tag) takes a mode constant. Here is the state of every one of them, quoted from the WifiManager reference.

Constant Status What the documentation says
WIFI_MODE_FULL Deprecated in API level 29 "This API is non-functional and will have no impact."
WIFI_MODE_SCAN_ONLY Deprecated in API level 29 "This API is non-functional and will have no impact."
WIFI_MODE_FULL_HIGH_PERF Deprecated in API level 34 "automatically replaced with WIFI_MODE_FULL_LOW_LATENCY with all the restrictions documented on that lock"
WIFI_MODE_FULL_LOW_LATENCY Current "Wi-Fi will operate with a priority to achieve low latency" — with limitations, below

There is a fifth casualty. The convenience overload createWifiLock(String tag), the one that takes no mode at all, is itself "deprecated in API level 29" with the note "This API is non-functional."

That is a striking amount of demolition for a class whose own top-level description still reads as a live promise. The description was written for API level 1 and is still accurate about intent. The constants underneath it are where the current behaviour lives.

The one lock that survived is documented as screen-on only

This is the sentence that decides the whole question for a camera. WIFI_MODE_FULL_LOW_LATENCY carries an explicit list of limitations:

"The lock is only active when the device is connected to an access point. The lock is only active when the screen is on. The lock is only active when the acquiring app is running in the foreground."

Read the second and third lines again with a shelf-mounted phone in mind. The only non-deprecated Wi-Fi lock mode is inactive in exactly the configuration a background camera runs in. It is not blocked, not throttled, not degraded — the documentation says it is not active.

And it is not an accident of neglect. The deprecation note on WIFI_MODE_FULL_HIGH_PERF says the replacement carries "all the restrictions documented on that lock", and gives the reason: "Deprecation is due to the impact of WIFI_MODE_FULL_HIGH_PERF on power dissipation." Android looked at an API that kept the radio hot regardless of screen state and decided, deliberately, that phones should not do that.

The docs even describe the intended audience: "Example use cases are real time gaming or virtual reality applications where low latency is a key factor for user experience." Games and VR. Both are, by definition, screen-on and in the foreground. The surviving mode was designed around a person looking at the device.

There is one more line worth knowing, for anyone reading old code: "For an app which acquires both WIFI_MODE_FULL_LOW_LATENCY and WIFI_MODE_FULL_HIGH_PERF locks, WIFI_MODE_FULL_LOW_LATENCY lock will be effective when app is running in foreground and screen is on, while the WIFI_MODE_FULL_HIGH_PERF lock will take effect otherwise." That sentence predates the API-34 deprecation of the second constant, and the two notes now sit on the same page pointing in different directions. If you are trying to reason about a specific device, read the deprecation note as the newer statement.

Before the stream fails, discovery fails

There is a second lock, and it explains a symptom people usually blame on their router.

WifiManager.MulticastLock exists because of a filter you probably never think about:

"Allows an application to receive Wifi Multicast packets. Normally the Wifi stack filters out packets not explicitly addressed to this device. Acquiring a MulticastLock will cause the stack to receive packets addressed to multicast addresses. Processing these extra packets can cause a noticeable battery drain and should be disabled when not needed."

Multicast is how zero-configuration discovery works. When something on your network advertises or resolves a .local name, it is doing it with multicast. If a device is not accepting multicast packets, it does not answer discovery queries — while remaining perfectly reachable at its raw IP address.

That produces a very specific and very confusing failure: the "find my camera on the network" button finds nothing, but typing the address into a browser works fine. Two more details from the same page make it worse for an unattended device. "Applications cannot leave Multicast locked on. When an app exits or crashes, any Multicast locks will be released." And releasing restores the filter — "restoring the filter of packets not addressed specifically to this device and saving power."

This is a good argument for not depending on names. If you are running a phone as a camera, reserve its address on the router and use the address. Discovery is a convenience layer with its own battery-driven off switch; the address is not. The mechanics of the server on the other end are in How an Android Phone Serves Its Own Live Camera Feed Over Your LAN.

This is not Doze, and the difference is practical

It is tempting to file all of this under Doze. Do not, because Doze has a precondition your camera almost certainly violates. From Google's Doze guidance:

"If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode."

Unplugged. A phone running as a 24/7 camera lives on a charger. It is stationary and its screen is off, but it fails the first condition, so the Doze behaviour described on that page — "suspending network access and deferring jobs, syncs, and alarms" — is not what you are looking at.

Which is exactly why this problem is worth naming separately. The advice that solves Doze (foreground service, battery-optimisation exemption) does not touch radio power save, because radio power save is not Doze. You can do everything right on the process-lifecycle side and still have a camera that takes several seconds to answer its first request of the hour.

What the documentation does not tell you

I went looking for these and did not find them. Naming the gaps is more useful than filling them from memory.

  • There is no documented statement of how long an idle radio takes to respond. No latency figure, no wake-up bound, nothing you can quote. Anyone who gives you a number for your phone has not measured your phone.
  • There is no documented tie between foreground-service type and Wi-Fi power state. The camera foreground-service type governs camera access. Nothing in it addresses the radio.
  • The behaviour of an already-open TCP connection during radio power save is not specified. Whether a long-lived stream survives an idle period or has to be re-established is left to the implementation.
  • OEM behaviour is not covered at all. Manufacturers ship their own power management on top of this, and the platform reference does not attempt to describe it.
  • The WifiLock class description was never updated to reflect the constants below it. It still reads as an unqualified promise to keep the radio on. Both statements are on the same page; only one of them describes API 34 behaviour.
  • There is no documented alternative for a background app that needs a hot radio. The deprecation notes explain why HIGH_PERF went away. They do not offer a replacement for the use case it served.

What you can actually do about it

None of this requires code, and none of it costs anything.

  1. Use the IP address, not a name. Give the phone a DHCP reservation on your router so the address never moves, and bookmark the address. That removes multicast discovery from the critical path entirely.
  2. Retry once before you panic. A first request that hangs and a second that loads instantly is the signature of a radio waking up, not of a dead camera. Treat one slow load as information, not as a failure.
  3. Measure your own device. Leave the phone idle for an hour, then load the page and count. Do it again after a full night. You now have a number for your hardware, which is worth more than any number in any article, including this one.
  4. Keep it plugged in. You were going to anyway, and per the quotation above it also keeps the device out of Doze, which removes one whole class of confounding behaviour from your testing.
  5. Check the per-app battery settings. Manufacturer power management sits above the platform and varies by brand; the setting names differ, but they are always in the battery section for that specific app.
  6. Decide whether latency actually matters to you. If the job is a recorded account of what happened, a slow first frame costs you nothing — the file was always going to be there. If the job is glancing at a live picture ten times a day, this is the thing to test before you commit.

Where this leaves the phone-as-camera trade

Here is the honest version. You are running a device whose entire power-management design assumes a battery that must last a day in a pocket, in a role where it sits on a permanent charger and nobody looks at the screen. Most of that design is harmless in the new role. This part is not: the radio was taught to go quiet when nobody is using the device, and Android has methodically removed the ways an app could ask it not to.

That is a real cost, and it is not one you can engineer around from inside an app, because the platform has closed the door on purpose and said why. What you get in exchange is a camera that records locally, serves its own live view over your own network, needs no account, and costs nothing to keep. The trade is a first frame that sometimes takes a moment against a device you already own.

It also means the useful mental model for a phone camera is recorder first, live view second. The recording is the durable artifact; the stream is a convenience with a power-management story attached. If two people need that stream, see Can Two People Watch Your Old-Phone Camera at the Same Time. If you need it from outside the house, How to Watch Your Phone's Camera From Outside Your Home Network covers that path. And for the failure modes that come from outside the phone entirely, What Happens to a Phone Security Camera During a Power Cut or an Internet Outage separates the two that get confused most often.


Background Camera RemoteStream records with the screen off, stores footage locally on the device, and serves a live view from a web server running inside the app — no account, no cloud, no subscription. It is on Google Play at play.google.com/store/apps/details?id=com.superfunicular.digicam, and there is more at superfunicular.com.

Sources

Every quotation above is from these pages, read on 2026-08-22:

Top comments (0)