Advanced Notifications
Rich push notifications with images, notification channels, badge counts, and scheduled local notifications.
Advanced Notifications
Beyond basic push notifications, ScaleRocket Mobile supports rich notifications with images, Android notification channels, badge counts, and scheduled local notifications.
Rich Notifications
Send notifications with images and custom content:
import * as Notifications from "expo-notifications";
// Schedule a rich local notification
await Notifications.scheduleNotificationAsync({
content: {
title: "New Message",
subtitle: "From John Doe",
body: "Hey, check out this photo from the trip!",
data: { screen: "/messages/123" },
attachments: [
{
url: "https://example.com/photo.jpg",
identifier: "photo",
},
],
},
trigger: null, // Send immediately
});Notification Channels (Android)
Android 8+ requires notification channels. Create channels for different notification types:
import * as Notifications from "expo-notifications";
import { Platform } from "react-native";
async function setupNotificationChannels() {
if (Platform.OS !== "android") return;
await Notifications.setNotificationChannelAsync("messages", {
name: "Messages",
importance: Notifications.AndroidImportance.HIGH,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#3B82F6",
sound: "default",
});
await Notifications.setNotificationChannelAsync("marketing", {
name: "Promotions",
importance: Notifications.AndroidImportance.LOW,
sound: null,
});
await Notifications.setNotificationChannelAsync("alerts", {
name: "Alerts",
importance: Notifications.AndroidImportance.MAX,
sound: "default",
enableVibrate: true,
});
}| Importance | Behavior |
|---|---|
MAX | Sound, vibration, heads-up display |
HIGH | Sound, vibration |
DEFAULT | Sound |
LOW | No sound, appears in shade |
MIN | No sound, no visual interruption |
Badge Count
Update the app icon badge number:
import * as Notifications from "expo-notifications";
// Set badge count
await Notifications.setBadgeCountAsync(5);
// Clear badge count
await Notifications.setBadgeCountAsync(0);
// Get current badge count
const count = await Notifications.getBadgeCountAsync();Clear the badge when the user opens the app:
// app/_layout.tsx
useEffect(() => {
Notifications.setBadgeCountAsync(0);
}, []);Scheduled Local Notifications
Schedule notifications for future delivery without a server:
// Notify in 30 minutes
await Notifications.scheduleNotificationAsync({
content: {
title: "Reminder",
body: "Don't forget to complete your profile!",
},
trigger: {
seconds: 30 * 60,
type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL,
},
});
// Notify at a specific date
await Notifications.scheduleNotificationAsync({
content: {
title: "Weekly Report",
body: "Your weekly summary is ready",
},
trigger: {
weekday: 1, // Monday
hour: 9,
minute: 0,
type: Notifications.SchedulableTriggerInputTypes.CALENDAR,
repeats: true,
},
});Cancel Scheduled Notifications
// Cancel a specific notification
const id = await Notifications.scheduleNotificationAsync({ ... });
await Notifications.cancelScheduledNotificationAsync(id);
// Cancel all scheduled notifications
await Notifications.cancelAllScheduledNotificationsAsync();Notification Handlers
Configure how notifications behave when the app is in the foreground:
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true, // Show even when app is open
shouldPlaySound: true,
shouldSetBadge: true,
}),
});Handling Notification Taps
Navigate to the relevant screen when a notification is tapped:
import { useEffect } from "react";
import { router } from "expo-router";
import * as Notifications from "expo-notifications";
function useNotificationNavigation() {
useEffect(() => {
const subscription = Notifications.addNotificationResponseReceivedListener(
(response) => {
const data = response.notification.request.content.data;
if (data.screen) {
router.push(data.screen as string);
}
}
);
return () => subscription.remove();
}, []);
}Notification Preferences
Let users control which notifications they receive:
function NotificationSettings() {
const [messages, setMessages] = useState(true);
const [marketing, setMarketing] = useState(false);
return (
<View>
<View style={styles.row}>
<Text>Messages</Text>
<Switch value={messages} onValueChange={setMessages} />
</View>
<View style={styles.row}>
<Text>Promotions</Text>
<Switch value={marketing} onValueChange={setMarketing} />
</View>
</View>
);
}Store preferences and send them to your backend so the server only sends relevant notifications.