1

Hope everyone is well. I am building a react native app using expo. So I reached the point where i need to implement push notification for my app. So i went to expo documentation on this link

and i made it work, so i started receiving push notification from expo with dummy body and title. But when i called axios to get title and body from server the notification stopped being received. So I need to know the process of how can i make the title and body of the notification being the last record entered into my database which is built using mysql on a server and domaine provider.

here is my last code with the added axios api call (if you change the title and body of push notification to 'dummy string' and remove the arguments from the schedulePushNotification() function it will work normally)

import {
    NavigationContainer,
    DarkTheme,
    DefaultTheme,
} from '@react-navigation/native';
import { StyleSheet } from 'react-native';
import React, { useState, useEffect, useRef } from 'react';
import AppNavigator from './App/navigation/AppNavigator';
import { StatusBar } from 'expo-status-bar';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';

import axios from 'axios';
import { baseApiUrl, apikey } from './App/api/config/apiLinks';

import { EventRegister } from 'react-native-event-listeners';
import themeContext from './App/theme/themeContext';
import theme from './App/theme/theme.js';

Notifications.setNotificationHandler({
    handleNotification: async () => ({
        shouldShowAlert: false,
        shouldPlaySound: false,
        shouldSetBadge: false,
    }),
});

export default function App() {
    const [darkModeOn, setDarkModeOn] = useState(false);
    const [isNotificationOn, setIsNotificationOn] = useState(true);

    const [expoPushToken, setExpoPushToken] = useState('');
    const [notification, setNotification] = useState(false);
    const notificationListener = useRef();
    const responseListener = useRef();

    const [newsTitle, setNewsTitle] = useState('');
    const [newsSource, setNewsSource] = useState('');
    const [newsDescription, setNewsDescription] = useState('');
    const [author, setAuthor] = useState();
    const [newsImage, setNewsImage] = useState('');
    const [newsPubDate, setNewsPubDate] = useState('');
    const [newsFeedName, setNewsFeedName] = useState('');
    const [newsLink, setNewsLink] = useState('');
    const [newsItem, setNewsItem] = useState({});

    const retrieveDarkMode = async () => {
        try {
            const jsonValue = await AsyncStorage.getItem('darkModeOn');

            if (jsonValue !== null) {
                const parsedValue = JSON.parse(jsonValue);
                setDarkModeOn(parsedValue);
            }
        } catch (e) {
            // error reading value
            console.log('error: ', e);
        }
    };

    const retrieveNotification = async () => {
        try {
            const jsonValue = await AsyncStorage.getItem('isNotificationOn');

            if (jsonValue !== null) {
                const parsedValue = JSON.parse(jsonValue);
                setIsNotificationOn(parsedValue);
            }
        } catch (e) {
            // error reading value
            console.log('error: ', e);
        }
    };

    const url = baseApiUrl + '/news/latest-single-news-get.php?' + apikey;

    const displayAuthor = (author) => {
        if (
            author !== 'Editor' &&
            author !== 'F1 Desk' &&
            author !== 'Motorsport Network' &&
            author !== 'RACER Staff' &&
            author !== 'GPblog' &&
            author !== ''
        ) {
            setAuthor('By ' + author);
        } else {
            setAuthor('');
        }
    };

    const loadLatestNews = () => {
        axios
            .get(url)
            .then((response) => {
                setNewsTitle(response.data.data.title);
                setNewsSource(response.data.data.feedName);
                setNewsDescription(response.data.data.description);
                setNewsImage(response.data.data.image);
                setNewsPubDate(response.data.data.pubDate);
                setNewsFeedName(response.data.data.feedName);
                setNewsLink(response.data.data.link);
                displayAuthor(response.data.data.author);
                item = {
                    title: newsTitle,
                    description: newsDescription,
                    author: author,
                    image: newsImage,
                    pubDate: newsPubDate,
                    source: newsSource,
                    feedName: newsFeedName,
                    link: newsLink,
                };
                setNewsItem((newsItem) => ({
                    ...newsItem,
                    ...item,
                }));
            })
            .catch((error) => console.log(error));
    };

    useEffect(() => {
        //retrieveDarkMode();
        let eventListener = EventRegister.addEventListener(
            'changeTheme',
            (data) => {
                setDarkModeOn(data);
            }
        );
        return () => {
            EventRegister.removeAllListeners(eventListener);
        };
    });

    useEffect(() => {
        retrieveDarkMode();
        retrieveNotification();

        registerForPushNotificationsAsync().then((token) => {
            setExpoPushToken(token);
            loadLatestNews();
            if (isNotificationOn) {
                schedulePushNotification(newsSource, newsTitle);
            }
        });

        notificationListener.current =
            Notifications.addNotificationReceivedListener((notification) => {
                setNotification(notification);
            });

        responseListener.current =
            Notifications.addNotificationResponseReceivedListener(
                (response) => {
                    console.log(response);
                }
            );

        // if (isNotificationOn) {
        //     loadLatestNews();
        //     schedulePushNotification();
        // }

        return () => {
            Notifications.removeNotificationSubscription(
                notificationListener.current
            );
            Notifications.removeNotificationSubscription(
                responseListener.current
            );
        };
    }, []);

    return (
        <themeContext.Provider
            value={theme === true ? theme.dark : theme.light}
        >
            <NavigationContainer theme={darkModeOn ? DarkTheme : DefaultTheme}>
                <StatusBar backgroundColor="#fff" hidden={false} />
                <AppNavigator
                    theme={darkModeOn ? theme.dark : theme.light}
                    darkModeOn={darkModeOn}
                />
            </NavigationContainer>
        </themeContext.Provider>
    );
}

