Battery Optimization for Background Tasks

Whistl provides continuous protection while minimising battery impact. This technical guide explains iOS Background App Refresh, Android WorkManager, adaptive task scheduling, and how Whistl balances real-time protection with battery efficiency.

The Battery Challenge

Continuous protection requires background processing, which consumes battery:

  • Location monitoring: GPS for venue geofencing
  • Transaction sync: Background fetch for new transactions
  • ML inference: Periodic impulse prediction
  • Network activity: DNS filtering, API calls
  • Biometric sync: HealthKit, Oura data updates

Whistl uses sophisticated optimization to keep battery impact under 7% per day.

iOS Background Execution

iOS provides multiple background execution modes:

Background Modes Used

ModePurposeBudget
Background FetchTransaction sync, model updates~30 seconds, 2-4x/day
Location UpdatesVenue geofencingContinuous (region monitoring)
Remote NotificationsServer-initiated sync~30 seconds per notification
Background ProcessingCritical tasks (iOS 13+)Variable, system-determined

Background Fetch Implementation

import UIKit

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Configure background fetch
        UIApplication.shared.setMinimumBackgroundFetchInterval(
            UIApplication.backgroundFetchIntervalMinimum
        )
        return true
    }
    
    func application(
        _ application: UIApplication,
        performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
    ) {
        let startTime = Date()
        
        Task {
            do {
                // Perform background tasks
                try await syncTransactions()
                try await syncBiometricData()
                try await checkForModelUpdates()
                
                let duration = Date().timeIntervalSince(startTime)
                let result: UIBackgroundFetchResult = duration < 25 ? .newData : .noData
                completionHandler(result)
            } catch {
                completionHandler(.failed)
            }
        }
    }
}

Background Task Scheduling (iOS 13+)

import BackgroundTasks

class BackgroundTaskScheduler {
    static let shared = BackgroundTaskScheduler()
    
    func scheduleTasks() {
        // Schedule background refresh
        let refreshRequest = BGAppRefreshTaskRequest(identifier: "com.whistl.refresh")
        refreshRequest.earliestBeginDate = Date().addingTimeInterval(3600)
        
        try? BGTaskScheduler.shared.submit(refreshRequest)
        
        // Schedule background processing
        let processingRequest = BGProcessingTaskRequest(identifier: "com.whistl.processing")
        processingRequest.earliestBeginDate = Date().addingTimeInterval(3600 * 4)
        processingRequest.requiresExternalPower = false
        processingRequest.requiresNetworkConnectivity = true
        
        try? BGTaskScheduler.shared.submit(processingRequest)
    }
    
    func handleRefresh(task: BGAppRefreshTask) {
        task.expirationHandler = {
            task.setTaskCompleted(success: false)
        }
        
        Task {
            do {
                try await performRefreshTasks()
                task.setTaskCompleted(success: true)
            } catch {
                task.setTaskCompleted(success: false)
            }
            
            scheduleTasks()  // Re-schedule
        }
    }
}

Android Background Execution

Android provides WorkManager for reliable background tasks:

WorkManager Implementation

import androidx.work.*

class BackgroundTaskScheduler(private val context: Context) {
    
    fun scheduleTasks() {
        // Transaction sync - periodic
        val transactionWork = PeriodicWorkRequestBuilder(
            4, TimeUnit.HOURS
        )
            .setConstraints(
                Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .setRequiresBatteryNotLow(true)
                    .build()
            )
            .setBackoffCriteria(
                BackoffPolicy.EXPONENTIAL,
                WorkRequest.MIN_BACKOFF_MILLIS,
                TimeUnit.MILLISECONDS
            )
            .build()
        
        // Model update - daily
        val modelWork = PeriodicWorkRequestBuilder(
            1, TimeUnit.DAYS
        )
            .setConstraints(
                Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.UNMETERED)  // WiFi only
                    .setRequiresCharging(true)
                    .build()
            )
            .build()
        
        // Biometric sync - every 6 hours
        val biometricWork = PeriodicWorkRequestBuilder(
            6, TimeUnit.HOURS
        )
            .setConstraints(
                Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build()
            )
            .build()
        
        WorkManager.getInstance(context).enqueue(
            transactionWork, modelWork, biometricWork
        )
    }
}

Worker Implementation

class TransactionSyncWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {
    
    override suspend fun doWork(): Result {
        return try {
            withTimeout(25 * 60 * 1000) {  // 25 minute timeout
                val syncManager = SyncManager(applicationContext)
                await syncManager.syncTransactions()
                
                Result.success()
            }
        } catch (e: TimeoutCancellationException) {
            Result.retry()
        } catch (e: Exception) {
            if (runAttemptCount >= 3) {
                Result.failure()
            } else {
                Result.retry()
            }
        }
    }
}

Adaptive Task Scheduling

Whistl adjusts background activity based on risk level:

Risk-Based Scheduling

class AdaptiveScheduler {
    func calculateSyncInterval(riskLevel: RiskLevel) -> TimeInterval {
        switch riskLevel {
        case .low:
            return 300  // 5 minutes
        case .elevated:
            return 60   // 1 minute
        case .high:
            return 30   // 30 seconds
        case .critical:
            return 10   // 10 seconds
        }
    }
    
    func calculateLocationUpdateInterval(riskLevel: RiskLevel) -> TimeInterval {
        switch riskLevel {
        case .low:
            return 300  // 5 minutes (significant changes)
        case .elevated:
            return 60   // 1 minute
        case .high:
            return 30   // 30 seconds
        case .critical:
            return 10   // 10 seconds (continuous)
        }
    }
}

