Frontend, Mobile

Stwórz swój pierwszy system Remote Push w aplikacji React Native

powiadomienie push react native

Czy kiedykolwiek, gdy na telefonie zobaczyłeś powiadomienie, pojawiła się w Twojej głowie myśl, że fajnie byłoby mieć taki system w swojej aplikacji? Może wydaje Ci się, że jest to coś skomplikowanego i dlatego Twoi użytkownicy wciąż nie otrzymują notyfikacji push? Jeśli tak jest, lub jeśli jesteś tu, bo po prostu chcesz wiedzieć jak zabrać się za taki problem to właśnie dla Ciebie jest ten artykuł.

powiadomienie push react

Anna Skrzeszewska. Frontend Developerka w Monterail. Na co dzień pracuje w projektach React oraz React Native. Jest mocno związana z rekrutacją, pełni również funkcję mentorki dla nowo przyjętych do zespołu osób.


Chciałabym przeprowadzić Cię krok po kroku przez to, jak zbudować system Push Notyfikacji w oparciu o Firebase Cloud Message, React Native Firebase oraz Notifee.

Wspólnie stworzymy nowy projekt React Native, który będziemy testować na urządzeniu z systemem Android, uproszczoną wersję backendu obsługującego wysyłanie notyfikacji na urządzenie. Dodatkowo przetestujemy dwa rodzaje powiadomień, żeby zobaczyć różne podejścia.

Mam nadzieję, że na końcu zostawię Cię z poczuciem tego, że implementacja takiego systemu nie jest wcale aż tak trudna i może wykorzystasz zdobytą wiedzę w swoim projekcie.

Zatem zaczynajmy!

Tworzenie nowego projektu React Native

Pod tym adresem znajdziesz dokładną dokumentację i opis tego, jak utworzyć projekt React Native oraz informację o wszystkich zależnościach jakich potrzebujesz, aby uruchomić ten projekt.

Zakładając, że masz zainstalowane wszystkie zależności wymienione wyżej, użyj poniższej komendy, aby zainicjować projekt:

> npx react-native init notifications-test

Dodatkowo zainstaluj potrzebne biblioteki:

> npm i react-native-firebase/app react-native-firebase/messaging
> npm install --save @notifee/react-native

Po utworzeniu projektu otwórz go w swoim ulubionym edytorze (VS Code, Sublime) i zastąp zawartość pliku App.js poniższym kawałkiem kodu:

import React from 'react';
import {Button, SafeAreaView, StyleSheet, Text, View} from 'react-native';
 
const App = () => {
 const handleSendNotification = () => {
   return;
 };
 
 const handleSetTheAlarm = () => {
   return;
 };
 
 return (
   <SafeAreaView style={styles.wrapper}>
     <Text>PUSH NOTIFICATIONS TEST</Text>
     <View style={styles.buttonsWrapper}>
       <View style={styles.buttonWrapper}>
         <Button title="SEND NOTIFICATION" onPress={handleSendNotification} />
       </View>
       <View style={styles.buttonWrapper}>
         <Button
           title="SET ALARM"
           color="red"
           onPress={handleSetTheAlarm}
         />
       </View>
     </View>
   </SafeAreaView>
 );
};
 
const styles = StyleSheet.create({
 wrapper: {
   flex: 1,
   justifyContent: 'center',
   alignItems: 'center',
   padding: 20,
   backgroundColor: 'white',
 },
 buttonsWrapper: {
   marginTop: 50,
 },
 buttonWrapper: {
   marginBottom: 20,
 },
});
 
export default App;

Następnie uruchom aplikację. Rezultatem powinien być poniższy ekran.

ekran push

Tworzenie projektu Firebase

Następnie utwórz projekt w Firebase Console. Ten link zawiera instrukcję krok po kroku, jak należy to zrobić.

Kolejnym krokiem jest dodanie Firebase do projektu React Native.

Aplikacja będzie testowana na urządzeniu z systemem Android, dlatego po wybraniu tego typu aplikacji przejdź przez wszystkie kroki – niektóre z nich będą wymagać zmian w kodzie aplikacji.

Tworzenie części serwerowej

W wybranym miejscu na dysku należy stworzyć nowy folder np. „notifications-test-api”. Dodaj w nim plik index.js, w którym umieszczony zostanie kod. Poniższe komendy zainicjują nowy projekt node.js oraz zainstalują wszystkie potrzebne zależności.

> npm init
> npm install fastify firebase-admin nodemon

Aby backend mógł działać z Firebasem należy pobrać serviceAccountKey, który musi zostać dodany do folderu z projektem.

