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;
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 👍