Notification Permissions: Mastering the "First Ask" Strategy
Requesting permissions is the most critical step in your user's journey. Research shows that over 60% of users decline permission requests if they appear at the wrong time or without clear context. In the Expo ecosystem, we have the tools to manage this process gracefully and professionally.
The Evolution of Notification Permissions
The landscape of mobile permissions has changed significantly:
- Android 13+: Requesting the
POST_NOTIFICATIONSpermission became mandatory and explicit, mirroring the long-standing iOS behavior. - iOS: Has always required explicit user consent before any notification could be delivered.
As a developer, you must handle these permissions programmatically, checking their status every time the app needs to send a notification.
The "Soft Ask" Strategy
The biggest technical mistake is requesting permissions immediately upon the first app launch. The user hasn't built trust with your app yet and doesn't understand the value it provides. Instead, follow the "Soft Ask" strategy:
- Explain the Benefit First: Show a custom in-app screen explaining why you need notifications (e.g., "To send you critical medical reminders").
- Contextual Triggers: Request permissions only when the user tries to activate a feature that depends on them (e.g., clicking a "Remind Me" button).
- Gate the System Dialog: Use a custom "Enable" button in your UI before triggering the official system permission dialog.
Implementation in Expo
We use the expo-notifications library to handle permissions. Here is the recommended pattern:
index.tstypescriptimport * as Notifications from 'expo-notifications'; import { Platform } from 'react-native'; async function requestNotificationPermissions() { // 1. Check current status const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; // 2. If not granted, request it if (existingStatus !== 'granted') { const { status } = await Notifications.requestPermissionsAsync(); finalStatus = status; } // 3. Handle the result if (finalStatus !== 'granted') { alert('We won\'t be able to send you important reminders without your permission.'); return false; } return true; }
Handling Denials Gracefully
Once a user denies the official system dialog twice (on Android) or once (on iOS), the dialog will not appear again. In this case, you must guide the user to open the system settings manually:
index.tstypescriptimport { Linking } from 'react-native'; const openAppSettings = () => { if (Platform.OS === 'android') { Linking.openSettings(); } else { Linking.openURL('app-settings:'); } };
Android-Specific Configuration
For Android 13+ projects, ensure you've added the permission to your app.json:
App.jsjson{ "expo": { "android": { "permissions": ["POST_NOTIFICATIONS"] } } }
Key Takeaways
- Avoid immediate permission prompts (use a "Soft Ask").
- Always check status using
getPermissionsAsync. - Provide a clear path to system settings if permission is denied.