async function schedulePushNotification(newsSource, newsTitle) {
    await Notifications.scheduleNotificationAsync({
        content: {
            title: newsSource,
            body: newsTitle,
            data: { data: 'goes here' },
        },
        trigger: { seconds: 30, repeats: true },
    });
}

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;
        }
        token = (await Notifications.getExpoPushTokenAsync()).data;
        console.log(token);
    } else {
        //alert('Must use physical device for Push Notifications');
    }

    return token;
}

const styles = StyleSheet.create({});
f1ian
  • 63
  • 6

1 Answers1

0

You'll have to add title, body and subtitle in expo.chunkPushNotifications as below.

Here is the full example with ExpressJs and NodeJs

    const expo = new Expo({ accessToken: accessTokenFromExpoPortal });

    const chunks = expo.chunkPushNotifications([{
      to: 'ExponentPushToken[Kj-ul2K2fgzxxxxx]',
      sound: 'default',
      title: ' Original Title',
      subtitle: "sub title",
      body: 'This is a test notification',
      data: { withSome: 'data' },
    }]);
    const tickets = [];

    for (const chunk of chunks) {
      try {
        const ticketChunk = await expo.sendPushNotificationsAsync(chunk);
        tickets.push(...ticketChunk);
      } catch (error) {
        console.error(error);
        res.status(500).send(resHelper.generateSuccessRes(200, null, error));
      }
    }

    let response = "";

    for (const ticket of tickets) {
      if (ticket.status === "error") {
        if (ticket.details && ticket.details.error === "DeviceNotRegistered") {
          response = "DeviceNotRegistered";
        } else {
          response = ticket.details.error
        }
      }

      if (ticket.status === "ok") {
        response = ticket.id;
      }
    }
    console.log('--response--', response)

    if (response && response.length === 36) {
      res.status(200).send(resHelper.generateSuccessRes(200, null, { ticket: response }));
    } else {
      res.status(500).send(resHelper.generateSuccessRes(200, null, { error: response }));
    }
Rohit Parte
  • 3,365
  • 26
  • 26
  • I am using php for that, I found out a way to do it, but when i asked the question i did not know the process – f1ian Jul 18 '23 at 16:36