Nearly every pinning incident reads the same: the app worked, the certificate was renewed, and older versions stopped connecting. Two decisions taken before you ship prevent it.
Pinning the server certificate forces a new app release on every renewal. Pinning the SPKI, that is the hash of the public key, lets you renew the certificate as often as you like as long as you keep the same key pair.
On Android, the supported way to do this is Network Security Configuration: a declarative XML file with the pins per domain, rather than a hand-written TrustManager. Being declarative, it is far harder to get wrong in a way that silently disables the check.
A single pin is a single point of failure. If that key is compromised and has to be replaced urgently, every version shipped with only that pin is dead until the user updates, and users cannot be made to update.
The correct practice is to generate a second key pair in advance, keep it offline, and ship its pin alongside the one in use. On rotation day the apps already trust the new key before a certificate for it exists.
Network Security Configuration accepts an expiration attribute on the pin set. Past that date the check is disabled and the app falls back to default behaviour.
It is a reasonable safeguard against stranding old versions, but be clear about what it means: an old app eventually stops being pinned at all. If that app is not expected to live that long, force an update before the date arrives.
Pinning guarantees you are talking to your server, not that your server is talking to your app. An attacker who reimplements the client connects without trouble: they are not intercepting anything, they are simply a new client. Authenticating the client is a different problem, and mTLS is what solves it.
Request access to the closed beta and try it on your app.