Handling Notification Permissions and User Preferences in React Native
Course: React Native Training
Topic: Handling Notification Permissions and User Preferences
Course Link: React Native Training at JustAcademy
Demo Link: Register for a Course Demo
Training Provider: JustAcademy
1. Introduction to Notification Permissions and User Preferences
Notification permissions determine whether a mobile application can display notifications, play notification sounds, update the application badge, and use other notification-related features. User preferences allow users to control which notifications they want to receive and how they want to receive them.
In React Native applications, notification permission handling is especially important when implementing messaging systems, e-commerce alerts, booking reminders, delivery updates, banking notifications, and social media applications.
When building an application with Expo, developers can use the expo-notifications package to check notification permissions, request authorization, inspect supported permission settings, and manage notification presentation.
Official documentation: Expo Notifications API Reference.
2. Learning Objectives
After completing this topic, learners should be able to:
- Understand notification permissions and their purpose.
- Differentiate operating-system permissions from application-level preferences.
- Install and configure the Expo Notifications package.
- Check existing notification permission status.
- Request permission at an appropriate point in the user journey.
- Handle permission denial and restricted permission states.
- Understand Android and iOS notification permission behavior.
- Build a notification preferences screen.
- Save notification preferences locally and on a backend.
- Open application settings when users need to change system permissions.
- Control notification sounds, badges, and presentation where supported.
- Test permission handling and troubleshoot common problems.
3. What Are Notification Permissions?
Notification permissions are authorizations controlled by the mobile operating system. They determine whether an application is allowed to present notifications or use certain notification features.
For example, a shopping application may request permission to send order updates. If permission is granted, the operating system can display notifications according to the user's system settings. If permission is denied, the application must respect that decision and provide an appropriate alternative way to view updates.
3.1 Why Notification Permissions Matter
- User control: Users decide whether an application can interrupt them.
- Privacy: Notification content can appear on a lock screen, so users should understand how alerts work.
- User experience: Relevant notifications are more useful than repeated or unwanted messages.
- Operating-system compliance: Applications must follow the permission requirements of Android and iOS.
- Engagement: Thoughtful permission handling can help users receive important information without overwhelming them.
3.2 Examples of Notification Permissions
| Permission or Setting |
Purpose |
Example |
| Notification alerts |
Allows visible notifications where authorized. |
A new message alert. |
| Sound |
Controls whether a notification can play a sound. |
A delivery update plays an alert tone. |
| Badge |
Controls the app icon's notification count where supported. |
An unread-message count on the app icon. |
| Lock-screen display |
Controls whether notifications can appear on the lock screen. |
A reminder is shown while the phone is locked. |
| Notification channel settings |
Allow Android users to control categories of notifications. |
Order alerts can have different settings from promotional alerts. |
| Application preferences |
Control which notification categories the app attempts to send. |
A user disables marketing notifications but keeps order updates enabled. |
Available controls differ by operating-system version, device, application configuration, and permission state.
4. System Permissions vs. Application Preferences
A critical concept is that operating-system permissions and application-level preferences are different. Both should be considered before sending a notification.
| Feature |
System Permission |
Application Preference |
| Managed by |
Android or iOS settings. |
Your application and backend. |
| Purpose |
Controls what the operating system allows. |
Controls what types of notifications the user wants. |
| Example |
Allow or deny notifications for the app. |
Enable order updates but disable promotions. |
| Can be changed by user? |
Yes, through system prompts or device settings. |
Yes, through the application's settings screen. |
| How to check |
Use the notification permission APIs. |
Read stored preferences from local storage or the backend. |
For example, a user might allow notifications at the system level but turn off promotional messages in the application. In this situation, the app must not send promotional notifications just because system permission is granted.
5. Installing Expo Notifications
For an Expo-based React Native project, install the notification and settings-related packages using Expo's compatible package versions.
npx expo install expo-notifications expo-constants
The packages have the following roles:
expo-notifications provides APIs for notification permission checks, requests, listeners, and presentation.
expo-constants provides application configuration information that can be useful when registering for remote push notifications.
expo-device can be used when the application needs to inspect whether it is running on a physical device.
@react-native-async-storage/async-storage can store simple, non-sensitive preferences locally.
Install AsyncStorage only if you need local persistence:
npx expo install @react-native-async-storage/async-storage
Package documentation: Expo Notifications.
6. Understanding Notification Permission States
Before requesting permission, check the current status. The operating system may have already granted or denied authorization.
6.1 Common Permission States
| State |
Meaning |
Recommended Action |
| Not determined |
The user has not yet made a permission decision, where this state is exposed. |
Explain the benefit and request permission at an appropriate moment. |
| Granted |
The application is authorized for notifications at the system level. |
Check granular settings and application preferences before sending notifications. |
| Denied |
The application is not authorized to display notifications or permission was refused. |
Explain how the user can enable notifications in system settings. |
| Provisional on iOS |
The application may be authorized to deliver non-interruptive notifications. |
Interpret the iOS authorization status rather than relying only on the root status. |
| Restricted or limited behavior |
Device policies or operating-system settings may limit notification behavior. |
Inspect the returned permission information and provide a suitable fallback. |
On iOS, the notification authorization status is more granular than a simple granted or denied value. Expo exposes iOS-specific status information through the permissions response. Consult the API documentation for the current SDK behavior.
7. Checking Existing Notification Permissions
The getPermissionsAsync() method checks the application's current notification permission settings without displaying a permission prompt.
import * as Notifications from 'expo-notifications';
export async function checkNotificationPermissions() {
try {
const permissions = await Notifications.getPermissionsAsync();
console.log('Permission response:', permissions);
return permissions;
} catch (error) {
console.error('Unable to check notification permissions:', error);
return null;
}
}
Use this function when:
- The application starts and needs to update the notification settings screen.
- The user returns from the device's Settings app.
- The application needs to determine whether notification registration should continue.
- The application wants to display an appropriate status message.
Do not assume that checking permissions means the application is allowed to use every notification feature. On iOS, sound, badges, alerts, and other settings can be controlled separately.
8. Requesting Notification Permissions
Use requestPermissionsAsync() to ask the operating system for notification authorization.
import * as Notifications from 'expo-notifications';
export async function requestNotificationPermission() {
try {
const permissions = await Notifications.requestPermissionsAsync({
ios: {
allowAlert: true,
allowBadge: true,
allowSound: true
}
});
return permissions;
} catch (error) {
console.error('Permission request failed:', error);
return null;
}
}
This example requests the specified notification capabilities on iOS. The exact options and returned status depend on the platform and the installed Expo SDK.
8.1 Recommended Permission Request Flow
- Explain why notifications would be useful to the user.
- Allow the user to choose whether to enable notifications.
- Check the existing system permission status.
- Request permission if appropriate.
- Inspect the response instead of assuming permission was granted.
- If authorized, continue with token registration when remote push notifications are needed.
- If denied, preserve application functionality and explain how to enable notifications later.
9. Creating an Android Notification Channel
On Android 8.0 and later, notification channels organize notifications into categories. On Android 13 and later, a notification channel must be created before the operating system's notification permission prompt can appear through the normal flow.
import { Platform } from 'react-native';
import * as Notifications from 'expo-notifications';
export async function createNotificationChannel() {
if (Platform.OS !== 'android') {
return;
}
await Notifications.setNotificationChannelAsync('general', {
name: 'General Notifications',
importance: Notifications.AndroidImportance.DEFAULT,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#2563EB'
});
}
Call this function before requesting notification permission or registering the device for push notifications.
9.1 Recommended Notification Channels
| Channel ID |
Channel Name |
Purpose |
messages |
Messages |
New chat messages and conversation updates. |
orders |
Order Updates |
Order confirmations and delivery status. |
reminders |
Reminders |
Scheduled events and personal reminders. |
marketing |
Offers and Promotions |
Promotional notifications when the user has opted in. |
Android users can adjust individual channel settings through system settings. Application-level preferences should still be checked before sending messages.
10. Understanding iOS Notification Permissions
iOS provides notification controls that can include alerts, sounds, badges, notification center display, lock-screen display, and other options. The user can change these settings after the initial permission decision.
Expo exposes iOS-specific permission information through the ios property of the permissions response.
import * as Notifications from 'expo-notifications';
export async function inspectIOSNotificationSettings() {
const permissions = await Notifications.getPermissionsAsync();
return {
overallGranted: permissions.granted,
iosStatus: permissions.ios?.status,
alertsAllowed: permissions.ios?.allowsAlert,
soundAllowed: permissions.ios?.allowsSound,
badgeAllowed: permissions.ios?.allowsBadge,
lockScreenAllowed: permissions.ios?.allowsDisplayOnLockScreen
};
}
These values can be unavailable or null depending on the operating system and response. Always handle missing values safely.
Official reference: Expo Notifications Permissions Documentation.
11. Designing a User-Friendly Permission Experience
Asking for permission immediately after the application opens can confuse users, especially if they do not yet understand the application's benefits.
A better approach is to show a short explanation before displaying the system permission prompt.
11.1 Example Permission Explanation
Notifications help you stay informed about:
- Important account updates
- Order and delivery status
- Messages and reminders
You can change your notification preferences at any time.
11.2 Permission Request Best Practices
- Explain the value of notifications before requesting authorization.
- Ask at a meaningful point in the user journey.
- Do not repeatedly pressure users who decline.
- Offer a clear choice where appropriate.
- Do not block unrelated application features just because permission is denied.
- Allow users to change category preferences later.
- Explain how to open system settings if permission has been disabled.
12. Handling Permission Denial
Users may deny notification permission. The application should handle this state gracefully instead of repeatedly showing prompts or assuming notifications will work.
import * as Notifications from 'expo-notifications';
export async function enableNotifications() {
const current = await Notifications.getPermissionsAsync();
if (current.granted) {
return {
enabled: true,
message: 'Notifications are authorized.'
};
}
const result = await Notifications.requestPermissionsAsync();
if (result.granted) {
return {
enabled: true,
message: 'Notifications have been enabled.'
};
}
return {
enabled: false,
canAskAgain: result.canAskAgain,
message: 'Notifications are not currently authorized.'
};
}
When permission is denied, display a helpful message. If the platform indicates that the permission cannot be requested again through the normal prompt, guide the user to the device's application settings.
Do not repeatedly call the permission request API in a loop. Permission prompts are controlled by the operating system, and users should remain in control of the decision.
13. Opening Device Settings
If users previously denied permission, they may need to enable notifications manually through system settings. React Native's Linking API can open the application's settings page on supported platforms.
import { Linking, Alert } from 'react-native';
export function showNotificationSettingsHelp() {
Alert.alert(
'Enable Notifications',
'Open your device settings to allow notifications for this app.',
[
{
text: 'Cancel',
style: 'cancel'
},
{
text: 'Open Settings',
onPress: () => {
Linking.openSettings();
}
}
]
);
}
The settings page may expose different notification controls depending on the device. After the user returns to the application, check the permissions again rather than assuming that settings were changed.
14. Refreshing Permission Status When the App Returns to the Foreground
Users can change notification permissions while the application is in the background. Use React Native's AppState API to refresh the permission status when the application returns to the foreground.
import { useEffect, useState } from 'react';
import { AppState } from 'react-native';
import * as Notifications from 'expo-notifications';
export function useNotificationPermissionStatus() {
const [permissions, setPermissions] = useState(null);
useEffect(() => {
let active = true;
async function refreshPermissions() {
try {
const result = await Notifications.getPermissionsAsync();
if (active) {
setPermissions(result);
}
} catch (error) {
console.error('Unable to refresh permissions:', error);
}
}
refreshPermissions();
const subscription = AppState.addEventListener(
'change',
nextState => {
if (nextState === 'active') {
refreshPermissions();
}
}
);
return () => {
active = false;
subscription.remove();
};
}, []);
return permissions;
}
This pattern is useful for a settings screen that must reflect changes made outside the application.
15. Understanding User Notification Preferences
Application-level notification preferences allow users to choose the categories of messages they want to receive. These preferences are separate from system permission status.
For example, a user might allow all notifications at the operating-system level but choose to receive only order updates and security alerts from the application.
15.1 Example Preference Categories
| Preference |
Example |
Typical Default |
| Order updates |
Order confirmed or shipped. |
Enabled if important to the service, with clear user controls. |
| Messages |
New chat messages. |
Enabled or configurable. |
| Reminders |
Upcoming appointment. |
Configurable by the user. |
| Marketing |
Discounts and promotional offers. |
Opt-in where appropriate and required by applicable rules. |
| Security alerts |
Sign-in or account security events. |
Handled according to the service's security requirements and user disclosures. |
| Product announcements |
New feature information. |
Configurable by the user. |
16. Creating a Notification Preferences Screen
A preferences screen can contain switches for different notification categories. The example below uses React Native's built-in Switch component and component state.
import { useState } from 'react';
import {
View,
Text,
Switch,
StyleSheet
} from 'react-native';
export default function NotificationPreferencesScreen() {
const [preferences, setPreferences] = useState({
orderUpdates: true,
messages: true,
reminders: true,
marketing: false
});
function updatePreference(key, value) {
setPreferences(previous => ({
...previous,
[key]: value
}));
}
return (
<View style={styles.container}>
<Text style={styles.title}>Notification Preferences</Text>
<View style={styles.row}>
<Text>Order Updates</Text>
<Switch
value={preferences.orderUpdates}
onValueChange={value =>
updatePreference('orderUpdates', value)
}
/>
</View>
<View style={styles.row}>
<Text>Messages</Text>
<Switch
value={preferences.messages}
onValueChange={value =>
updatePreference('messages', value)
}
/>
</View>
<View style={styles.row}>
<Text>Reminders</Text>
<Switch
value={preferences.reminders}
onValueChange={value =>
updatePreference('reminders', value)
}
/>
</View>
<View style={styles.row}>
<Text>Marketing Messages</Text>
<Switch
value={preferences.marketing}
onValueChange={value =>
updatePreference('marketing', value)
}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#FFFFFF'
},
title: {
fontSize: 22,
fontWeight: 'bold',
marginBottom: 24
},
row: {
minHeight: 56,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
borderBottomWidth: 1,
borderBottomColor: '#DDDDDD'
}
});
Important: The example above updates preferences in memory only. The values will reset when the screen or application state is recreated. Use persistent storage to retain the user's choices.
17. Saving Preferences with AsyncStorage
AsyncStorage can persist simple application preferences on the device. It is suitable for non-sensitive settings such as notification category choices.
import AsyncStorage from '@react-native-async-storage/async-storage';
const PREFERENCES_KEY = '@app_notification_preferences';
export async function saveNotificationPreferences(preferences) {
try {
await AsyncStorage.setItem(
PREFERENCES_KEY,
JSON.stringify(preferences)
);
} catch (error) {
console.error('Failed to save preferences:', error);
throw error;
}
}
export async function loadNotificationPreferences() {
try {
const stored = await AsyncStorage.getItem(PREFERENCES_KEY);
if (!stored) {
return {
orderUpdates: true,
messages: true,
reminders: true,
marketing: false
};
}
return JSON.parse(stored);
} catch (error) {
console.error('Failed to load preferences:', error);
return {
orderUpdates: true,
messages: true,
reminders: true,
marketing: false
};
}
}
Validate stored data before relying on it. Local storage can be missing, outdated, or malformed after application updates.
18. Integrating Preference Saving with a Switch
When a user changes a preference, update the interface immediately and save the change. In a production application, you may also synchronize it with your backend.
import { useEffect, useState } from 'react';
import {
View,
Text,
Switch,
Alert
} from 'react-native';
import {
loadNotificationPreferences,
saveNotificationPreferences
} from './notificationPreferences';
export default function NotificationSettings() {
const [preferences, setPreferences] = useState({
orderUpdates: true,
messages: true,
reminders: true,
marketing: false
});
useEffect(() => {
let mounted = true;
loadNotificationPreferences().then(saved => {
if (mounted) {
setPreferences(saved);
}
});
return () => {
mounted = false;
};
}, []);
async function togglePreference(key, value) {
const updated = {
...preferences,
[key]: value
};
setPreferences(updated);
try {
await saveNotificationPreferences(updated);
} catch (error) {
Alert.alert(
'Unable to Save',
'Your notification preference could not be saved.'
);
}
}
return (
<View style={{ padding: 20 }}>
<Text style={{ fontSize: 22, fontWeight: 'bold' }}>
Notification Settings
</Text>
<View style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginTop: 20
}}>
<Text>Order Updates</Text>
<Switch
value={preferences.orderUpdates}
onValueChange={value =>
togglePreference('orderUpdates', value)
}
/>
</View>
<View style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginTop: 20
}}>
<Text>Marketing Messages</Text>
<Switch
value={preferences.marketing}
onValueChange={value =>
togglePreference('marketing', value)
}
/>
</View>
</View>
);
}
This example illustrates the basic interaction. For robust applications, use a state update strategy that avoids stale state when multiple switches are changed quickly, and decide how to roll back or retry if saving fails.
19. Combining System Permission with User Preferences
Before sending a notification, the application should consider both the operating-system permission and the user's category preferences.
A simplified decision process is:
- Check whether the user is eligible to receive the notification.
- Check whether the user has enabled the relevant category.
- Check whether the system allows the notification to be displayed.
- Send the notification only when the applicable rules and preferences allow it.
- Use the operating system's presentation behavior and settings to determine whether sound, badge, or visual alerts can be shown.
For remote notifications, the backend should enforce category preferences before sending. Disabling a category only in the user interface is not enough if the server continues to send messages for that category.
19.1 Example Notification Decision Function
export function shouldSendCategoryNotification({
categoryEnabled,
userEligible,
systemPermissionGranted
}) {
return (
userEligible === true &&
categoryEnabled === true &&
systemPermissionGranted === true
);
}
const allowed = shouldSendCategoryNotification({
categoryEnabled: true,
userEligible: true,
systemPermissionGranted: true
});
console.log('Eligible to send:', allowed);
This is a simplified client-side example for understanding the decision. In production, the backend must enforce user eligibility and category preferences independently. The device permission check cannot guarantee that a notification will appear.
20. Controlling Notification Presentation
The Expo notification handler determines how an incoming notification should be presented while the application is active. For example, the app can request that notifications show a banner and appear in the notification list.
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowBanner: true,
shouldShowList: true,
shouldPlaySound: true,
shouldSetBadge: false
})
});
Register the handler during application initialization. This configuration does not override system-level permission restrictions or guarantee that every notification will be presented.
Users may disable sound or alerts through device settings. On iOS, inspect the granular permission values when you need to understand whether sounds or badges are allowed.
21. Managing Application Badge Counts
Application badges can display a count of unread messages or other pending items. Badge support and behavior vary by operating system and device launcher.
21.1 Reading the Badge Count
import * as Notifications from 'expo-notifications';
export async function getCurrentBadgeCount() {
return Notifications.getBadgeCountAsync();
}
21.2 Updating the Badge Count
import * as Notifications from 'expo-notifications';
export async function updateBadgeCount(count) {
const safeCount = Math.max(0, Math.floor(count));
return Notifications.setBadgeCountAsync(safeCount);
}
21.3 Clearing the Badge
await Notifications.setBadgeCountAsync(0);
On iOS, badge permission must be authorized for badge updates to succeed. Some Android launchers do not support badges or may report that badge updates are unavailable. Handle the returned result accordingly.
22. Managing Sound Preferences
Notification sound behavior is controlled by the operating system, notification settings, and application configuration. An application should not assume that sound will play simply because a notification includes a sound field.
Good practices include:
- Allow users to control optional sound preferences.
- Respect system-level sound settings.
- Use notification channels on Android to separate categories where appropriate.
- Avoid using sound for nonessential notifications that could interrupt users.
- Explain when a setting controls app behavior rather than overriding system settings.
For example, a user preference called “Play sounds for reminders” can be stored in the application. However, the operating system can still prevent a sound from playing when its notification permissions or channel settings disallow it.
23. Notification Preferences on the Backend
Applications with accounts or multiple devices should usually store notification preferences on a backend so that the settings follow the user across devices.
23.1 Example Preference Object
{
"userId": "USER_123",
"notifications": {
"orderUpdates": true,
"messages": true,
"reminders": false,
"marketing": false
},
"updatedAt": "2026-10-21T00:00:00Z"
}
This is an illustrative data structure. Use your application's actual user identifier and timestamp.
23.2 Recommended Backend Behavior
- Provide an authenticated endpoint to retrieve notification preferences.
- Allow users to update preferences securely.
- Validate preference names and values on the server.
- Use the latest saved preferences before sending category-specific notifications.
- Synchronize settings across a user's devices where appropriate.
- Record relevant changes for debugging and compliance when necessary.
- Keep marketing consent separate from system notification permission where required.
23.3 Example API Request
PATCH /api/me/notification-preferences
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN
{
"orderUpdates": true,
"messages": true,
"reminders": false,
"marketing": false
}
The endpoint and payload are illustrative. Never hardcode a real access token in application source code or course examples.
24. Handling Permission Changes and Token Registration
Remote push notifications commonly require an Expo push token, but permission status and token registration are separate concerns.
A recommended sequence is:
- Create the Android notification channel where required.
- Check the current permission state.
- Request permission if appropriate.
- Check the resulting permission response.
- Obtain the Expo push token when remote notifications are needed and the app is configured correctly.
- Register or update the token with the backend.
- Refresh the permission state when the app returns from device settings.
Example:
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';
export async function getAuthorizedExpoPushToken() {
const permission = await Notifications.getPermissionsAsync();
if (!permission.granted) {
return null;
}
const projectId =
Constants.expoConfig?.extra?.eas?.projectId ??
Constants.easConfig?.projectId;
if (!projectId) {
throw new Error('EAS project ID is missing.');
}
const result = await Notifications.getExpoPushTokenAsync({
projectId
});
return result.data;
}
This example checks the overall granted flag for simplicity. If your application supports provisional authorization on iOS, interpret the iOS-specific status as described in the current Expo documentation.
25. Testing Notification Permission Behavior
Permission handling should be tested in multiple states. A single successful permission request does not prove that the application correctly handles every user choice.
| Test Case |
Expected Behavior |
| First application launch |
The application explains the value of notifications before requesting permission at the appropriate time. |
| Permission granted |
The app updates its permission state and can continue with notification registration. |
| Permission denied |
The app continues to work and displays a useful explanation. |
| Permission disabled in device settings |
The app refreshes permission status when it returns to the foreground. |
| Marketing preference disabled |
The backend excludes the user from optional marketing notifications. |
| Sound disabled at the system level |
The app does not promise that notification sounds will play. |
| Badge permission unavailable |
The app handles the result without crashing. |
| Local preference storage fails |
The app displays an appropriate error or uses a safe fallback. |
| Backend preference update fails |
The app informs the user and follows a defined retry or rollback strategy. |
| Notification permission changes while the app is inactive |
The app refreshes its state when it returns to the foreground. |
26. Common Errors and Troubleshooting
| Problem |
Possible Cause |
Solution |
| Permission prompt does not appear |
Permission was previously decided, platform behavior differs, or Android channel setup is missing. |
Check current status, create the channel on Android, and guide the user to settings if needed. |
| Notifications remain disabled after granting permission |
The app's own category preferences may still be disabled. |
Inspect both system permissions and application preferences. |
| Sound does not play |
System sound settings or notification channel settings may disable it. |
Inspect the relevant system settings and permission response. |
| Badge count does not update |
Badge permission or launcher support may be unavailable. |
Check the returned result and treat badges as an optional feature. |
| Settings screen shows outdated permission status |
The user changed permissions while the app was inactive. |
Refresh permissions when the app returns to the foreground. |
| Preferences reset after restarting the app |
Preferences were kept only in component state. |
Persist settings with AsyncStorage or a backend. |
| Marketing notifications still arrive |
The backend does not enforce the user's saved preference. |
Check the latest preference on the server before sending optional messages. |
| Token registration fails |
Missing EAS project ID, invalid configuration, network problems, or missing credentials. |
Inspect the error, verify project configuration, and retry appropriately. |
| Repeated permission alerts appear |
The app repeatedly requests permission instead of checking the existing state. |
Check permissions first and avoid repeated prompts. |
27. Security and Privacy Best Practices
- Respect the user's decision to enable or disable notifications.
- Request only the permissions required for the application's functionality.
- Do not include passwords, access tokens, or sensitive personal information in notification content.
- Protect push tokens and account information during backend registration.
- Validate user identity before updating account-specific preferences.
- Enforce category preferences on the backend, not only in the UI.
- Separate optional marketing preferences from essential service messages.
- Provide a clear way to change notification preferences.
- Do not use notification permission as a condition for unrelated application features.
- Respect relevant privacy, consumer protection, and marketing consent requirements.
- Explain whether preferences apply to one device or to all devices associated with the account.
28. Mini Project: Notification Settings Manager
Project objective: Build a React Native screen that lets users inspect notification permissions and manage their notification preferences.
Project Requirements
- Create a React Native application with Expo.
- Install
expo-notifications.
- Display the current system permission status.
- Provide a button to request notification permission.
- Provide a button to open device settings when required.
- Create switches for messages, order updates, reminders, and marketing.
- Save preferences locally using AsyncStorage.
- Refresh the permission status when the app returns to the foreground.
- Show appropriate messages for granted and denied permissions.
- Optionally synchronize preferences with a backend API.
Expected Result
The user can view the current permission status, request permission, open device settings, and configure notification categories. Preferences persist between application sessions, and the application responds correctly when system permissions change.
29. Practical Exercises
- Install Expo Notifications in a new Expo project.
- Write a function that checks the current notification permission status.
- Write a function that requests permission and handles the response.
- Create an Android notification channel before requesting permission.
- Design an explanatory screen that appears before the system prompt.
- Handle the case in which the user denies permission.
- Add an option to open device settings.
- Create switches for four notification categories.
- Persist the switches' values using AsyncStorage.
- Refresh permission status when the app returns to the foreground.
- Build a backend endpoint for storing user notification preferences.
- Test the application with system permission granted and denied.
30. Interview Questions and Answers
Q1. What are notification permissions?
They are operating-system authorizations that determine whether an application can present notifications and use supported notification features.
Q2. What is the purpose of getPermissionsAsync()?
It checks the current notification permission state without showing a permission prompt.
Q3. What does requestPermissionsAsync() do?
It requests notification authorization from the operating system and returns a permission response.
Q4. What is the difference between system permission and user preferences?
System permission controls what the operating system allows. Application preferences control which categories of messages the user wants from the application.
Q5. Why should an app explain notification permissions first?
An explanation helps users understand the benefit of notifications and make an informed decision.
Q6. How should an app handle denied permission?
It should continue to work where possible, explain the consequences, avoid repeatedly requesting permission, and provide a route to device settings when appropriate.
Q7. Why are Android notification channels important?
Channels organize notifications into categories and allow users to control category-specific behavior. A channel must be created before the normal notification permission prompt can appear on Android 13 and later.
Q8. Why should notification preferences be saved?
Persistence ensures that a user's choices remain available after the application restarts and can be synchronized across devices when stored on a backend.
Q9. Why should preferences also be checked on the backend?
Because remote notifications are often sent by the server. Client-side switches alone cannot prevent the server from sending a disabled category.
Q10. How can an app detect permission changes made in device settings?
It can refresh permission status when the app returns to the foreground, for example by listening to React Native's AppState changes.
Q11. Does granted notification permission guarantee that every notification appears?
No. Delivery, system settings, channel configuration, network conditions, and other platform restrictions can affect notification behavior.
Q12. What should an application do if sound or badges are disabled?
Respect the current system setting, inspect granular permission information where available, and avoid promising behavior that the operating system does not allow.
31. Quick Revision Checklist
- Install and configure
expo-notifications.
- Check the existing permission state before requesting authorization.
- Explain why notifications are useful before displaying the system prompt.
- Create Android notification channels where required.
- Handle granted, denied, and provisional states appropriately.
- Guide users to device settings when they need to change system permissions.
- Refresh permission status when the app returns to the foreground.
- Separate system permissions from application-level notification preferences.
- Persist preferences locally or on a backend.
- Enforce notification category preferences on the server.
- Respect sound, badge, and display restrictions set by the operating system.
- Test permission states on physical Android and iOS devices.
- Protect user data and respect privacy and marketing consent requirements.
32. Official Learning Resources
33. Conclusion
Handling notification permissions and user preferences is an essential part of building a reliable React Native application. Developers must understand operating-system permission states, request authorization at the right moment, handle denial gracefully, and provide controls for notification categories.
A complete implementation also persists preferences, refreshes system permission status when users return from settings, respects Android notification channels and iOS permission options, and enforces user choices on the backend before sending remote notifications.
By following these practices, developers can create a notification experience that is useful, privacy-conscious, reliable, and respectful of user choice.
To learn more about React Native development, visit JustAcademy's React Native Training or register for a course demo.