Quick answer: A well-designed bug reporting SDK has negligible battery impact during normal gameplay. The SDK passively collects log lines and context updates with minimal CPU overhead.
This guide covers automated bug reporting for mobile games in detail. Mobile games present unique challenges for bug reporting. Players are on metered data connections, battery life matters, app store review guidelines restrict what you can collect, and the sheer diversity of Android devices means a bug might only appear on a specific chipset with a specific OS version. Getting bug reporting right on mobile requires understanding these constraints and designing around them. This guide covers the mobile-specific considerations that most desktop-focused bug reporting guides miss.
Why Mobile Bug Reporting Is Different
On desktop, you can assume reliable internet, ample storage, and relatively homogeneous hardware. Mobile breaks all three assumptions:
Connectivity is unreliable. Players switch between WiFi, cellular, and no connectivity constantly. A bug report that fails to upload on the subway needs to be cached and retried when the player gets home. If your SDK cannot handle offline scenarios, you will lose reports from exactly the situations that produce the most interesting bugs.
Battery and bandwidth are precious resources. A bug reporting SDK that constantly phones home or runs background processing will drain battery and consume data. Players will blame your game for both. The SDK must be nearly invisible during normal gameplay, only consuming meaningful resources when a report is actively being submitted.
Device fragmentation is extreme. On Android alone, there are thousands of active device models running dozens of OS versions with different GPU drivers, screen sizes, and performance characteristics. A bug report without device-specific context is nearly useless because the first question will always be "what device?"
Screenshot Capture on Mobile
Screenshot capture is the highest-value automatic data you can include, but on mobile it requires careful handling:
// Unity: mobile-optimized screenshot
IEnumerator CaptureScreenshot()
{
yield return new WaitForEndOfFrame();
var texture = new Texture2D(
Screen.width, Screen.height,
TextureFormat.RGB24, false);
texture.ReadPixels(
new Rect(0, 0, Screen.width, Screen.height),
0, 0);
texture.Apply();
// Downscale for bandwidth on mobile
var scaled = ScaleTexture(texture, 960, 540);
byte[] jpg = scaled.EncodeToJPG(75);
Destroy(texture);
Destroy(scaled);
// jpg is typically 50-150KB at this size
AttachToReport(jpg);
}
Downscale before compressing. A full-resolution screenshot on a modern phone (2400x1080 or higher) produces a massive image. Downscale to 960x540 or 1280x720 before JPEG compression. The resulting image is still perfectly readable for bug identification and dramatically reduces upload size.
Use JPEG, not PNG. JPEG at quality 70–80 produces files 5–10x smaller than PNG with no meaningful loss of diagnostic information. For a bug report screenshot, you need to see what is on screen, not preserve pixel-perfect color accuracy.
Capture asynchronously. The screenshot capture (ReadPixels in Unity, get_image in Godot) can cause a frame hitch. On mobile where frame budgets are tight (16.6ms for 60fps), schedule the capture for the end of a frame and accept that one frame may drop. Do not capture screenshots every frame—only when the report form opens.
Crash Capture on iOS and Android
Mobile crash capture is platform-specific and technically demanding. Here is what each platform requires:
iOS
iOS crashes fall into two categories: Objective-C/Swift exceptions and POSIX signals (SIGSEGV, SIGABRT). For games built with Unity or Unreal, most crashes are signal-based because the game logic runs in native code.
The crash handler must write crash data to disk synchronously during the crash, because the process is about to terminate. On next launch, the SDK reads the persisted crash data and uploads it. Apple restricts what you can do in a signal handler—no Objective-C calls, no memory allocation, no file I/O through high-level APIs. Use POSIX write() directly to a pre-opened file descriptor.
Apple also provides crash reports through the Xcode Organizer and App Store Connect, but these arrive with a 24–48 hour delay and lack game-specific context. Use them as a supplement, not a replacement.
Android
Android has three crash vectors: JVM exceptions (caught by Thread.UncaughtExceptionHandler), native signal crashes (SIGSEGV, SIGABRT via sigaction), and ANRs (Application Not Responding, triggered when the main thread is blocked for 5+ seconds).
// Android: setting up JVM exception handler
Thread.setDefaultUncaughtExceptionHandler(
(thread, throwable) -> {
// Serialize crash data to disk
writeCrashToFile(throwable);
// Call previous handler
if (previousHandler != null)
previousHandler.uncaughtException(
thread, throwable);
}
);
ANRs are particularly nasty for mobile games. A complex physics simulation, a large asset load, or a synchronous network call can block the main thread and trigger an ANR. Capture the main thread’s stack trace periodically (every 500ms) in a watchdog thread. If an ANR is detected, you have the stack trace showing what the main thread was doing when it froze.
Offline Caching and Retry
Mobile games must handle offline bug reporting gracefully. The pattern is:
1. Submit immediately if online. Check connectivity before upload. If the device has a network connection, send the report immediately in the background.
2. Cache to disk if offline. Serialize the report (including screenshot bytes) to local storage. On iOS, use the app’s Documents or Caches directory. On Android, use internal storage (no permission needed) or scoped external storage.
3. Retry on next launch or connectivity change. When the app launches or when connectivity is restored, check for cached reports and upload them. Use exponential backoff for retry attempts.
4. Expire old reports. If a cached report is older than 7 days, discard it. Stale reports with outdated build versions are unlikely to be actionable, and they consume storage on the player’s device.
Battery and Performance Impact
A bug reporting SDK should have zero measurable impact on frame rate and battery during normal gameplay. Here is how to ensure that:
No per-frame work. The SDK should not run any code in the game’s update loop during normal play. Log capture can use an event-driven callback that fires only when a log line is emitted, not a polling loop.
Fixed-size log buffer. Use a ring buffer with a fixed capacity (100–200 entries). This ensures constant memory usage regardless of how verbose the game’s logging is.
Compress before upload. Compress the report payload (gzip the JSON, JPEG the screenshot) before uploading. This reduces upload time and cellular data usage.
Respect low-power mode. On iOS, check ProcessInfo.processInfo.isLowPowerModeEnabled. On Android, check BatteryManager.isCharging(). When the device is in low-power mode or below 20% battery, cache reports instead of uploading immediately.
“We measured our SDK’s battery impact across a 4-hour play session on a Pixel 7. The difference between SDK enabled and disabled was within the measurement margin of error—less than 0.5% battery. The screenshot capture at report time was the only measurable cost, at approximately 8ms on that device.”
App Store Compliance
Both Apple and Google have policies about data collection that affect bug reporting:
Apple App Privacy: declare what data your app collects in App Store Connect. Bug reports that include device info, crash data, and user-provided descriptions fall under "Diagnostics" and "Other Data." If you collect a player identifier, declare it under "User ID."
Google Play Data Safety: similarly, declare crash logs and diagnostic data in your Data Safety section. If reports are sent to a third-party service (like Bugnet), disclose this.
GDPR and CCPA: if your game has European or Californian players, ensure your privacy policy covers bug report data collection and that players can opt out. A good practice is to show a brief consent prompt on first launch: "Help us improve by sending crash reports and bug data."
Related Issues
For general mobile error logging setup, see How to Set Up Error Logging for Mobile Games. For a broader look at mobile crash reporting, check our guide on Mobile Game Crash Reporting Best Practices. And for crash reporting fundamentals that apply across all platforms, read How to Set Up Crash Reporting for Indie Games.
Mobile players will never email you a bug report. If you want to know what is breaking on their devices, the SDK has to do all the work. Make it invisible, make it reliable, and make it respectful of their battery and data.