W celu pobrania tego pliku należy otworzyć projekt Firebase → wejść w ustawienia projektu, a następnie w zakładkę Service accounts i wybrać w przycisk Generate new private key.

react native powiadomienie aplikacja

Kolejnym etapem będzie wklejenie poniższego kodu do pliku index.js i podmiana ścieżki prowadzącej do wcześniej pobranego pliku.

const admin = require("firebase-admin");
const fastify = require("fastify")({ logger: true, keepAliveTimeout: 5000 });
const util = require("util");

// Zastąp "path/to/serviceAccountKey.json"
const serviceAccount = require("path/to/serviceAccountKey.json");

const delay = util.promisify(setTimeout);

// Initialize Firebase
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

// Remote Push Notification
async function sendAlarmNotification(token) {
  return admin.messaging().send({
    token,
    notification: {
      body: "Hi here's your alarm",
      title: "It's time to wake up",
    },
    data: {
      type: "alarmNotification",
    },
  });
}

// Partial Push Notification
async function sendPartialNotification(token) {
  return admin.messaging().send({
    token,
    data: {
      type: "partial_notification",
      notifee: JSON.stringify({
        body: "I'm your push notification",
        android: {
          channelId: "default",
        },
      }),
    },
  });
}

// Declare a notification route
fastify.post("/notifications", async (request) => {
  await delay(5000);
  await sendPartialNotification(JSON.parse(request.body).token);
  return "OK";
});

// Declare a alarm route
fastify.post("/alarm", async (request) => {
  await delay(5000);
  await sendAlarmNotification(JSON.parse(request.body).token);
  return "OK";
});

