Kurs React Native · Moduł 7: Powiadomienia
Projekt: System powiadomień Atlantydy
Stwórzmy kompletny system powiadomień!
import { useEffect, useRef, useState } from 'react';
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';
import { Platform } from 'react-native';
// Konfiguracja
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowBanner: true,
shouldShowList: true,
shouldPlaySound: true,
shouldSetBadge: true,
}),
});
// Hook do powiadomień
export function useNotifications() {
const [expoPushToken, setExpoPushToken] = useState<string>('');
const [notification, setNotification] = useState<Notifications.Notification>();
const notificationListener = useRef<Notifications.Subscription>();
const responseListener = useRef<Notifications.Subscription>();
useEffect(() => {
// Rejestracja
registerForPushNotificationsAsync().then((token) => {
if (token) setExpoPushToken(token);
});
// Setup kanałów Android
setupAndroidChannels();
// Listenery
notificationListener.current = Notifications.addNotificationReceivedListener(
setNotification
);
responseListener.current = Notifications.addNotificationResponseReceivedListener(
(response) => {
handleNotificationResponse(response);
}
);
return () => {
notificationListener.current?.remove();
responseListener.current?.remove();
};
}, []);
return { expoPushToken, notification };
}
async function registerForPushNotificationsAsync() {
if (!Device.isDevice) {
console.log('Push notifications wymagają urządzenia');
return;
}
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
return;
}
const token = await Notifications.getExpoPushTokenAsync();
return token.data;
}
async function setupAndroidChannels() {
if (Platform.OS !== 'android') return;
await Notifications.setNotificationChannelAsync('default', {
name: 'Domyślne',
importance: Notifications.AndroidImportance.MAX,
});
await Notifications.setNotificationChannelAsync('reminders', {
name: 'Przypomnienia',
importance: Notifications.AndroidImportance.HIGH,
});
}
function handleNotificationResponse(response: Notifications.NotificationResponse) {
const data = response.notification.request.content.data;
// Nawigacja na podstawie data
console.log('Notification data:', data);
}
// Serwisy powiadomień
export const NotificationService = {
// Lokalne powiadomienie
sendLocal: async (title: string, body: string, data?: object) => {
return Notifications.scheduleNotificationAsync({
content: { title, body, data, sound: true },
trigger: null,
});
},
// Przypomnienie
scheduleReminder: async (title: string, body: string, date: Date) => {
return Notifications.scheduleNotificationAsync({
content: { title, body },
trigger: date,
});
},
// Codzienne przypomnienie
scheduleDailyReminder: async (title: string, body: string, hour: number, minute: number) => {
return Notifications.scheduleNotificationAsync({
content: { title, body },
trigger: { hour, minute, repeats: true },
});
},
// Anuluj wszystkie
cancelAll: async () => {
await Notifications.cancelAllScheduledNotificationsAsync();
},
// Wyczyść badge
clearBadge: async () => {
await Notifications.setBadgeCountAsync(0);
},
};Ten system obsługuje rejestrację, lokalne powiadomienia, push notifications i kanały Android!
Kod do tej lekcji: App.tsx
import { View, Text, Button, StyleSheet } from 'react-native';
import * as Notifications from 'expo-notifications';
// Projekt: kompletny serwis powiadomień Atlantydy
export const NotificationService = {
// Lokalne powiadomienie natychmiastowe
sendLocal: async (title: string, body: string, data?: object) => {
// TODO: wywołaj scheduleNotificationAsync z trigger: null
return Notifications.scheduleNotificationAsync({
content: { title, body, data, sound: true },
trigger: null,
});
},
// Przypomnienie na konkretną datę
scheduleReminder: async (title: string, body: string, date: Date) => {
// TODO: ustaw trigger na przekazaną datę
return Notifications.scheduleNotificationAsync({
content: { title, body },
trigger: date,
});
},
// Codzienne przypomnienie o danej godzinie
scheduleDailyReminder: async (title: string, body: string, hour: number, minute: number) => {
// TODO: ustaw trigger { hour, minute, repeats: true }
return Notifications.scheduleNotificationAsync({
content: { title, body },
// TODO: uzupełnij trigger z repeats: true
trigger: { hour, minute, repeats: false },
});
},
// Anuluj wszystkie zaplanowane powiadomienia
cancelAll: async () => {
// TODO: wywołaj cancelAllScheduledNotificationsAsync()
},
// Wyczyść badge na ikonie aplikacji
clearBadge: async () => {
// TODO: ustaw badge na 0 przez setBadgeCountAsync(0)
},
};
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.title}>System powiadomień Atlantydy</Text>
<Button
title="Wyślij lokalne"
onPress={() => NotificationService.sendLocal('Atlantyda', 'Posejdon cię wzywa!')}
/>
<Button title="Wyczyść badge" onPress={NotificationService.clearBadge} />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#1a5276', gap: 16, padding: 20 },
title: { fontSize: 22, color: '#fff', textAlign: 'center' },
});
Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Zadania praktyczne w grze
- Edytor kodu
Uzupełnij kod kompletnego serwisu.