Permissions And Privacy
Permissions are native release work. The JavaScript prompt is only the runtime part.
Permission Layers
| Layer | Android | iOS |
|---|---|---|
| Native declaration | android.permissions, package manifests, android.blockedPermissions | ios.infoPlist, usage strings, background modes |
| Runtime request | Expo or React Native permission API | Expo or React Native permission API |
| User experience | Rationale, denial, permanent denial, settings recovery | Rationale, denial, limited access, settings recovery |
| Store review | Play policy, Data safety, sensitive permission declarations | App privacy, usage strings, privacy manifests, App Review |
Configure Intentionally
{
"expo": {
"ios": {
"infoPlist": {
"NSCameraUsageDescription": "Scan receipts you choose to capture."
}
},
"android": {
"permissions": ["CAMERA"],
"blockedPermissions": ["com.google.android.gms.permission.AD_ID"]
}
}
}
Use specific, user-facing explanations. Generic strings create review risk and user mistrust.
Test The Denied Path
Every permission feature needs:
- First-run prompt behavior.
- Denied behavior.
- Permanently denied/settings recovery.
- Feature fallback or clear disabled state.
- Store-review explanation that matches actual behavior.
Gotcha: Permission changes require a new binary. You cannot add a new Android manifest permission or iOS usage string with EAS Update alone.