// Run the server
const start = async () => {
  try {
    await fastify.listen(3000);
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};
start();

Teraz mamy działający serwer! Można go uruchomić za pomocą komendy:

Poniższa funkcja jest odpowiedzialna za wysyłanie wiadomości z kluczami notification oraz data. Wiadomości wysyłane w takim formacie spowodują to, że Push Notyfikacja pojawi się na urządzeniu i zostanie wyświetlona przez system operacyjny. Nasza aplikacja nie ma wpływu na wyświetlanie tego typu powiadomień.

// Remote Push Notification
async function sendAlarmNotification(token) {
  return admin.messaging().send({
    token,
    notification: {
      body: "Hi here's your alarm",
      title: "It's time to wake up",
    },
    data: {
      type: "alarmNotification",
    },
  });
}

W drugim przypadku, wiadomość zostanie wysłana tylko z kluczem data. Taka notyfikacja nie wyświetli się automatycznie. W celu wyświetlenia takiego powiadomienia musimy zaimplementować logikę, która je obsłuży.

Na potrzeby tego artykułu zastosowana została funkcja setTimeout, która będzie opóźniać wysyłanie wiadomości tak, aby mieć czas na zamknięcie aplikacji po naciśnięciu przycisku wysyłającego zapytania do serwera. Notyfikacja pojawi się na urządzeniu tylko wtedy, kiedy aplikacja będzie zminimalizowana. Więcej możesz poczytać o tym tu.

Obsługa i wyświetlanie Remote Push Notyfikacji na urządzeniu

Ostatnim etapem jest zaimplementowanie obsługi notyfikacji push w naszej aplikacji React Native tj.:

  • rejestracja urządzenia w Firebase Cloud Messages,
  • pobranie zarejestrowanego tokenu,
  • jako uproszczenie przesyłać będziemy token w każdym zapytaniu do serwera, jest to wymagane, żeby serwer mógł zidentyfikować adresatów Push Notyfikacji (w realnym projekcie sugeruję, by był on przetrzymywany, np: w bazie danych).

Te założenia spełnia poniższy kod, który należy dodać do App.js.

const [token, setToken] = useState('');

  const getFirebaseToken = async () => {
    // Register the device with FCM
    await messaging().registerDeviceForRemoteMessages();

    // Get the token
    const generatedToken = await messaging().getToken();

    return generatedToken;
  };

  useEffect(() => {
    async function fetchData() {
      const generatedToken = await getFirebaseToken();
      setToken(generatedToken);
    }
    fetchData();
  }, []);

W celu zareagowania przez aplikację na przychodzące powiadomienie React Native Firebase udostępnia dwie metody: onMessage oraz setBackgroundMessageHandler. W tym projekcie użyjemy funkcji setBackgroundMessageHandler, która obsługuje komunikaty z FCM, gdy aplikacja działa w tle (jest to warunek konieczny, aby zobaczyć notyfikacje na urządzeniu).

useEffect(() => {
    messaging().setBackgroundMessageHandler(onMessageReceived);
  }, []);setBackgroundMessageHandler przyjmuje funkcję, która zostaje wywołana w ramach reakcji na to zdarzenie.
const onMessageReceived = async message => {
	// do sth
	};

Na tym etapie możemy już wysłać pierwszą notyfikację. Zacznijmy od tej, która została zdefiniowana po stronie serwera z kluczami notification i data. Żeby ją zobaczyć należy dodać funkcję, która zostanie później użyta podczas obsługi naciśnięcia na przycisk 'SET ALARM’.

const handleSetTheAlarm = () => {
    fetch(`${BASE_URL}/alarm`, {
      method: 'POST',
      body: JSON.stringify({
        token,
      }),
    });
  };

Po naciśnięciu przycisku, serwer otrzyma zapytanie i wyśle z opóźnieniem (ok. 10s) powiadomienie przez FCM. Pamiętaj, że pojawi się ono dopiero, gdy wyjdziesz z aplikacji (aplikacja będzie działać w tle). Po chwili będzie można zobaczyć swoją pierwszą notyfikację, która została wyświetlona przez system operacyjny.

powiadomienie react native

Pamiętaj, że teraz możesz napisać obsługę takiej notyfikacji w funkcji onMessageReceived(notification). Możesz np. spróbować dodać do swojego projektu nawigację i po kliknięciu na taką notyfikację przenieść się w inne miejsce aplikacji.

Notifee

Teraz pokażę Ci jak możemy wykorzystać zainstalowaną bibliotekę Notifee, tak aby obsłużyć drugi rodzaj notyfikacji, czyli takiej, która została zdefiniowana po stronie serwera tylko z kluczem data.

Tym razem musisz zaimplementować obsługę takiej notyfikacji w funkcji onMessageReceived(notification).

Zdefiniowana na serwerze wiadomość posiada pole type:

data: {
      type: "partial_notification",
      ...
    },

Można użyć go to tego, by rozpoznać, jaka notyfikacja została wysłana na urządzenie i odpowiednio ją obsłużyć.

const onMessageReceived = async message => {
    if (!message || !message.data || !message.data.type) {
      return;
    }
    if (message.data.type === 'partial_notification') {
			// add code to display notification
    }
  };

Teraz, podczas testowania notyfikacji, która została zdefiniowana tylko z kluczem data, nie zostanie ona wyświetlona na urządzeniu tak, jak poprzednim razem. W tym celu wykorzystamy bibliotekę Notifee, żeby ją wyświetlić.

Notyfikacja wyświetlona zostanie przy użyciu metody displayNotification z biblioteki Notifee.

displayNotification(notification: Notification): Promise<string>;

Funkcja ta jako parametr przyjmuje obiekt typu Notification, w naszym przypadku chcemy wyświetlić notyfikacje, która składa się z tytułu oraz treści. Dodatkowo przy wyświetlaniu notyfikacji na urządzeniu z systemem Android wymagane jest aby przekazać dodatkowy parametr channelId.

Więcej informacji znajdziesz tutaj.

const onMessageReceived = async message => {
    if (!message || !message.data || !message.data.type) {
      return;
    }
    if (message.data.type === 'partial_notification') {
			// Transormowanie danych do obiektu
      const notifeeData = JSON.parse(message.data.notifee);
      await notifee.displayNotification({
        title:
          '<p style="color: #4caf50;"><b>Hello! I was defined on frontend</span></p></b></p> &#128576;',
        body: notifeeData.body,
        android: {
          channelId,
        },
      });
    }
  };

Następnie należy zdefiniować funkcję, którą będziemy wywoływać po naciśnięciu w przycisk 'SEND NOTIFICATION’.

const handleSendNotification = () => {
    fetch(`${BASE_URL}/notifications`, {
      method: 'POST',
      body: JSON.stringify({
        token,
      }),
    });
  };

Gotowe! Tak jak ostatnio, po naciśnięciu przycisku i zminimalizowaniu aplikacji, wynikiem będzie pojawienie się poniższej notyfikacji na urządzeniu.

powiadomienie push

Podsumowanie

Mam nadzieję, że z tym poradnikiem uda Wam się ustawić pierwszą notyfikację push. Pochwalcie się w komentarzach, jaki komunikat przygotowaliście, a jeśli macie jakiś pytania, śmiało zostawiajcie je właśnie w sekcji komentarzy.

 

Zdjęcie główne artykułu pochodzi z unsplash.com.

Podobne artykuły

[wpdevart_facebook_comment curent_url="https://geek.justjoin.it/stworz-swoj-pierwszy-system-remote-push-w-aplikacji-react-native/" order_type="social" width="100%" count_of_comments="8" ]