Battery Drain in Mobile Apps: Causes and Fixes
Battery drain is the most user-hostile perf issue. Users notice. Reviews name the app. Uninstalls follow. The fix pattern is usually "stop doing work you do not need to do" — but finding which work is
Battery drain is the most user-hostile perf issue. Users notice. Reviews name the app. Uninstalls follow. The fix pattern is usually "stop doing work you do not need to do" — but finding which work is the culprit requires specific tools. This guide covers how to diagnose and fix.
How battery drain shows up
- Android: Settings → Battery → App usage shows your app in top consumers
- iOS: Settings → Battery → shows "Last 10 Days" with foreground/background split
- Reviews: "drains my battery," "hot phone," "turning off when I open it"
- Analytics: session length drops, then uninstalls climb
Common causes
1. Wakelocks held too long
A wakelock prevents CPU sleep. Intended for short background work. Forgotten wakelocks drain the battery fast.
Diagnosis: adb shell dumpsys power | grep "wake locks" — your app should appear briefly, not for hours.
Fix: always release in finally. Use PARTIAL_WAKE_LOCK only for the minimum window. Prefer WorkManager for scheduled background work.
2. Excessive network polling
Polling the server every 30 seconds keeps the radio warm. Radio state transitions are expensive.
Fix:
- Use push for server-initiated updates (FCM / APNs)
- For polling, use exponential backoff
- Batch requests — send 5 small updates every 5 minutes, not 1 every minute
3. Location updates too frequent
requestLocationUpdates(minTime = 0) — GPS on continuously. Catastrophic.
Fix: Match location precision to need. FUSED_LOCATION_PROVIDER with PRIORITY_BALANCED_POWER_ACCURACY for most uses. Only fine/high accuracy when user is actively using a map or navigation.
4. Background services always on
A foreground service that was supposed to be short-lived and stayed running. Or background service doing work that could be scheduled.
Fix: WorkManager for deferrable work. Foreground service only for genuinely in-progress user tasks (download, playback, nav).
5. Excessive screen redraws
60fps animation when static content will do. Video decoder running on a paused video. OpenGL overdraw.
Fix: Android Studio GPU profiler shows overdraw (red = 4x+ overdraw). Reduce by removing unused backgrounds, avoiding nested opaque containers.
6. Bluetooth / Wi-Fi scans
Continuous scanning drains the radio.
Fix: Scan only when user-initiated or event-triggered (geofence enter). On Android, BluetoothLeScanner with SCAN_MODE_LOW_POWER.
7. Sensor subscriptions
Accelerometer / gyro at SENSOR_DELAY_FASTEST when SENSOR_DELAY_NORMAL would do.
Fix: Match rate to need. Unregister when the feature is not active.
8. CPU-bound work on main thread
Not always a battery issue directly, but sustained high CPU drains battery. A tight loop on main thread for image processing is a common culprit.
Fix: Move to background. Use optimized libraries (RenderScript deprecated, Vulkan or ML Kit for image work).
Diagnostics
Android Battery Historian
adb shell dumpsys batterystats --reset
# Use the app
adb bugreport bugreport.zip
Run the zip through Battery Historian web tool. Timeline shows wakelocks, radio usage, CPU, and a per-app drain score.
Android Studio Energy Profiler
Runs during Profiler session. Shows CPU, network, location, wakelock events. Low/Medium/High categorization.
iOS Energy Log
Xcode → Organizer → Energy. Shows per-app energy consumption from real users (via opt-in telemetry).
Accubattery / GSam (third-party)
User-facing apps that give detailed per-app drain. Useful for reproducing user complaints.
Fixes that move the number
Switch polling to push: 10-30% drain reduction if polling was frequent.
Remove unused wakelocks: 5-15% if any were held unnecessarily.
Batch network calls: 5-10%.
Downgrade location accuracy when not actively used: 10-25%.
Efficient image loading: 3-8%.
Foreground service → WorkManager: 5-15% for apps that over-used foreground.
Testing battery drain
Controlled test
Charged to 100%, screen off, app in background, measured over 8 hours overnight. Compare app-included drain to baseline (same test without app running).
Real-user feedback
Firebase Performance Monitoring or your own telemetry — battery level at session start, session end. Aggregate across devices.
How SUSA covers battery
SUSA's performance monitor samples battery level during exploration. A 10-step session that drains > 2% on a fully charged phone is a red flag. Sustained CPU and network activity that should be idle flags wakelock / poll-too-often suspicion. The business_professional persona (expects efficient flows) surfaces UX friction; the supporting performance data flags the battery cost of that friction.
susatest-agent test myapp.apk --persona curious --steps 200
# Report includes battery_delta, sustained_cpu_pct, network_calls_per_min
Fix order by ROI
- Identify your worst offender (polling, wakelock, location, sensor)
- Add telemetry to confirm in production
- Implement fix; validate locally
- Ship; measure drain before/after on a sample of users
- Repeat with next offender
Battery is solvable. Most apps can cut drain 30-50% in one focused week of engineering. The ROI is huge — battery affects reviews, retention, and platform ranking in ways that compound.
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free