I’m developing a React Native Expo mobile app. Now I’m going to use expo-notifications
library to show reminder push notifications. I want reminders to be displayed at a specific time (for example, 8 a.m.) if the user has not opened the app for more than 4 hours. I’ve already implemented showing notifications at a specific time. But I have a problem keeping track of when the app was last opened.
import Constants from "expo-constants";
import * as Device from "expo-device";
import { useFonts } from "expo-font";
import * as Notifications from "expo-notifications";
import * as SplashScreen from "expo-splash-screen";
import { StatusBar } from "expo-status-bar";
import React, { useCallback, useEffect } from "react";
import { View, Platform } from "react-native";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import Navigation from "./src/navigation";
import { store, persistor } from "./src/store";
import styles from "./styles";
SplashScreen.preventAutoHideAsync();
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
export default function App() {
const [fontsLoaded, fontError] = useFonts({
mainReg: require("./assets/fonts/DINReg.otf"),
mainMed: require("./assets/fonts/DINMed.otf"),
mainBold: require("./assets/fonts/DINBold.otf"),
});
const onLayoutRootView = useCallback(async () => {
if (fontsLoaded || fontError) {
await SplashScreen.hideAsync();
}
}, [fontsLoaded, fontError]);
useEffect(() => {
registerForPushNotificationsAsync();
scheduleReminderNotification();
}, []);
async function scheduleReminderNotification() {
const now = new Date();
const trigger = new Date();
trigger.setHours(8, 0, 0); // Set to 8:00 AM local time
if (trigger <= now) {
trigger.setDate(trigger.getDate() + 1); // If 8:00 AM has already passed today, set for tomorrow
}
await Notifications.scheduleNotificationAsync({
content: {
title: "Reminder",
body: "You haven't opened the app for more than 4 hours. Check out now!",
},
trigger,
});
}
if (!fontsLoaded && !fontError) {
return null;
}
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<SafeAreaProvider>
<View style={styles.container} onLayout={onLayoutRootView}>
<Navigation />
<StatusBar style="auto" />
</View>
</SafeAreaProvider>
</PersistGate>
</Provider>
);
}
async function registerForPushNotificationsAsync() {
let token;
if (Platform.OS === "android") {
await Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C",
});
}
if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
try {
const projectId = Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
if (!projectId) {
throw new Error("Project ID not found");
}
token = (
await Notifications.getExpoPushTokenAsync({
projectId,
})
).data;
console.log(token);
} catch (e) {
token = `${e}`;
}
} else {
alert("Must use physical device for Push Notifications");
}
return token;
}