Android app security is critical in 2026, with increasing threats and stricter privacy regulations. Protecting user data and your app from attacks is not optional—it’s essential for success on Google Play and user trust.
This comprehensive guide covers all aspects of Android app security, from basic best practices to advanced techniques.
Why Android App Security Matters
Key Reasons:
- User Trust – Security breaches destroy reputation
- Legal Compliance – GDPR, CCPA, and other regulations
- Financial Loss – Data breaches cost millions
- Play Store Requirements – Google enforces security standards
- Competitive Advantage – Security is a feature
1. Secure Data Storage
Never Store Sensitive Data in Plain Text
Bad Practice:
// DON'T DO THIS
SharedPreferences prefs = getSharedPreferences("app", MODE_PRIVATE);
prefs.edit().putString("password", userPassword).apply();
Good Practice – Use EncryptedSharedPreferences:
MasterKey masterKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
SharedPreferences securePrefs = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
securePrefs.edit().putString("api_key", apiKey).apply();
Use Android Keystore
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore"
);
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
"MyKeyAlias",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build();
keyGenerator.init(keyGenParameterSpec);
SecretKey secretKey = keyGenerator.generateKey();
2. Network Security
Always Use HTTPS
Network Security Config (res/xml/network_security_config.xml):
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
In AndroidManifest.xml:
<application
android:networkSecurityConfig="@xml/network_security_config"
...>
</application>
Certificate Pinning
<network-security-config>
<domain-config>
<domain includeSubdomains="true">api.yourapp.com</domain>
<pin-set>
<pin digest="SHA-256">base64encodedpin==</pin>
<pin digest="SHA-256">backuppin==</pin>
</pin-set>
</domain-config>
</network-security-config>
3. Authentication Best Practices
Use Biometric Authentication
BiometricPrompt biometricPrompt = new BiometricPrompt(
activity,
executor,
new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationSucceeded(
BiometricPrompt.AuthenticationResult result
) {
// User authenticated successfully
}
@Override
public void onAuthenticationFailed() {
// Authentication failed
}
}
);
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Authentication")
.setSubtitle("Log in using your biometric credential")
.setNegativeButtonText("Use password")
.build();
biometricPrompt.authenticate(promptInfo);
Secure Token Storage
// Store tokens securely
EncryptedSharedPreferences.create(...)
.edit()
.putString("auth_token", token)
.putLong("token_expiry", expiryTime)
.apply();
// Always validate token expiry
long expiry = securePrefs.getLong("token_expiry", 0);
if (System.currentTimeMillis() > expiry) {
// Token expired, re-authenticate
}
4. Code Obfuscation
Enable R8/ProGuard
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}
Protect API Keys
Don’t hardcode API keys:
// BAD String apiKey = "sk_live_1234567890abcdef";
Use BuildConfig or NDK:
// In build.gradle
buildTypes {
release {
buildConfigField "String", "API_KEY", ""${System.getenv('API_KEY')}""
}
}
// In code
String apiKey = BuildConfig.API_KEY;
5. Input Validation
Validate All User Input
public boolean isValidEmail(String email) {
if (email == null || email.isEmpty()) {
return false;
}
String emailPattern = "[a-zA-Z0-9._-]+@[a-z]+\.+[a-z]+";
return email.matches(emailPattern);
}
public boolean isValidPassword(String password) {
// At least 8 characters, 1 uppercase, 1 lowercase, 1 digit
String passwordPattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$";
return password != null && password.matches(passwordPattern);
}
Prevent SQL Injection
// BAD - SQL Injection vulnerable
String query = "SELECT * FROM users WHERE username = '" + username + "'";
// GOOD - Use parameterized queries
String query = "SELECT * FROM users WHERE username = ?";
Cursor cursor = db.rawQuery(query, new String[]{username});
6. Permissions Best Practices
Request Minimum Permissions
<!-- Only request what you need --> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- Avoid dangerous permissions if possible -->
Runtime Permission Handling
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.CAMERA},
CAMERA_PERMISSION_CODE
);
} else {
// Permission already granted
openCamera();
}
7. Secure WebView Usage
WebView Security Settings
WebView webView = findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
// Disable JavaScript if not needed
settings.setJavaScriptEnabled(false);
// Disable file access
settings.setAllowFileAccess(false);
settings.setAllowContentAccess(false);
// Enable safe browsing
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
settings.setSafeBrowsingEnabled(true);
}
// Only load HTTPS
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return !url.startsWith("https://");
}
});
8. Prevent Reverse Engineering
Techniques:
- Code Obfuscation – R8/ProGuard
- String Encryption – Encrypt sensitive strings
- Root Detection – Detect rooted devices
- Tamper Detection – Verify app integrity
- Native Code – Move critical logic to NDK
Root Detection Example
public boolean isDeviceRooted() {
// Check for su binary
String[] paths = {
"/system/app/Superuser.apk",
"/sbin/su",
"/system/bin/su",
"/system/xbin/su"
};
for (String path : paths) {
if (new File(path).exists()) {
return true;
}
}
return false;
}
9. Secure Logging
Never Log Sensitive Data
// BAD
Log.d("Auth", "Password: " + password);
Log.d("Payment", "Credit Card: " + cardNumber);
// GOOD
if (BuildConfig.DEBUG) {
Log.d("Auth", "Login attempt for user: " + userId);
}
// Remove all logs in production
if (!BuildConfig.DEBUG) {
// Disable logging
}
10. App Integrity Verification
Google Play Integrity API
IntegrityManager integrityManager =
IntegrityManagerFactory.create(context);
Task<IntegrityTokenResponse> integrityTokenResponse =
integrityManager.requestIntegrityToken(
IntegrityTokenRequest.builder()
.setNonce(nonce)
.build()
);
integrityTokenResponse.addOnSuccessListener(response -> {
String token = response.token();
// Verify token on your server
});
Security Checklist
Before Release:
- ✅ Enable R8/ProGuard obfuscation
- ✅ Use HTTPS for all network calls
- ✅ Encrypt sensitive data at rest
- ✅ Implement certificate pinning
- ✅ Validate all user input
- ✅ Use EncryptedSharedPreferences
- ✅ Remove debug logs
- ✅ Request minimum permissions
- ✅ Secure WebView settings
- ✅ Implement biometric auth
- ✅ Test for common vulnerabilities
- ✅ Use Play Integrity API
Common Security Vulnerabilities
1. Insecure Data Storage
Risk: High
Fix: Use EncryptedSharedPreferences and Android Keystore
2. Weak Cryptography
Risk: High
Fix: Use AES-256, avoid MD5/SHA1
3. Insecure Communication
Risk: Critical
Fix: Always use HTTPS, implement certificate pinning
4. Improper Platform Usage
Risk: Medium
Fix: Follow Android security best practices
5. Code Tampering
Risk: Medium
Fix: Obfuscation, integrity checks
Security Testing Tools
- MobSF – Mobile Security Framework
- QARK – Quick Android Review Kit
- Drozer – Android security assessment
- Burp Suite – Network traffic analysis
- APKTool – Reverse engineering
Best Practices Summary
- Encrypt everything – Data at rest and in transit
- Validate all input – Never trust user data
- Use HTTPS only – No cleartext traffic
- Obfuscate code – Make reverse engineering harder
- Minimize permissions – Request only what’s needed
- Secure authentication – Use biometrics and tokens
- Test regularly – Security is ongoing
- Stay updated – Follow security advisories
Conclusion
Android app security is not a one-time task—it’s an ongoing process. By implementing these best practices, you can significantly reduce security risks and protect your users’ data.
Start with the basics (HTTPS, encryption, input validation) and gradually implement advanced techniques. Regular security audits and staying updated with the latest threats are essential.
For more Android development tips, check out our free WebP converter tool.