pushy/pushy-react-native

How to get iOS banner when app is in foreground?

Closed this issue · 2 comments

Since the setNotificationListener has to sit outside of the component I rely on the setNotificationClickListener to pass the data to my component state. This works fine in Android but in iOS when the app is in the foreground I get an alert instead of the banner so the setNotificationClickListener doesn't get triggered.

My question is if it's possible to get a banner to show up. If not is there another way to pass the data from the notification to my component state?

I ended up using EventEmitter to create a direct channel with my React Native component. I am not sure if that's the best way to do it or not but it works fine. The only thing I have to figure out is how to auto dismiss or suppress Android notification in the drawer when the app is in the foreground.

Here is my code in case it helps someone else.

import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import MainTabBar from './src/navigation/mainTabBar';
import FlashMessage from 'react-native-flash-message';
import RNBootSplash from 'react-native-bootsplash';
import {StatusBar, Platform} from 'react-native';
import {navigationRef} from './src/components/navigationProps';
import Pushy from 'pushy-react-native';
import NotificationHandler from './src/utils/notification';
import auth from '@react-native-firebase/auth';
import firestore from '@react-native-firebase/firestore';
import AsyncStorage from '@react-native-community/async-storage';
import EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';
const emitter = new EventEmitter();
Pushy.setNotificationListener(async data => {
  // Print notification payload data
  console.log('Received notification: ' + JSON.stringify(data));
  emitter.emit('forgroundNotification', data);
  if (Platform.OS === 'android') {
    let notificationTitle = 'Gazebo';
    let notificationText = data.message || 'Test notification';
    Pushy.notify(notificationTitle, notificationText, data);
  }
});

class App extends React.Component {
  state = {
    notification: '',
  };
  async componentDidMount() {
    RNBootSplash.hide({duration: 250});
    // Start the Pushy service
    Pushy.listen();
    // Register the device for push notifications
    // Register the user for push notifications
    if (Platform.OS === 'android') {
      // Enable FCM fallback delivery
      Pushy.toggleFCM(true);
    }
    Pushy.register()
      .then(async deviceToken => {
        // Display an alert with device token

        try {
          await AsyncStorage.setItem('@deviceToken', deviceToken);
          console.log('Data successfully saved');
        } catch (e) {
          console.log('Failed to save the data to the storage');
        }

        const userId = auth().currentUser ? auth().currentUser.uid : null;
        if (userId !== null) {
          await firestore()
            .collection('users')
            .doc(userId)
            .update({
              tokens: firestore.FieldValue.arrayUnion(deviceToken),
            });
        }

        // Send the token to your backend server via an HTTP GET request
        //await fetch('https://your.api.hostname/register/device?token=' + deviceToken);

        // Succeeded, optionally do something to alert the user
      })
      .catch(err => {
        // Handle registration errors
        console.error(err);
      });
    emitter.addListener('forgroundNotification', data => {
      this.setState({notification: data});
    });
  }
  componentWillUnmount() {
    emitter.removeListener();
  }
  render() {
    return (
      <NavigationContainer ref={navigationRef}>
        {Platform.OS === 'ios' ? (
          <StatusBar barStyle="dark-content" translucent={true} />
        ) : null}
        <MainTabBar />
        <NotificationHandler
          notification={this.state.notification}
          clear={() => {
            emitter.emit('forgroundNotification', '');
            this.setState({notification: ''});
          }}
        />
        <FlashMessage position="top" floating={true} />
      </NavigationContainer>
    );
  }
}

export default App;
pushy commented

Hi @hhemmati81,
Thanks for reaching out. Indeed calling Pushy.notify() on iOS will display an alert dialog.

Passing data to your Component via an EventEmitter and displaying the notification in a custom UI element is indeed the way to go to achieve your desired in-app banner behavior 👍