A device battery API helps an application understand the battery of the device running that application. For a website opened on a phone, that means the phone battery. It does not reveal the charge level of a nearby electric vehicle, a connected charging station, or a household battery. Establishing that boundary prevents an attractive dashboard from making a claim its data cannot support.

The useful starting point is a small product decision: what should the application do differently when battery information is available? A quieter animation, an optional reminder, or a less frequent background refresh can be reasonable. Core navigation and saving user work should continue regardless of battery access. Our device battery overview introduces this distinction between local device signals and other battery integrations.

Check capability at runtime

Browser support for the Battery Status API is limited. Do not assume that a modern phone, a particular operating system, or installation as a web app implies support. In supporting implementations, navigator.getBattery() returns a promise for a BatteryManager. Access also depends on the browsing context, including secure context requirements and relevant permissions policy.

Use capability detection at the point of use. A browser name collected earlier is a weak substitute for checking whether the method exists now. Catch failures even after that check: the existence of an interface does not guarantee that the application can use it successfully. Keep an explicit unavailable state in the component rather than substituting a percentage.

For example, this illustrative adapter obtains a single snapshot. It is ordinary browser JavaScript, not a ChargeAPI service endpoint:

async function readDeviceBattery() {
  if (typeof navigator === "undefined" ||
      typeof navigator.getBattery !== "function") {
    return { status: "unavailable" };
  }
  try {
    const battery = await navigator.getBattery();
    return {
      status: "reported",
      level: battery.level,
      charging: battery.charging
    };
  } catch {
    return { status: "unavailable" };
  }
}

The name reported is deliberate. It says that the browser supplied a value, without asserting that your application independently measured a physical battery. A production adapter should also validate the returned shape before passing values to presentation code.

Preserve the meaning of each value

The browser interface represents level as a fraction from zero to one and exposes charging state and time estimates. The W3C Battery Status API specification also describes privacy protections and default values that can resemble a fully charged device when information cannot be reported. Consequently, a successful read is not proof that the device has a battery or that its physical charge was measured accurately.

Keep the original fraction inside your adapter and convert it for display only. Round a displayed percentage consistently. Validate that a numeric value is finite and inside the expected range; do not silently clamp a wildly invalid input into an apparently credible reading. If a time estimate is not finite, render an unknown state rather than a countdown. A changing estimate should be described as an estimate.

Use separate fields for value, availability, and observation time. That structure is more expressive than a single nullable percentage. It lets a screen distinguish unavailable telemetry from an older reading, and lets tests examine each case without reverse engineering a display string. The broader battery data guide applies the same discipline when battery information comes from another system.

Design the feature around optional information

Suppose a document editor offers a battery saving mode. The application can suggest reducing decorative effects after receiving a low reading, while still offering that setting manually to everyone. A user on an unsupported browser then retains the same useful control. This avoids making access to a resource saving feature depend on access to telemetry.

Choose changes that are understandable and reversible. Explain a visible change near the setting that controls it. Avoid repeatedly opening a modal when the same condition remains true. Store the user's preference separately from the latest battery reading, so an explicit choice survives a telemetry update.

For event driven updates, subscribe only while the consuming feature is active and remove listeners during cleanup. Keep the initial read and later updates on the same validation path. Prevent an asynchronous initialization from attaching listeners after its screen has already closed. This lifecycle detail matters in applications where navigation repeatedly mounts and unmounts the same component.

Minimize collection and retention

Battery readings can contribute to fingerprinting when combined with other signals; the W3C specification explicitly addresses this privacy concern. Treat local adaptation as the default design. A page can decide to reduce its own optional work without sending a history of battery readings to a server.

Write down the purpose before adding telemetry to analytics. If the question is whether a battery related feature works, an aggregate count of feature use may answer it better than a stream of percentages attached to persistent identifiers. Remove unnecessary precision, avoid linking unrelated device characteristics, and choose a retention period that matches the actual operational need.

Document what happens when access is unavailable. Privacy choices should not produce misleading warnings such as “your battery is empty.” They should lead to a quiet fallback with ordinary functionality. Make this behavior part of the acceptance criteria, so it remains intact when another engineer refactors the interface.

Choose native integration when the application needs it

Android applications

Android's BatteryManager is a native starting point for battery properties. The Android reference also defines battery related values carried by ACTION_BATTERY_CHANGED. These are platform interfaces, with property availability and behavior that should be checked against the operating system versions and devices you support.

Put Android specific code behind the same application level adapter used by your screens. Normalize supported readings there, and retain an unavailable result for unsupported properties. Do not make a portable model require every field simply because one test phone provides it. Keep platform detail close to the adapter rather than scattering conditional logic throughout the interface.

Apple applications and shared frameworks

For UIKit applications, Apple's UIDevice exposes battery monitoring through properties including isBatteryMonitoringEnabled, batteryLevel, and batteryState. Consult their platform documentation when implementing monitoring and its lifecycle. A framework plugin may wrap these native facilities, but its cross-platform name does not establish identical support or semantics everywhere.

Evaluate a wrapper by inspecting which platforms it actually implements, how it reports unavailable values, and when it starts and stops monitoring. A bridge should expose enough information to distinguish a native failure from a legitimate low battery reading. The developer learning hub provides related guidance on adapters and integration boundaries.

Test transitions and uncertainty

Build fixtures for an unavailable method, a rejected promise, a normal reading, an invalid number, and an update arriving after cleanup. Test a transition into and out of the application's chosen low battery condition. Check that the manual preference remains authoritative and that repeated updates do not generate repeated prompts.

Test on the real browsers and devices your product supports. Include a device where telemetry is unavailable and a page embedded in the context you actually ship. Simulated readings help exercise interface logic, but they do not establish that physical hardware reports the same values or that a feature reduces energy consumption.

Evaluate the feature by its intended outcome. If the goal is to preserve unfinished work, verify the save behavior independently of battery events. If the goal is to reduce optional computation, measure the work performed with the setting enabled. These checks keep the battery signal in its proper role as an input to a useful behavior.

Conclusion

A reliable device battery integration starts with capability detection and an honest unavailable state. Keep browser and native details behind a narrow adapter, interpret reported values cautiously, and collect only what the feature needs. The strongest implementation remains useful when no battery information arrives and makes its battery related behavior easy for the user to understand and control.