"It installs fine on my old phone, but on an Android 14 device it just won't." I've seen this feedback more times than I can count, and my first instinct is always the same place: check targetSdkVersion.

Android has spent the last few years steadily raising the bar. To keep apps stuck on old API levels — and missing the security updates that come with them — out of the ecosystem, the system treats installation packages with a conspicuously low targetSdkVersion increasingly harshly: a warning at first, then an outright block on certain paths. Google pushes that threshold forward with nearly every major release. Google Play's rule is even harder: a listed app's targetSdk has to fall within the most recent one or two Android versions, or it can't even be submitted.

How do you tell if you're on the wrong side of that line? Inspect the package directly with aapt: aapt dump badging app-release.apk | grep targetSdkVersion. Or check targetSdk in app/build.gradle. If that value is several major versions behind the current system, your install failure is almost certainly here.

The fix direction is clear: bump targetSdk in build.gradle above whatever floor Google currently requires, then rebuild and re-sign. But raising targetSdk isn't just editing a number — every bump pulls in behavioral changes: tighter background limits, shifted permission defaults, narrowed broadcasts. After upgrading, run your core flows on a real device running the target version. Don't ship just because it compiles.

A common trap is thinking "my app has run fine on old devices forever, no reason to touch it." The problem is users replace devices and systems upgrade; a package that installs today may not tomorrow. Keeping targetSdk moving with the mainstream isn't optimization so much as self-preservation.