Battery & Network Optimization
📖 Concept
Battery optimization is critical for user retention. Android's battery management has become increasingly aggressive with each version. Senior engineers must design apps that work within these constraints.
Battery-draining operations:
- Wake locks — Keeping CPU/screen active. Use sparingly with proper timeouts.
- GPS polling — Location updates drain battery significantly. Use fused location provider with appropriate intervals.
- Network polling — Frequent network requests keep the radio active. Batch requests.
- Background services — Long-running services consume CPU. Use WorkManager.
- Alarms — Exact alarms prevent the device from entering Doze. Use inexact when possible.
Android power management features:
- Doze mode (6.0+): When device is stationary and screen off, network/wake locks/alarms are deferred to maintenance windows.
- App Standby Buckets (9.0+): Apps are ranked by usage frequency. Infrequently used apps get fewer resources.
- Background execution limits (8.0+): Background services limited to ~10 minutes. Use Foreground Service or WorkManager.
Network optimization:
- OkHttp connection pooling — Reuse TCP connections. Default: 5 connections, 5 min keepalive.
- HTTP caching — Cache responses using Cache-Control headers. OkHttp supports this natively.
- Compression — Use gzip for request/response bodies.
- Batching — Combine multiple small requests into one batch request.
- Prefetching — Load data before the user needs it, but intelligently (on WiFi, charged).
💻 Code Example
1// Network optimization with OkHttp2@Module3@InstallIn(SingletonComponent::class)4object NetworkModule {5 @Provides6 @Singleton7 fun provideOkHttpClient(@ApplicationContext context: Context): OkHttpClient {8 val cacheDir = File(context.cacheDir, "http_cache")9 val cache = Cache(cacheDir, 50L * 1024 * 1024) // 50MB cache1011 return OkHttpClient.Builder()12 .cache(cache) // Enable HTTP caching13 .addInterceptor(CacheInterceptor()) // Custom cache policy14 .addNetworkInterceptor(HttpLoggingInterceptor())15 .connectionPool(ConnectionPool(5, 5, TimeUnit.MINUTES))16 .build()17 }18}1920// Cache interceptor — serve stale cache when offline21class CacheInterceptor : Interceptor {22 override fun intercept(chain: Interceptor.Chain): Response {23 var request = chain.request()24 // If offline, use cache (up to 7 days old)25 if (!isNetworkAvailable()) {26 request = request.newBuilder()27 .cacheControl(CacheControl.Builder()28 .maxStale(7, TimeUnit.DAYS)29 .build())30 .build()31 }32 return chain.proceed(request)33 }34}3536// Battery-aware sync scheduling37fun scheduleSync(context: Context) {38 val constraints = Constraints.Builder()39 .setRequiredNetworkType(NetworkType.UNMETERED) // WiFi only40 .setRequiresBatteryNotLow(true) // Don't sync on low battery41 .setRequiresCharging(false) // But don't require charging42 .build()4344 val syncWork = PeriodicWorkRequestBuilder<SyncWorker>(45 1, TimeUnit.HOURS, // Repeat hourly46 15, TimeUnit.MINUTES // Flex window47 )48 .setConstraints(constraints)49 .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 10, TimeUnit.MINUTES)50 .build()5152 WorkManager.getInstance(context)53 .enqueueUniquePeriodicWork("sync", ExistingPeriodicWorkPolicy.KEEP, syncWork)54}5556// Location optimization57class LocationTracker @Inject constructor(58 private val fusedClient: FusedLocationProviderClient59) {60 fun startTracking(priority: Priority): Flow<Location> = callbackFlow {61 val request = LocationRequest.Builder(62 if (priority == Priority.HIGH) Priority.PRIORITY_HIGH_ACCURACY63 else Priority.PRIORITY_BALANCED_POWER_ACCURACY,64 if (priority == Priority.HIGH) 5_000L else 30_000L // Interval ms65 ).setMinUpdateDistanceMeters(66 if (priority == Priority.HIGH) 10f else 100f67 ).build()6869 val callback = object : LocationCallback() {70 override fun onLocationResult(result: LocationResult) {71 result.lastLocation?.let { trySend(it) }72 }73 }74 fusedClient.requestLocationUpdates(request, callback, Looper.getMainLooper())75 awaitClose { fusedClient.removeLocationUpdates(callback) }76 }7778 enum class Priority { HIGH, LOW }79}
🏋️ Practice Exercise
Practice:
- Implement HTTP caching with OkHttp and verify cached responses with stale-if-error
- Set up battery-aware WorkManager sync with appropriate constraints
- Profile your app's battery impact using Battery Historian
- Implement a smart prefetching strategy that loads data on WiFi only
- Measure your app's network traffic using Network Profiler and identify redundant calls
⚠️ Common Mistakes
Not using OkHttp's built-in cache — re-fetching data that hasn't changed wastes bandwidth and battery
Using exact alarms for non-time-critical work — exact alarms prevent Doze, use WorkManager instead
Polling with high frequency for location — use geofencing or significant motion triggers when possible
Not batching network requests — each request activates the radio, keeping it awake for 20-30 seconds
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for Battery & Network Optimization. Login to unlock this feature.