запрашивать разрешения: я успешно запрашиваю и получаю предоставленное статус для разрешений уведомлений.
// app.json snippet
Код: Выделить всё
{
"expo": {
"name": "WakeUp",
"slug": "WakeUp",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "wakeup",
"userInterfaceStyle": "automatic",
"newArchEnabled": true,
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#1B1A2C"
},
"edgeToEdgeEnabled": true,
"package": "com.IvnoGood.WakeUp"
},
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#fff8f4",
"dark": {
"backgroundColor": "#18120d",
"image": "./assets/images/splash-icon.png"
}
}
],
"expo-font",
[
"expo-notifications",
{
"color": "#1B1A2C",
"icon": "./assets/images/notificationIcon.png",
"defaultChannel": "default",
"enableBackgroundRemoteNotifications": true
}
],
[
"expo-task-manager",
{
"permissionMessage": "Allow WakeUp to run alarms and other background tasks."
}
]
],
"experiments": {
"typedRoutes": true
},
"extra": {
"router": {},
"eas": {
"projectId": "d6e9fdf5-0dfa-47f0-982a-5aee7b7a5827"
}
}
}
}
Код: Выделить всё
import { startLightUpSequence } from './lightControl';
import * as Notifications from 'expo-notifications';
import * as TaskManager from 'expo-task-manager';
const ALARM_WAKE_UP_TASK = 'ALARM_WAKE_UP_TASK';
export async function setupAllTasksAndPermissions() {
// 1. Define the Task
if (!TaskManager.isTaskDefined(ALARM_WAKE_UP_TASK)) {
TaskManager.defineTask(ALARM_WAKE_UP_TASK, ({ data, error }) => {
if (error) {
console.error('--- TASK MANAGER ERROR ---', error);
return;
}
if (data) {
// This console.log is NEVER called when the app is in the background
console.log('--- BACKGROUND TASK IS RUNNING ---');
const alarmData = data?.notification?.request?.content?.data;
if (alarmData) {
const { alarm, device } = alarmData;
startLightUpSequence({ device, alarm });
}
}
});
}
// 2. Define Notification Categories
await Notifications.setNotificationCategoryAsync('alarm', [
{ identifier: 'stop', buttonTitle: 'Stop' },
]);
// 3. Set Foreground Handler
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: false,
}),
});
}
Код: Выделить всё
import * as Notifications from 'expo-notifications';
import { Platform } from 'react-native';
export async function requestNotificationPermissions() {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
// Stop here if the user did not grant permissions
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return false;
}
// For Android, set a notification channel
if (Platform.OS === 'android') {
await Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
return true;
}
export async function scheduleAlarmNotification(alarm, device) {
// ... (Your logic to calculate triggerDate is here) ...
const now = new Date();
const [hours, minutes] = alarm.startTime.split(":");
let triggerDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), parseInt(hours), parseInt(minutes), 0);
if (triggerDate < now) {
triggerDate.setDate(triggerDate.getDate() + 1);
}
await Notifications.cancelScheduledNotificationAsync(alarm.id);
await Notifications.scheduleNotificationAsync({
identifier: alarm.id,
content: {
title: 'Wake Up!',
body: `Your alarm "${alarm.title}" is starting.`,
sound: 'default',
// --- THIS IS THE CRITICAL PART ---
data: {
// Pass the full alarm and device objects so the task can use them
alarm: alarm,
device: device,
},
categoryIdentifier: 'alarm',
},
// For Task Manager, the trigger can be the Date object directly.
// It will still wake up the task.
trigger: triggerDate,
});
console.log(`Alarm scheduled for ${alarm.title} at ${triggerDate.toLocaleTimeString()}`);
}
import { blink } from '@/components/light/lightUp';
import { setupAllTasksAndPermissions } from '@/components/light/setupApp';
import LightStateProvider from '@/components/provider/LightStateProvider';
import ThemeProvider, { useAppTheme } from '@/components/provider/ThemeProvider';
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as Notifications from 'expo-notifications';
import { Stack, useRouter } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react';
import 'react-native';
import { PaperProvider } from 'react-native-paper';
function Layout() {
const { theme, setThemeName } = useAppTheme();
const router = useRouter()
useEffect(() => {
// --- LISTENER #1: Whe n a notification is RECEIVED while the app is in the foreground ---
const notificationReceivedSubscription = Notifications.addNotificationReceivedListener(notification => {
console.log("FOREGROUND: Notification received!");
// Extract the data payload
const { alarm, device } = notification.request.content.data;
// Check if we have the data we need
if (alarm && device) {
console.log(`FOREGROUND: Manually starting light sequence for alarm "${alarm.title}"`);
// Manually start your light sequence function
blink(device, alarm, false)
} else {
console.warn("FOREGROUND: Notification received, but no alarm/device data found in payload.");
}
});
return () => {
notificationReceivedSubscription.remove();
subscription.remove();
};
}, []);
return (
//All the screens
);
}
export default function RootLayout() {
useEffect(() => {
setupAllTasksAndPermissions()
}, [])
return (
)
}
< /code>
Вы также можете проверить репо Github для получения более подробной информации о моем коде < /p>
Вопрос:
Что мне не хватает, что предотвращает определенное задание TaskManager, когда запланированное уведомление доставляется, когда приложение находится в фоновом режиме или прекращено? Есть ли более прямой способ связать уведомление с задачей, которую я не использую?
Спасибо
Подробнее здесь: https://stackoverflow.com/questions/797 ... on-trigger
Мобильная версия