There is a group of Android phones that most developers never test on. Not old phones, not cheap phones. Normal, modern devices where the owner removed Google services, or bought a device that never shipped with them, or uses a privacy focused Android build.
On those phones a lot of apps behave strangely. Some show an empty screen where a map should be. Some pop up a dialog asking to install something. Some just close. The app is not broken in any interesting way. It simply assumed a piece of software was there, and it was not.
This is worth fixing, and it is usually a small fix.
Google Play Services is a separate app
This is the part that surprises people. Google Play Services is not part of Android. It is an app, made by Google, that ships on most phones and provides a set of extras: push notifications, maps, location helpers, the in app rating popup, in app purchases, sign in with a Google account.
Android works without it. Your phone still makes calls, runs apps, connects to wifi. What disappears is that specific bundle of extras.
So when your app calls one of those extras, you are calling into an app that may not be installed. Most developers write that call as if it cannot fail, because on their own device it never does.
What actually breaks
The list is shorter than people expect, but the pieces are common ones.
The rating popup. The native “rate this app” dialog comes from the store, not from Android. No store, no dialog.
Maps. If you embed the standard map view, you get an empty rectangle or a crash, depending on how the library handles a missing dependency.
Push notifications. The usual push channel is part of the same bundle. On a de-Googled phone your messages never arrive and often nothing tells you why.
In app purchases. Billing runs through the store app. Without it, the purchase screen either fails to open or opens and cannot complete.
Sign in with a Google account. Obvious in hindsight, easy to forget when it is one option among several on your login screen.
Notice that most of these are optional features. A user can enjoy a game, a notes app or a calculator without any of them. The problem is almost never that the feature is essential. The problem is that the app treats it as guaranteed.
The failure is worse than it needs to be
If a missing feature simply did nothing, this would be a minor issue. What happens instead is louder.
The most common outcome is an error dialog that interrupts the user at a bad moment. The second most common is a crash. The third, and the most annoying for the person holding the phone, is an app that asks them to install the very thing they deliberately removed.
That last one is a small insult. Someone made a considered choice about their device, and your app responds by telling them the choice was wrong. It reads like a shop refusing to sell you bread because you arrived on foot.
The fix is a question, asked once
The rule is simple. Before using one of those extras, ask the system whether it is actually available. If it is not, skip that part of the app and carry on.
Android gives you a way to check. On newer versions you also have to declare which apps you want to ask about, which trips people up, because the check quietly returns “not installed” when you forget the declaration. That detail matters more than it should, since a forgotten declaration and a genuinely missing service look identical from inside your code.
Then handle the answer properly:
- If the rating popup is unavailable, never ask for a rating. Do not offer a fallback that opens a web page. The user did not ask to rate anything.
- If maps are unavailable, show an address as text, or open whichever map app the person actually has.
- If push is unavailable, fall back to checking for updates when the app opens, or accept that this user gets no push and say so once in settings.
- If billing is unavailable, hide the purchase screen instead of showing one that cannot work.
The pattern behind all four: the feature is optional, the app is not.
Degrade quietly, not apologetically
There is a temptation to explain. To show a banner saying this device is missing something, with a link to documentation.
Resist it. The user knows what is on their phone. A missing rating popup needs no announcement, because nobody opens a game hoping to be asked for a review. Silence is the correct response to an absent optional feature.
Reserve an explanation for the rare case where a missing service removes something the user actually asked for. If someone taps “pay” and billing is gone, tell them plainly and immediately. If someone never taps anything, say nothing.
Why we care about this
We build privacy first apps, and most of them work offline by design. That makes this group of users a natural audience for us. People who strip Google services off their phone tend to also want apps with no tracking, no accounts and no ads.
It would be strange to court that audience and then ship software that falls over on their device. So the check goes in, the optional feature stays optional, and the app behaves the same whether the extras are present or not.
There is a second reason, less about principle and more about craft. An app that assumes a dependency exists is an app with a hidden requirement nobody wrote down. Making that requirement explicit, even in a few lines, usually reveals that you needed it far less than you thought.
Test it once and you will keep testing it
The fastest way to find these assumptions is to run your app on a device with no Google services at all. Not a simulation, a real install. Most teams discover two or three surprises the first time, and after that the habit sticks.
It costs an afternoon. What you get back is an app that runs on every Android phone, including the ones owned by people who care most about what their software does behind their back. That is a reasonable trade.