Course Dashboard

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_NOTIFICATIONS permission 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:

  1. Explain the Benefit First: Show a custom in-app screen explaining why you need notifications (e.g., "To send you critical medical reminders").
  2. Contextual Triggers: Request permissions only when the user tries to activate a feature that depends on them (e.g., clicking a "Remind Me" button).
  3. 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.tstypescript
import * 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.tstypescript
import { 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.