On this page
An APK is a zip file. Its strings, BuildConfig constants, resources and even native libraries can be extracted with free tools in minutes. Obfuscation and NDK tricks slow attackers slightly, and runtime interception defeats them anyway. Design as if every key in the app is public.
Classify your keys
Keeping keys out of source control
Even for keys that are allowed in the app, avoid committing them to Git, where they're scraped quickly from public repos. The Secrets Gradle Plugin reads values from local.properties (which is ignored by Git) and exposes them as BuildConfig fields and manifest placeholders:
MAPS_API_KEY=your-restricted-maps-keyplugins {
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin")
}
android {
buildFeatures { buildConfig = true }
}<meta-data android:name="com.google.android.geo.API_KEY" android:value="${MAPS_API_KEY}" />The value still ends up in the built app. That's fine for restricted client keys, and never acceptable for real secrets.
Restrict client keys
- Application restrictions: limit to your package name and signing certificate SHA-1 (include the Play App Signing certificate).
- API restrictions: allow only the APIs the app uses.
- Quotas and alerts: cap usage and alert on spikes.
Remember that app restrictions rely on request metadata that a determined attacker can spoof. They limit casual abuse, not targeted attacks.
Real secrets: use a backend
For Gemini specifically, Firebase AI Logic with App Check provides this mediation without your own server. See Integrating Cloud AI APIs Securely.
If a secret leaks
- Revoke or rotate the key immediately in the provider console.
- Check usage logs and billing for abuse.
- Remove it from history (rewrite Git history if needed) and from any published APKs, by releasing an update.
- Fix the architecture so the secret no longer needs to be in the app.
- Enable secret scanning on your repositories.
Common keys and where they go
| Key | Where |
|---|---|
google-services.json (Firebase config) | App: identifiers, protected by Security Rules and App Check |
| Maps SDK key | App, restricted by package, SHA and API |
| Gemini / OpenAI / other AI keys | Server (or Firebase AI Logic) |
| Payment gateway secret key | Server only (publishable keys may ship) |
| Signing keystore passwords | CI secrets only |
Frequently asked questions
What about storing keys in native (C++) code?
It adds a small amount of effort for attackers, who can still extract them from the binary or intercept them at runtime. It isn't a substitute for keeping secrets server-side.
Can I fetch the key from my server at runtime?
Then it's in device memory and network traffic, so still exposed. Instead, have the server make the call that needs the key.
Is google-services.json a secret?
It contains project identifiers meant to be in the app. Protect your Firebase data with Security Rules and App Check instead.
Conclusion
You can't hide secrets in an APK. Ship only public or restricted client keys, keep them out of Git with the Secrets Gradle Plugin, put real secrets behind a backend (or Firebase AI Logic with App Check for Gemini), and have a rotation plan for leaks.
Next step: decide whether pinning is right for your API in Certificate Pinning: Benefits and Limitations.
Official references
๐ฑ Apps built by Yunok Tech
Real Android apps on Google Play, free to download.
Walzi4K wallpapers for lock and home screenGet it โธ
NotiVaultNotification history: recover dismissed notificationsGet it โธ
Ready to build real Android applications?
Security is easiest to get right when it is part of how you build from the first screen. Strengthen the Android fundamentals that secure, privacy-respecting apps are built on.
Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.
Explore the Android course and take your next step as an Android developer.