Sleep Mode Optimization

class SleepModeOptimizer {
    func isSleepTime() -> Bool {
        let hour = Calendar.current.component(.hour, from: Date())
        return hour >= 23 || hour < 6
    }
    
    func isStationary() -> Bool {
        // Check if device hasn't moved significantly
        return locationManager.distanceFilter > 1000
    }
    
    func getSleepInterval() -> TimeInterval {
        if isSleepTime() && isStationary() {
            return 1800  // 30 minutes during sleep
        }
        return 300  // 5 minutes normal
    }
}

Location Optimization

Geofencing is optimized for battery efficiency:

Region Monitoring vs. Continuous GPS

MethodBattery/HourAccuracyUse Case
Region Monitoring~0.5%100-200mNormal protection
Significant Changes~0.1%500mSleep mode
Continuous GPS~15%5-10mCritical risk only
Adaptive (Whistl)~2-3%50mBalanced approach

Geofence Management

class GeofenceManager {
    private let maxMonitoredRegions = 20  // iOS limit
    
    func updateMonitoredRegions(userLocation: CLLocation) {
        // Get nearby venues
        let nearbyVenues = venueDatabase.getVenues(
            within: 5000,  // 5km radius
            of: userLocation
        )
        
        // Prioritize by risk
        let sortedVenues = nearbyVenues.sorted {
            $0.riskScore > $1.riskScore
        }
        
        // Monitor top 20
        let venuesToMonitor = sortedVenues.prefix(maxMonitoredRegions)
        
        // Update regions
        for venue in venuesToMonitor {
            startMonitoring(venue)
        }
    }
}

Network Optimization

Network activity is batched and deferred:

Request Batching

class NetworkBatcher {
    private var pendingRequests: [APIRequest] = []
    private let maxBatchSize = 10
    private let maxWaitTime: TimeInterval = 30
    
    func queueRequest(_ request: APIRequest) {
        pendingRequests.append(request)
        
        if pendingRequests.count >= maxBatchSize {
            flush()
        } else if pendingRequests.count == 1 {
            // First request - schedule flush
            DispatchQueue.main.asyncAfter(deadline: .now() + maxWaitTime) {
                self.flush()
            }
        }
    }
    
    func flush() {
        guard !pendingRequests.isEmpty else { return }
        
        let batch = pendingRequests
        pendingRequests = []
        
        Task {
            try? await apiClient.sendBatch(batch)
        }
    }
}

WiFi-Preferred Sync

class SyncScheduler {
    func shouldSyncNow(dataType: DataType) -> Bool {
        let networkStatus = NetworkMonitor.shared.status
        
        switch dataType {
        case .transactions:
            // Large data - prefer WiFi
            return networkStatus == .wifi
        case .settings:
            // Small data - any network
            return networkStatus != .offline
        case .modelUpdate:
            // Very large - WiFi + charging
            return networkStatus == .wifi && BatteryMonitor.shared.isCharging
        }
    }
}

Battery Impact Measurements

Whistl tracks and reports battery usage:

Battery Breakdown

ComponentBattery/DayPercentage
Location Services2.5%36%
Network Activity1.8%26%
ML Inference1.2%17%
Background Fetch0.8%11%
UI Rendering0.7%10%
Total7.0%100%

Battery Usage Reporting

class BatteryReporter {
    func getBatteryUsage() -> BatteryReport {
        return BatteryReport(
            totalUsage: getTotalBatteryUsage(),
            breakdown: [
                .location: getLocationUsage(),
                .network: getNetworkUsage(),
                .ml: getMLUsage(),
                .background: getBackgroundUsage()
            ],
            averagePerDay: getAverageDailyUsage(),
            trend: getUsageTrend()
        )
    }
    
    // Users can view this in Settings → Battery Usage
}

Power Saving Mode

Users can enable power saving mode for reduced battery impact:

Power Saving Features

  • Extended sync intervals: 15 minutes instead of 5
  • Reduced location accuracy: Region monitoring only
  • Deferred ML inference: Every 15 minutes instead of 5
  • WiFi-only sync: No cellular data for background sync
  • Suspended animations: Reduced UI effects

Power Saving Impact

MetricNormal ModePower SavingReduction
Battery/Day7.0%3.5%50%
Location UpdatesEvery 5 minEvery 15 min67%
ML InferenceEvery 5 minEvery 15 min67%
Sync FrequencyEvery 4 hoursEvery 8 hours50%

User Testimonials

"I was worried about battery drain but Whistl uses maybe 5-7% per day. Totally worth it for the protection." — Emma, 26

"Power saving mode gets me through long days when I can't charge. Still protected, just less frequent updates." — Marcus, 28

"Battery usage is way better than other protection apps I've tried. Whistl clearly optimized this well." — Jake, 31

Conclusion

Whistl balances continuous protection with battery efficiency through adaptive scheduling, intelligent location management, and network optimization. At 7% daily battery impact (3.5% in power saving mode), protection doesn't come at the cost of all-day battery life.

Background tasks are scheduled intelligently—more frequent during high-risk periods, reduced during sleep—to maximise protection while minimising battery drain.

Get Efficient Protection

Whistl provides continuous protection with minimal battery impact. Download free and experience efficient background monitoring.

Download Whistl Free

Related: GPS Geofencing | On-Device ML | Offline-First Architecture