Battery Optimization for Mobile Applications
Introduction to Mobile Battery Management
Battery optimization is a critical aspect of mobile application development that directly impacts user experience and app retention. Modern mobile operating systems implement sophisticated power management systems, and applications must work within these constraints while providing optimal functionality.
Battery Management Architecture
Platform-Specific Battery Optimization
Android Battery Management
Battery State Monitoring
class BatteryOptimizationManager(private val context: Context) {
private val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
private val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
Intent.ACTION_BATTERY_CHANGED -> handleBatteryChanged(intent)
Intent.ACTION_POWER_CONNECTED -> handlePowerConnected()
Intent.ACTION_POWER_DISCONNECTED -> handlePowerDisconnected()
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED -> handlePowerSaveModeChanged()
}
}
}
fun initialize() {
val filter = IntentFilter().apply {
addAction(Intent.ACTION_BATTERY_CHANGED)
addAction(Intent.ACTION_POWER_CONNECTED)
addAction(Intent.ACTION_POWER_DISCONNECTED)
addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
}
context.registerReceiver(batteryReceiver, filter)
}
private fun handleBatteryChanged(intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
val batteryPct = level * 100 / scale.toFloat()
val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL
val health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, -1)
val temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1) / 10.0
updateBatteryOptimization(
BatteryState(
level = batteryPct,
isCharging = isCharging,
health = health,
temperature = temperature
)
)
}
private fun updateBatteryOptimization(batteryState: BatteryState) {
when {
batteryState.level < 15 -> enableUltraLowPowerMode()
batteryState.level < 30 -> enableLowPowerMode()
batteryState.level < 50 -> enableBalancedMode()
else -> enableNormalMode()
}
if (powerManager.isPowerSaveMode) {
enableSystemPowerSaveOptimizations()
}
// Thermal throttling
if (batteryState.temperature > 40) { // 40°C
enableThermalThrottling()
}
}
private fun enableUltraLowPowerMode() {
// Most aggressive power saving
BackgroundTaskManager.pauseNonCriticalTasks()
NetworkManager.enableDataSavingMode()
UIManager.reduceAnimations()
LocationManager.disableLocationTracking()
CacheManager.clearNonEssentialCaches()
// Reduce CPU frequency if possible
reduceBackgroundActivity(0.1f) // 10% of normal activity
}
private fun enableLowPowerMode() {
// Significant power saving
BackgroundTaskManager.limitBackgroundTasks()
NetworkManager.enableRequestCoalescing()
UIManager.reduceRefreshRate()
LocationManager.enableLowPowerLocationMode()
reduceBackgroundActivity(0.3f) // 30% of normal activity
}
private fun enableBalancedMode() {
// Moderate power saving
BackgroundTaskManager.enableIntelligentScheduling()
NetworkManager.optimizeNetworkCalls()
UIManager.enableSmartRefresh()
reduceBackgroundActivity(0.7f) // 70% of normal activity
}
private fun enableNormalMode() {
// Full functionality
BackgroundTaskManager.enableAllTasks()
NetworkManager.enableFullNetworking()
UIManager.enableFullAnimations()
LocationManager.enableFullLocationTracking()
reduceBackgroundActivity(1.0f) // 100% normal activity
}
private fun reduceBackgroundActivity(ratio: Float) {
SchedulerManager.setActivityRatio(ratio)
TimerManager.adjustTimerIntervals(ratio)
WorkManager.setBackgroundWorkRatio(ratio)
}
}
data class BatteryState(
val level: Float,
val isCharging: Boolean,
val health: Int,
val temperature: Double
)
Background Task Optimization
class BackgroundTaskOptimizer {
private val taskQueue = PriorityQueue<OptimizedTask>(compareBy { it.priority })
private val executionLimiter = ExecutionLimiter()
enum class TaskPriority {
CRITICAL, // User-initiated, immediate
HIGH, // Important but can be delayed
MEDIUM, // Background sync, prefetching
LOW, // Analytics, cleanup
DEFERRED // Non-essential maintenance
}
fun scheduleTask(task: OptimizedTask) {
// Check battery constraints
if (!canExecuteTask(task)) {
deferTask(task)
return
}
// Check execution limits
if (!executionLimiter.canExecute(task)) {
queueTask(task)
return
}
executeTask(task)
}
private fun canExecuteTask(task: OptimizedTask): Boolean {
val batteryLevel = getBatteryLevel()
val isPowerSaveMode = isPowerSaveMode()
val isCharging = isCharging()
return when (task.priority) {
TaskPriority.CRITICAL -> true
TaskPriority.HIGH -> batteryLevel > 15 || isCharging
TaskPriority.MEDIUM -> (batteryLevel > 30 && !isPowerSaveMode) || isCharging
TaskPriority.LOW -> (batteryLevel > 50 && !isPowerSaveMode) || isCharging
TaskPriority.DEFERRED -> isCharging && batteryLevel > 80
}
}
private fun executeTask(task: OptimizedTask) {
CoroutineScope(Dispatchers.Default).launch {
try {
// Monitor resource usage during execution
val resourceMonitor = ResourceMonitor()
resourceMonitor.startMonitoring()
// Execute with timeout
withTimeout(task.maxExecutionTime) {
task.execute()
}
val resourceUsage = resourceMonitor.getUsage()
updateTaskStatistics(task, resourceUsage)
} catch (e: Exception) {
handleTaskFailure(task, e)
}
}
}
private class ExecutionLimiter {
private val executionCounts = mutableMapOf<TaskPriority, Int>()
private val resetTimer = Timer()
init {
// Reset execution counts every hour
resetTimer.scheduleAtFixedRate(object : TimerTask() {
override fun run() {
executionCounts.clear()
}
}, 0, 3600000) // 1 hour
}
fun canExecute(task: OptimizedTask): Boolean {
val currentCount = executionCounts[task.priority] ?: 0
val limit = getExecutionLimit(task.priority)
return currentCount < limit
}
private fun getExecutionLimit(priority: TaskPriority): Int {
return when (priority) {
TaskPriority.CRITICAL -> Int.MAX_VALUE
TaskPriority.HIGH -> 100
TaskPriority.MEDIUM -> 50
TaskPriority.LOW -> 20
TaskPriority.DEFERRED -> 5
}
}
}
}
data class OptimizedTask(
val id: String,
val priority: BackgroundTaskOptimizer.TaskPriority,
val maxExecutionTime: Long,
val requiredResources: Set<Resource>,
val execute: suspend () -> Unit
)
enum class Resource {
NETWORK,
GPS,
CAMERA,
MICROPHONE,
STORAGE,
COMPUTE
}
iOS Battery Optimization
Power Management Implementation
import UIKit
import Foundation
class BatteryOptimizationManager: NSObject {
private let processInfo = ProcessInfo.processInfo
private var batteryMonitoringTimer: Timer?
private var currentPowerState: PowerState = .normal
enum PowerState {
case normal
case balanced
case lowPower
case critical
}
override init() {
super.init()
setupBatteryMonitoring()
}
private func setupBatteryMonitoring() {
UIDevice.current.isBatteryMonitoringEnabled = true
NotificationCenter.default.addObserver(
self,
selector: #selector(batteryLevelChanged),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(batteryStateChanged),
name: UIDevice.batteryStateDidChangeNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(powerModeChanged),
name: .NSProcessInfoPowerStateDidChange,
object: nil
)
// Start periodic monitoring
startPeriodicMonitoring()
}
private func startPeriodicMonitoring() {
batteryMonitoringTimer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { _ in
self.evaluatePowerState()
}
}
@objc private func batteryLevelChanged() {
evaluatePowerState()
}
@objc private func batteryStateChanged() {
evaluatePowerState()
}
@objc private func powerModeChanged() {
evaluatePowerState()
}
private func evaluatePowerState() {
let batteryLevel = UIDevice.current.batteryLevel
let batteryState = UIDevice.current.batteryState
let isLowPowerMode = processInfo.isLowPowerModeEnabled
let thermalState = processInfo.thermalState
let newPowerState = determinePowerState(
batteryLevel: batteryLevel,
batteryState: batteryState,
isLowPowerMode: isLowPowerMode,
thermalState: thermalState
)
if newPowerState != currentPowerState {
currentPowerState = newPowerState
applyPowerOptimizations(newPowerState)
}
}
private func determinePowerState(
batteryLevel: Float,
batteryState: UIDevice.BatteryState,
isLowPowerMode: Bool,
thermalState: ProcessInfo.ThermalState
) -> PowerState {
// Critical conditions
if batteryLevel < 0.1 || thermalState == .critical {
return .critical
}
// Low power conditions
if isLowPowerMode || batteryLevel < 0.2 || thermalState == .serious {
return .lowPower
}
// Balanced conditions
if batteryLevel < 0.5 || thermalState == .fair {
return .balanced
}
return .normal
}
private func applyPowerOptimizations(_ powerState: PowerState) {
switch powerState {
case .critical:
applyCriticalOptimizations()
case .lowPower:
applyLowPowerOptimizations()
case .balanced:
applyBalancedOptimizations()
case .normal:
applyNormalOptimizations()
}
}
private func applyCriticalOptimizations() {
// Suspend all non-essential operations
BackgroundTaskManager.shared.suspendAllTasks()
NetworkManager.shared.enableUltraDataSaving()
LocationManager.shared.disableLocationTracking()
AnimationManager.shared.disableAnimations()
// Reduce screen brightness
UIScreen.main.brightness = max(UIScreen.main.brightness * 0.5, 0.1)
// Minimize refresh rates
if #available(iOS 15.0, *) {
// Request lower refresh rate
UIApplication.shared.windows.first?.rootViewController?.view.preferredFramesPerSecond = 30
}
}
private func applyLowPowerOptimizations() {
BackgroundTaskManager.shared.limitBackgroundTasks()
NetworkManager.shared.enableRequestCoalescing()
LocationManager.shared.enableLowPowerMode()
AnimationManager.shared.reduceAnimations()
// Reduce background app refresh
if #available(iOS 14.0, *) {
// Minimize background processing
}
}
private func applyBalancedOptimizations() {
BackgroundTaskManager.shared.enableIntelligentScheduling()
NetworkManager.shared.optimizeNetworkUsage()
LocationManager.shared.enableBalancedMode()
AnimationManager.shared.enableSmartAnimations()
}
private func applyNormalOptimizations() {
BackgroundTaskManager.shared.enableAllTasks()
NetworkManager.shared.enableFullNetworking()
LocationManager.shared.enableFullTracking()
AnimationManager.shared.enableFullAnimations()
}
}
// Battery-aware background task scheduling
class BatteryAwareTaskScheduler {
private var scheduledTasks: [String: BGTask] = [:]
func scheduleTask(
identifier: String,
earliestBeginDate: Date? = nil,
requiresNetworkConnectivity: Bool = false,
requiresExternalPower: Bool = false
) {
let request: BGTaskRequest
if requiresExternalPower {
// Use BGAppRefreshTaskRequest for power-dependent tasks
let appRefreshRequest = BGAppRefreshTaskRequest(identifier: identifier)
appRefreshRequest.earliestBeginDate = earliestBeginDate
request = appRefreshRequest
} else {
// Use BGProcessingTaskRequest for general background tasks
let processingRequest = BGProcessingTaskRequest(identifier: identifier)
processingRequest.requiresNetworkConnectivity = requiresNetworkConnectivity
processingRequest.requiresExternalPower = requiresExternalPower
processingRequest.earliestBeginDate = earliestBeginDate
request = processingRequest
}
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule task: \(error)")
}
}
func handleBackgroundTask(_ task: BGTask) {
// Schedule the next iteration
scheduleTask(identifier: task.identifier)
// Create an operation queue for the task
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
// Add the task operation
let operation = createTaskOperation(for: task)
queue.addOperation(operation)
// Handle task expiration
task.expirationHandler = {
queue.cancelAllOperations()
task.setTaskCompleted(success: false)
}
// Notify when the task is complete
operation.completionBlock = {
task.setTaskCompleted(success: !operation.isCancelled)
}
}
private func createTaskOperation(for task: BGTask) -> Operation {
return BlockOperation {
// Perform the background work
self.performBackgroundWork(for: task)
}
}
private func performBackgroundWork(for task: BGTask) {
// Check battery level before proceeding
let batteryLevel = UIDevice.current.batteryLevel
let isCharging = UIDevice.current.batteryState == .charging
if batteryLevel < 0.2 && !isCharging {
// Skip non-critical tasks on low battery
return
}
// Perform the actual work based on task type
switch task.identifier {
case "com.app.background-sync":
performBackgroundSync()
case "com.app.data-cleanup":
performDataCleanup()
case "com.app.cache-preload":
if batteryLevel > 0.5 || isCharging {
performCachePreload()
}
default:
break
}
}
private func performBackgroundSync() {
// Implement background sync with battery awareness
}
private func performDataCleanup() {
// Implement data cleanup
}
private func performCachePreload() {
// Implement cache preloading only when battery allows
}
}
React Native Battery Optimization
Cross-Platform Battery Management
import { DeviceEventEmitter, NativeModules, Platform } from 'react-native';
import DeviceInfo from 'react-native-device-info';
interface BatteryInfo {
level: number;
isCharging: boolean;
isLowPowerMode?: boolean;
}
class BatteryOptimizationService {
private batteryInfo: BatteryInfo = { level: 1, isCharging: false };
private optimizationLevel: 'normal' | 'balanced' | 'aggressive' = 'normal';
private listeners: Set<(info: BatteryInfo) => void> = new Set();
async initialize(): Promise<void> {
// Get initial battery info
await this.updateBatteryInfo();
// Set up battery monitoring
this.setupBatteryMonitoring();
// Start periodic checks
this.startPeriodicMonitoring();
}
private async updateBatteryInfo(): Promise<void> {
try {
const [level, isCharging] = await Promise.all([
DeviceInfo.getBatteryLevel(),
DeviceInfo.isBatteryCharging(),
]);
let isLowPowerMode = false;
if (Platform.OS === 'ios') {
isLowPowerMode = await DeviceInfo.isPowerSaveMode();
}
this.batteryInfo = {
level,
isCharging,
isLowPowerMode,
};
this.updateOptimizationLevel();
this.notifyListeners();
} catch (error) {
console.error('Failed to update battery info:', error);
}
}
private setupBatteryMonitoring(): void {
if (Platform.OS === 'android') {
// Android battery monitoring
DeviceEventEmitter.addListener('batteryChanged', (batteryInfo) => {
this.batteryInfo = {
level: batteryInfo.level / 100,
isCharging: batteryInfo.isCharging,
};
this.updateOptimizationLevel();
this.notifyListeners();
});
}
// iOS monitoring through native module
if (Platform.OS === 'ios') {
DeviceEventEmitter.addListener('batteryStateChanged', (batteryInfo) => {
this.batteryInfo = batteryInfo;
this.updateOptimizationLevel();
this.notifyListeners();
});
}
}
private startPeriodicMonitoring(): void {
setInterval(() => {
this.updateBatteryInfo();
}, 60000); // Check every minute
}
private updateOptimizationLevel(): void {
const { level, isCharging, isLowPowerMode } = this.batteryInfo;
if (level < 0.15 || isLowPowerMode) {
this.optimizationLevel = 'aggressive';
} else if (level < 0.5 && !isCharging) {
this.optimizationLevel = 'balanced';
} else {
this.optimizationLevel = 'normal';
}
this.applyOptimizations();
}
private applyOptimizations(): void {
switch (this.optimizationLevel) {
case 'aggressive':
this.applyAggressiveOptimizations();
break;
case 'balanced':
this.applyBalancedOptimizations();
break;
case 'normal':
this.applyNormalOptimizations();
break;
}
}
private applyAggressiveOptimizations(): void {
// Reduce background sync frequency
BackgroundSyncManager.setUpdateInterval(300000); // 5 minutes
// Disable non-essential features
LocationService.enablePowerSaveMode();
AnimationService.disableAnimations();
// Reduce image quality
ImageCacheManager.setQuality('low');
// Minimize network requests
NetworkManager.enableAggressiveCoalescing();
}
private applyBalancedOptimizations(): void {
// Moderate background sync
BackgroundSyncManager.setUpdateInterval(120000); // 2 minutes
// Reduce location accuracy
LocationService.enableBalancedMode();
// Optimize animations
AnimationService.enableLightAnimations();
// Medium image quality
ImageCacheManager.setQuality('medium');
// Enable request coalescing
NetworkManager.enableRequestCoalescing();
}
private applyNormalOptimizations(): void {
// Normal operation
BackgroundSyncManager.setUpdateInterval(30000); // 30 seconds
LocationService.enableFullAccuracy();
AnimationService.enableFullAnimations();
ImageCacheManager.setQuality('high');
NetworkManager.enableFullNetworking();
}
addBatteryListener(listener: (info: BatteryInfo) => void): void {
this.listeners.add(listener);
}
removeBatteryListener(listener: (info: BatteryInfo) => void): void {
this.listeners.delete(listener);
}
private notifyListeners(): void {
this.listeners.forEach(listener => listener(this.batteryInfo));
}
getBatteryInfo(): BatteryInfo {
return { ...this.batteryInfo };
}
getOptimizationLevel(): string {
return this.optimizationLevel;
}
}
// Network optimization based on battery
class BatteryAwareNetworkManager {
private requestQueue: NetworkRequest[] = [];
private batchTimer: NodeJS.Timeout | null = null;
private batteryService: BatteryOptimizationService;
constructor(batteryService: BatteryOptimizationService) {
this.batteryService = batteryService;
this.batteryService.addBatteryListener(this.onBatteryChanged.bind(this));
}
private onBatteryChanged(batteryInfo: BatteryInfo): void {
if (batteryInfo.level < 0.2 && !batteryInfo.isCharging) {
// Enable aggressive request batching
this.enableAggressiveBatching();
} else if (batteryInfo.level < 0.5) {
// Enable moderate batching
this.enableModerateBatching();
} else {
// Normal operation
this.enableNormalOperation();
}
}
private enableAggressiveBatching(): void {
// Batch requests for 10 seconds
this.setBatchInterval(10000);
}
private enableModerateBatching(): void {
// Batch requests for 3 seconds
this.setBatchInterval(3000);
}
private enableNormalOperation(): void {
// Minimal batching (1 second)
this.setBatchInterval(1000);
}
private setBatchInterval(interval: number): void {
if (this.batchTimer) {
clearInterval(this.batchTimer);
}
this.batchTimer = setInterval(() => {
this.processBatchedRequests();
}, interval);
}
queueRequest(request: NetworkRequest): void {
this.requestQueue.push(request);
// Process immediately if not in power save mode
const batteryInfo = this.batteryService.getBatteryInfo();
if (batteryInfo.level > 0.5 || batteryInfo.isCharging) {
this.processBatchedRequests();
}
}
private async processBatchedRequests(): Promise<void> {
if (this.requestQueue.length === 0) return;
const batch = [...this.requestQueue];
this.requestQueue = [];
// Group similar requests
const groupedRequests = this.groupSimilarRequests(batch);
for (const group of groupedRequests) {
await this.executeBatchRequest(group);
}
}
private groupSimilarRequests(requests: NetworkRequest[]): NetworkRequest[][] {
const groups = new Map<string, NetworkRequest[]>();
requests.forEach(request => {
const key = `${request.method}-${request.baseUrl}`;
if (!groups.has(key)) {
groups.set(key, []);
}
groups.get(key)!.push(request);
});
return Array.from(groups.values());
}
private async executeBatchRequest(requests: NetworkRequest[]): Promise<void> {
try {
if (requests.length === 1) {
await requests[0].execute();
} else {
// Execute as batch request
await this.executeBatch(requests);
}
} catch (error) {
console.error('Batch request failed:', error);
// Retry individual requests
for (const request of requests) {
this.queueRequest(request);
}
}
}
private async executeBatch(requests: NetworkRequest[]): Promise<void> {
// Implementation for batch API call
const batchPayload = {
requests: requests.map(req => ({
id: req.id,
method: req.method,
url: req.url,
data: req.data,
})),
};
const response = await fetch('/api/batch', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(batchPayload),
});
const results = await response.json();
// Process batch results
results.responses.forEach((result: any) => {
const request = requests.find(req => req.id === result.id);
if (request) {
if (result.success) {
request.resolve(result.data);
} else {
request.reject(new Error(result.error));
}
}
});
}
}
interface NetworkRequest {
id: string;
method: string;
baseUrl: string;
url: string;
data?: any;
execute: () => Promise<any>;
resolve: (data: any) => void;
reject: (error: Error) => void;
}
Flutter Battery Optimization
Comprehensive Battery Management
import 'package:battery_plus/battery_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'dart:async';
import 'dart:io';
enum PowerState {
normal,
balanced,
lowPower,
critical,
}
class BatteryOptimizationService {
static final BatteryOptimizationService _instance = BatteryOptimizationService._internal();
factory BatteryOptimizationService() => _instance;
BatteryOptimizationService._internal();
final Battery _battery = Battery();
PowerState _currentPowerState = PowerState.normal;
StreamSubscription<BatteryState>? _batterySubscription;
Timer? _batteryCheckTimer;
final StreamController<PowerState> _powerStateController = StreamController<PowerState>.broadcast();
Stream<PowerState> get powerStateStream => _powerStateController.stream;
int _batteryLevel = 100;
bool _isCharging = false;
bool _isLowPowerMode = false;
Future<void> initialize() async {
await _updateBatteryInfo();
_startBatteryMonitoring();
_startPeriodicChecks();
}
void dispose() {
_batterySubscription?.cancel();
_batteryCheckTimer?.cancel();
_powerStateController.close();
}
Future<void> _updateBatteryInfo() async {
try {
_batteryLevel = await _battery.batteryLevel;
final batteryState = await _battery.batteryState;
_isCharging = batteryState == BatteryState.charging;
if (Platform.isIOS) {
_isLowPowerMode = await _battery.isInBatterySaveMode;
}
_evaluatePowerState();
} catch (e) {
print('Failed to update battery info: $e');
}
}
void _startBatteryMonitoring() {
_batterySubscription = _battery.onBatteryStateChanged.listen((BatteryState state) {
_isCharging = state == BatteryState.charging;
_evaluatePowerState();
});
}
void _startPeriodicChecks() {
_batteryCheckTimer = Timer.periodic(const Duration(minutes: 1), (_) {
_updateBatteryInfo();
});
}
void _evaluatePowerState() {
PowerState newState;
if (_batteryLevel < 10 || (_isLowPowerMode && _batteryLevel < 20)) {
newState = PowerState.critical;
} else if (_batteryLevel < 20 || _isLowPowerMode) {
newState = PowerState.lowPower;
} else if (_batteryLevel < 50 && !_isCharging) {
newState = PowerState.balanced;
} else {
newState = PowerState.normal;
}
if (newState != _currentPowerState) {
_currentPowerState = newState;
_powerStateController.add(_currentPowerState);
_applyOptimizations(_currentPowerState);
}
}
void _applyOptimizations(PowerState state) {
switch (state) {
case PowerState.critical:
_applyCriticalOptimizations();
break;
case PowerState.lowPower:
_applyLowPowerOptimizations();
break;
case PowerState.balanced:
_applyBalancedOptimizations();
break;
case PowerState.normal:
_applyNormalOptimizations();
break;
}
}
void _applyCriticalOptimizations() {
// Suspend all non-essential operations
BackgroundTaskManager.instance.suspendAllTasks();
NetworkManager.instance.enableUltraDataSaving();
LocationService.instance.disableLocationTracking();
// Reduce refresh rates
FrameRateManager.instance.setTargetFrameRate(30);
// Clear caches
CacheManager.instance.clearNonEssentialCaches();
}
void _applyLowPowerOptimizations() {
BackgroundTaskManager.instance.limitBackgroundTasks();
NetworkManager.instance.enableRequestCoalescing();
LocationService.instance.enableLowPowerMode();
// Reduce animation duration
AnimationManager.instance.setDurationMultiplier(0.5);
}
void _applyBalancedOptimizations() {
BackgroundTaskManager.instance.enableIntelligentScheduling();
NetworkManager.instance.optimizeNetworkUsage();
LocationService.instance.enableBalancedMode();
AnimationManager.instance.setDurationMultiplier(0.8);
}
void _applyNormalOptimizations() {
BackgroundTaskManager.instance.enableAllTasks();
NetworkManager.instance.enableFullNetworking();
LocationService.instance.enableFullTracking();
FrameRateManager.instance.setTargetFrameRate(60);
AnimationManager.instance.setDurationMultiplier(1.0);
}
PowerState get currentPowerState => _currentPowerState;
int get batteryLevel => _batteryLevel;
bool get isCharging => _isCharging;
bool get isLowPowerMode => _isLowPowerMode;
}
// Battery-aware widget that adapts its behavior
class BatteryAwareWidget extends StatefulWidget {
final Widget child;
final Widget? lowPowerChild;
final Widget? criticalPowerChild;
const BatteryAwareWidget({
Key? key,
required this.child,
this.lowPowerChild,
this.criticalPowerChild,
}) : super(key: key);
@override
_BatteryAwareWidgetState createState() => _BatteryAwareWidgetState();
}
class _BatteryAwareWidgetState extends State<BatteryAwareWidget> {
late StreamSubscription<PowerState> _powerStateSubscription;
PowerState _currentPowerState = PowerState.normal;
@override
void initState() {
super.initState();
_currentPowerState = BatteryOptimizationService().currentPowerState;
_powerStateSubscription = BatteryOptimizationService()
.powerStateStream
.listen((PowerState state) {
if (mounted) {
setState(() {
_currentPowerState = state;
});
}
});
}
@override
void dispose() {
_powerStateSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
switch (_currentPowerState) {
case PowerState.critical:
return widget.criticalPowerChild ??
widget.lowPowerChild ??
_buildSimplifiedWidget();
case PowerState.lowPower:
return widget.lowPowerChild ?? _buildOptimizedWidget();
case PowerState.balanced:
return _buildOptimizedWidget();
case PowerState.normal:
return widget.child;
}
}
Widget _buildSimplifiedWidget() {
// Return minimal UI for critical battery state
return Container(
padding: const EdgeInsets.all(16),
child: const Text(
'Low Battery Mode',
style: TextStyle(fontSize: 16),
),
);
}
Widget _buildOptimizedWidget() {
// Return optimized version of the widget
return AnimatedContainer(
duration: const Duration(milliseconds: 200),
child: widget.child,
);
}
}
// Background task manager with battery awareness
class BatteryAwareTaskManager {
static final BatteryAwareTaskManager _instance = BatteryAwareTaskManager._internal();
factory BatteryAwareTaskManager() => _instance;
BatteryAwareTaskManager._internal();
final List<BatteryAwareTask> _tasks = [];
Timer? _executionTimer;
void initialize() {
BatteryOptimizationService().powerStateStream.listen(_onPowerStateChanged);
_startTaskExecution();
}
void scheduleTask(BatteryAwareTask task) {
_tasks.add(task);
}
void _onPowerStateChanged(PowerState state) {
switch (state) {
case PowerState.critical:
_pauseAllTasks();
break;
case PowerState.lowPower:
_pauseLowPriorityTasks();
break;
case PowerState.balanced:
_resumeHighPriorityTasks();
break;
case PowerState.normal:
_resumeAllTasks();
break;
}
}
void _startTaskExecution() {
_executionTimer = Timer.periodic(const Duration(seconds: 10), (_) {
_executePendingTasks();
});
}
void _executePendingTasks() {
final powerState = BatteryOptimizationService().currentPowerState;
final isCharging = BatteryOptimizationService().isCharging;
for (final task in _tasks.where((t) => t.shouldExecute(powerState, isCharging))) {
task.execute();
}
}
void _pauseAllTasks() {
for (final task in _tasks) {
task.pause();
}
}
void _pauseLowPriorityTasks() {
for (final task in _tasks.where((t) => t.priority == TaskPriority.low)) {
task.pause();
}
}
void _resumeHighPriorityTasks() {
for (final task in _tasks.where((t) => t.priority == TaskPriority.high)) {
task.resume();
}
}
void _resumeAllTasks() {
for (final task in _tasks) {
task.resume();
}
}
}
enum TaskPriority {
high,
medium,
low,
}
abstract class BatteryAwareTask {
final String id;
final TaskPriority priority;
bool _isPaused = false;
BatteryAwareTask({required this.id, required this.priority});
bool shouldExecute(PowerState powerState, bool isCharging) {
if (_isPaused) return false;
switch (priority) {
case TaskPriority.high:
return true;
case TaskPriority.medium:
return powerState != PowerState.critical || isCharging;
case TaskPriority.low:
return powerState == PowerState.normal || isCharging;
}
}
void pause() => _isPaused = true;
void resume() => _isPaused = false;
Future<void> execute();
}
Network Optimization for Battery Life
Intelligent Request Management
class BatteryAwareNetworkOptimizer {
private requestQueue: PriorityQueue<NetworkRequest> = new PriorityQueue();
private batchingEnabled = false;
private compressionEnabled = false;
private cacheAggressiveness = 'normal';
updateOptimizationLevel(batteryLevel: number, isCharging: boolean): void {
if (batteryLevel < 0.15 && !isCharging) {
this.enableUltraOptimization();
} else if (batteryLevel < 0.3) {
this.enableAggressiveOptimization();
} else if (batteryLevel < 0.6) {
this.enableModerateOptimization();
} else {
this.enableNormalOperation();
}
}
private enableUltraOptimization(): void {
this.batchingEnabled = true;
this.compressionEnabled = true;
this.cacheAggressiveness = 'ultra';
// Delay non-critical requests
this.setRequestDelay('low', 60000); // 1 minute
this.setRequestDelay('medium', 30000); // 30 seconds
// Enable request deduplication
this.enableRequestDeduplication(true);
}
private enableAggressiveOptimization(): void {
this.batchingEnabled = true;
this.compressionEnabled = true;
this.cacheAggressiveness = 'aggressive';
this.setRequestDelay('low', 30000); // 30 seconds
this.setRequestDelay('medium', 10000); // 10 seconds
this.enableRequestDeduplication(true);
}
private enableModerateOptimization(): void {
this.batchingEnabled = true;
this.compressionEnabled = false;
this.cacheAggressiveness = 'moderate';
this.setRequestDelay('low', 10000); // 10 seconds
this.clearRequestDelay('medium');
this.enableRequestDeduplication(false);
}
private enableNormalOperation(): void {
this.batchingEnabled = false;
this.compressionEnabled = false;
this.cacheAggressiveness = 'normal';
this.clearAllRequestDelays();
this.enableRequestDeduplication(false);
}
async makeRequest(request: NetworkRequest): Promise<any> {
// Check cache first based on aggressiveness
const cacheResult = await this.checkCache(request);
if (cacheResult) {
return cacheResult;
}
// Apply request optimizations
const optimizedRequest = this.optimizeRequest(request);
if (this.batchingEnabled && request.priority !== 'critical') {
return this.queueForBatch(optimizedRequest);
}
return this.executeRequest(optimizedRequest);
}
private optimizeRequest(request: NetworkRequest): NetworkRequest {
const optimized = { ...request };
// Enable compression if configured
if (this.compressionEnabled) {
optimized.headers = {
...optimized.headers,
'Accept-Encoding': 'gzip, deflate, br',
};
}
// Reduce image quality for image requests
if (this.isImageRequest(request)) {
optimized.params = {
...optimized.params,
quality: this.getImageQuality(),
};
}
return optimized;
}
private getImageQuality(): string {
switch (this.cacheAggressiveness) {
case 'ultra': return 'low';
case 'aggressive': return 'medium';
case 'moderate': return 'medium';
default: return 'high';
}
}
}
Performance Monitoring and Analytics
Battery Usage Analytics
class BatteryUsageAnalytics {
private val powerProfile = PowerProfile(context)
private val batteryStatsManager = context.getSystemService(Context.BATTERY_STATS_SERVICE) as BatteryStatsManager
fun trackBatteryUsage(component: String, startTime: Long, endTime: Long) {
val duration = endTime - startTime
val powerConsumption = estimatePowerConsumption(component, duration)
// Log to analytics
Analytics.track("battery_usage", mapOf(
"component" to component,
"duration_ms" to duration,
"estimated_power_mah" to powerConsumption,
"battery_level_before" to getBatteryLevelAtTime(startTime),
"battery_level_after" to getBatteryLevelAtTime(endTime)
))
}
private fun estimatePowerConsumption(component: String, durationMs: Long): Double {
val powerMah = when (component) {
"cpu" -> powerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE)
"screen" -> powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON)
"wifi" -> powerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
"gps" -> powerProfile.getAveragePower(PowerProfile.POWER_GPS_ON)
"camera" -> powerProfile.getAveragePower(PowerProfile.POWER_CAMERA)
else -> 0.0
}
return powerMah * (durationMs / 3600000.0) // mAh per hour
}
fun generateBatteryReport(): BatteryReport {
val stats = batteryStatsManager.getBatteryUsageStats()
val uidStats = stats.uidBatteryUsageStats
val appUsage = uidStats.find { it.uid == android.os.Process.myUid() }
return BatteryReport(
totalConsumption = appUsage?.consumedPower ?: 0.0,
cpuUsage = appUsage?.cpuTimeMs ?: 0,
backgroundUsage = appUsage?.backgroundTimeMs ?: 0,
foregroundUsage = appUsage?.foregroundActivityTimeMs ?: 0,
recommendations = generateRecommendations(appUsage)
)
}
private fun generateRecommendations(stats: UidBatteryUsageStats?): List<String> {
val recommendations = mutableListOf<String>()
stats?.let { usage ->
if (usage.backgroundTimeMs > usage.foregroundActivityTimeMs * 2) {
recommendations.add("Reduce background activity")
}
if (usage.consumedPower > 100) { // mAh
recommendations.add("Optimize power-intensive operations")
}
}
return recommendations
}
}
data class BatteryReport(
val totalConsumption: Double,
val cpuUsage: Long,
val backgroundUsage: Long,
val foregroundUsage: Long,
val recommendations: List<String>
)
Best Practices and Guidelines
1. Battery State Awareness
- Monitor battery level, charging state, and power save mode
- Adapt app behavior based on current battery conditions
- Implement graceful degradation for low battery scenarios
2. Background Task Optimization
- Use platform-appropriate background task mechanisms
- Implement intelligent task scheduling based on battery state
- Coalesce and batch background operations
3. Network Efficiency
- Implement request coalescing and batching
- Use compression and optimize payload sizes
- Cache aggressively during low battery conditions
4. Resource Management
- Monitor and limit CPU-intensive operations
- Reduce screen brightness and frame rates when needed
- Disable non-essential features during power save mode
5. User Experience
- Provide clear indicators of battery optimization modes
- Allow users to control optimization levels
- Maintain core functionality even in extreme power save scenarios
Conclusion
Effective battery optimization requires a holistic approach that considers all aspects of mobile application behavior. By implementing intelligent power management systems, monitoring battery conditions, and adapting application behavior accordingly, developers can create applications that provide excellent user experience while respecting device battery constraints.
The key to successful battery optimization is proactive monitoring and adaptive behavior that responds to changing power conditions, ensuring applications remain functional and efficient across all battery levels and charging states.