AFBattery Optimization
Android-only helper for the battery-optimization exemption — the single biggest lever for geofencing reliability on aggressive OEMs.
On stock Android, geofence transitions and the SDK's WorkManager jobs (outbox flush, geofence reconcile) survive backgrounding fine. On battery-aggressive OEMs (Xiaomi/MIUI, Huawei/EMUI, Oppo·OnePlus/ColorOS, Vivo, some Samsung deep-sleep), Doze and app-hibernation defer or kill them — which is what actually drops geofence delivery and stalls the reconcile cadence. A foreground service does not fix this (a force-stop / OEM task-killer removes it too); the effective mitigation is asking the user to exempt the app from battery optimization.
This is opt-in by design — only the host app can decide when to surface the prompt (typically right after the member enables facility monitoring). The SDK does not prompt on its own.
if (!AFBatteryOptimization.isIgnoringBatteryOptimizations(context)) {
// Explain why, then:
AFBatteryOptimization.openBatteryOptimizationSettings(context)
}Note on the direct one-tap prompt: Android also offers ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, which exempts this app in a single dialog, but it requires the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission and Google Play restricts that permission to apps with a qualifying core use case (continuous location qualifies, but it draws Play review). To avoid forcing that permission — and Play scrutiny — on every consumer, this helper deliberately routes to the settings screen instead, which needs no special permission. Apps that qualify can add the direct intent themselves.
Functions
True when the host app is already exempt from battery optimization (or the OS predates the feature, where there is nothing to exempt). When this returns false, background geofence delivery and the SDK's WorkManager cadence may be throttled by Doze / OEM hibernation.
Opens the system battery-optimization list so the user can mark this app as "not optimized" / "unrestricted". Play-safe (no special permission). Falls back to the app's details screen if the dedicated screen is unavailable on the device. Pass an Activity context where possible; a non-Activity context works because FLAG_ACTIVITY_NEW_TASK is added.