Quick answer: Low-end Android phones, which a huge share of players actually own, crash from memory pressure, fragmented GPU drivers, and ANRs far more than from logic bugs. The low-memory killer terminates your game silently, cheap GPUs fail on shaders flagships handle, and slow CPUs trip the ANR watchdog. Capture available memory, device model, GPU renderer, and ANR state on each crash, group duplicates, and budget-phone crashes resolve into clear hardware patterns.
The phone you develop on is almost certainly nicer than the phone most of your players use. A large share of the global Android base is budget hardware: a gigabyte or two of RAM, an entry-level GPU, a slow CPU, and aggressive thermal throttling. On these devices your game faces failure modes that simply do not occur on a flagship, namely silent out-of-memory kills, GPU driver bugs on cheap chipsets, and application-not-responding errors when a slow CPU misses the watchdog. If you only test on good hardware, you are blind to the crashes that hit the most people. This post covers what breaks on low-end Android and how to capture the context that makes it fixable.
Memory is the first thing to break
On a phone with a gigabyte or two of RAM, your game shares memory with the OS and a pile of background apps, and the Android low-memory killer terminates whatever it decides costs too much. That is usually your game, and it dies without a stack trace, just vanishing to the launcher. Players report this as the game closing itself or restarting. A texture set, audio buffer, or level that loads comfortably on a flagship can push a budget phone past its budget and trigger an out-of-memory kill. Capturing available memory at crash time is what lets you recognize these for what they are.
Memory kills are not always clean crashes, so you have to treat low-memory warnings, trim-memory callbacks, and out-of-memory exceptions as first-class signals. A device that fired a memory warning shortly before disappearing was almost certainly killed for memory, even if no exception was thrown. Recording the memory state and warning history alongside the device model lets you correlate kills to specific low-RAM hardware. The fix is rarely a code logic change; it is a low-memory quality tier with smaller textures, fewer simultaneous sounds, and more aggressive unloading, targeted at exactly the devices the data implicates.
GPU driver fragmentation
Cheap Android phones use a wide range of entry-level GPUs with immature or buggy drivers, and a shader or rendering path that works on every flagship can fail, render garbage, or crash on a particular budget chipset. This is the classic Android fragmentation problem concentrated on hardware nobody tests. A graphics crash that appears only on certain GPU renderer strings is a driver issue, not a bug in your render logic, and the workaround is usually a simpler shader path or a feature toggle for that chipset rather than a universal change that would penalize everyone else.
Capturing the GPU renderer and driver version string on every crash is essential, because it is the only way to map a render crash to the hardware that produced it. With that context, a crash that looks scary and widespread often resolves to a single GPU family, which you can then own a cheap device for and reproduce directly. Without it, you are staring at a graphics stack trace with no idea whether it is one driver misbehaving or your code being genuinely wrong, and on fragmented low-end Android it is very often the former.
ANRs from slow CPUs
Application Not Responding errors are a uniquely Android failure: if your app does not respond to input or finish a frame on the main thread within the system timeout, Android shows the dreaded close-or-wait dialog and may kill you. On a slow budget CPU, work that is instant on a flagship, loading a level, decoding assets, a heavy frame, can blow past the watchdog and trigger an ANR that a fast phone would never hit. These are not classic crashes but they end sessions just as effectively, and players experience them as the game freezing.
To debug ANRs you need to know they happened and what the main thread was doing. Capture an ANR indicator and the operation in progress, the loading screen, the heavy frame, the save operation, so you can see which long task is blocking. A signature where ANRs cluster on a particular load or a specific cheap device points at a main-thread operation you must move off the main thread or chunk into smaller pieces. Treating ANRs as a tracked crash class, not an untraceable freeze, is what makes the slowest devices survivable.
Triaging the budget-phone population
Tag and group your crashes so the low-end population is visible. Budget phones often outnumber flagships in your install base, so their crashes are not an edge case, they are the main event, but only if you can see them. Group duplicates by signature and the list resolves into clear buckets: out-of-memory kills on low-RAM models, GPU crashes on specific cheap chipsets, and ANRs on slow CPUs. Sort by occurrence count, and weight memory kills and ANRs heavily since affected players frequently quit rather than retry, undercounting how much damage these do.
Filter by available memory and device model to confirm the out-of-memory story and tie it to specific hardware, by GPU renderer to isolate driver crashes, and by ANR state to find main-thread blocking. Because low-end Android is fragmented, these filters are what turn an overwhelming wall of reports into a short, hardware-correlated list. A crash confined to sub-two-gigabyte devices asks for a low-memory tier; one confined to a GPU family asks for a shader workaround; an ANR on a load screen asks for background loading. Each class has a distinct fix once the context separates them.
Setting it up with Bugnet
Bugnet's Android SDK is built for exactly this fragmentation. On a crash, kill, or ANR it captures the stack trace where one exists and attaches the context that decides everything on low-end hardware: available memory and memory-warning history, device model, GPU renderer and driver version, CPU class, an ANR indicator, the operation in progress, and the current scene. You add custom fields for a quality tier or any device classification you use, so each report arrives already showing whether memory, a GPU driver, or a slow-CPU ANR was the cause, which is most of the diagnosis on budget phones.
On the dashboard, occurrence grouping folds the huge, fragmented low-end stream into ranked issues, and the captured context becomes your filters. You separate out-of-memory kills on low-RAM models from GPU crashes on specific chipsets from ANRs on slow devices, and player attributes show how much of your base each fragile hardware tier represents. Because budget phones are where most players live, seeing these crashes grouped and quantified in one dashboard is what lets you prioritize the fixes that protect the largest, most underserved part of your audience instead of chasing whatever your flagship happened to show.
Designing for the devices players own
Build for the low end deliberately. Define an explicit low-memory quality tier and detect when to apply it from device memory, keep heavy work off the main thread to avoid ANRs, and maintain a list of fragile GPU chipsets with simpler render paths. Test on a genuinely cheap phone, not just your flagship, profiling memory under real conditions and timing your load screens against the ANR watchdog. These devices are the majority of the market, so every fix targeted at them protects more players than a flagship-only optimization ever could.
After release, watch the low-end population closely, since its crashes are easy to ignore when your own device runs everything fine. Use the captured memory, GPU, and ANR context to keep prioritizing by real player impact rather than by what is loudest in your own testing. Over a release or two you build a map of which budget devices need which accommodations, and the once-mysterious flood of self-closing and freezing reports resolves into a manageable set of memory, driver, and threading fixes. Serving the low end well is often the single biggest reliability win an indie Android game can make.
Most players are on budget phones where memory, GPU drivers, and ANRs cause the crashes. Capture memory, GPU renderer, and ANR state and the fixes target the real majority.