I'm facing a really troubling issue with my React Native app and Pushwoosh.
If I close my app completely and send a notification from Pushwoosh control panel, it appears, I tap on it on my phone and my app receive push info.
But if my app is in background (for example, I've already opened it and just press "Home" button on my phone) and I send the notificacion from control panel, it appears, I tap on it BUT my app won't receive any push data.
It seems like onPushHandler function is being unregistered if my app is in background.
Here is my code (I removed a lot of useless code for this purpose):
import React, {
Component,
} from 'react';
import {
AppRegistry,
} from 'react-native';
class App extends Component {
constructor(props) {
super(props);
this.state = {};
this.pushHandler = this.pushHandler.bind(this);
}
componentDidMount() {
Pushwoosh.init(/* myconfig */);
Pushwoosh.register(
(token) => {
console.log('✓ Registered for pushes');
},
(error) => {
console.error('Failed to register: ' + error);
}
);
Pushwoosh.onPushOpen(this.pushHandler);
}
render() {
return (
<View><Text>Test</Text></View>
);
}
pushHandler(pushData) {
console.log(pushData);
Pushwoosh.onPushOpen(this.pushHandler);
}
}
AppRegistry.registerComponent('MyApp', () => App);
Related
I am implementing a react-native app that receives firebase push notification. When a notification arrives the app navigate to a screen to show the notification.
I followed this approach using reference:
"Navigating without the navigation prop"
https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
When I tested this with debug mode, it works perfectly. But when I tested in release mode (android signed app) it does not work.
Especially, when the notification arrives when the app is open, it does not work. There is no error message and the app become freezing and in a 30 seconds or so, the app crashes.
Here are package info:
"react": "16.8.3",
"react-i18next": "10.12.2",
"react-native": "0.59.10",
"react-native-firebase": "5.5.6",
"react-native-gesture-handler": "1.3.0",
"react-navigation": "3.11.1",
Basically, I tried this
"Navigating without the navigation prop"
https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
Similarly, this one too:
https://github.com/react-navigation/react-navigation/issues/742
I am using not class component but functional component.
// Navigator.js
const switchNavigator = createSwitchNavigator({
ResolveAuth: ResolveAuthScreen,
loginFlow: createStackNavigator({
Signin: SigninScreen,
Signup: SignupScreen
}),
helpFlow: createStackNavigator({
Help: HelpScreen,
}, {headerLayoutPreset: 'center'}),
mainFlow: createBottomTabNavigator({
Ask: createStackNavigator({
AskMain: AskScreen,
AskWait: AskWaitScreen,
}, {headerLayoutPreset: 'center'}),
Chat: createStackNavigator({
ChatList: ChatListScreen,
Chatting: ChatScreen,
}, {headerLayoutPreset: 'center'}),
Profile: createStackNavigator({
Account: AccountScreen,
AccountEdit: AccountEditScreen,
ProfileContract: ProfileScreen
}
, {headerLayoutPreset: 'center'})
},
...
export default createAppContainer(switchNavigator);
// App.js
import Navigator from './Navigator';
import { useTranslation } from 'react-i18next';
import { navigate, setNavigator } from './src/navigationRef';
const App = Navigator;
export default () => {
// setup language
const { t } = useTranslation();
// use effect
useEffect(() => {
// notification listener (triggered when a particular notification has been received)
// if the app is foreground, we need to navigate the screen
const listenerFG = firebase.notifications().onNotification((notification: Notification) => {
console.log('onNotification', notification);
Alert.alert(
t('AppScreen.title'),
t('AppScreen.message'),
[
{text: t('yes'), onPress: () => navigate('Help', { notificationBody: notification })},
],
{cancelable: true},
);
});
listenerForAppClosed();
return () => {
listenerFG();
}
}, []);
return (
<App ref={(navigator) => { setNavigator(navigator) }} />
);
// navigationRef.js
import { NavigationActions } from 'react-navigation';
let navigator;
// nav is coming from react navigation
export const setNavigator = navRef => {
console.log('navigation ref', navRef);
// set navigator
navigator = navRef;
};
export const navigate = (routeName, params) => {
console.log('[navigate dispatch] navigator', navigator);
navigator.dispatch(
NavigationActions.navigate({
routeName,
params
})
);
};
In debug mode, using `navigate('any screen') works like a charm, but in release mode, it does not work.
But one strange thing is that the following navigation works. A user opens a push notification when the app is not foreground state.
// part of App.js
// listen the notification being opened or clicked when the app is closed
const listenerForAppClosed = async() => {
// app closed
const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
// app was opened by a notification
console.log('getInitialNotification', notificationOpen);
// get information about the notification that was opened
const notification: Notification = notificationOpen.notification;
//// ignore the same notification id since the same notification is received again, don't know why.
// get noti id from storage
const notiId = await AsyncStorage.getItem('notiId');
// set noti id to storage
await AsyncStorage.setItem('notiId', notification.notificationId);
if (notification.notificationId === notiId) {
console.log('notification id is the same');
} else {
console.log('navigating to helpscreen...');
// navigate to Help screen
navigate('Help', { notificationBody: notification });
}
}
}
The problem happens both on Android emulator and a device (Android9).
Why the navigate('Help') does not work in release mode? I searched many documents and I feel that it should work in release mode too.
Is there any other way to navigate to a screen from top-level (like App.js)?
I found the source of the problem.
I tested several things.
I wanted to know that whether very simple app in release mode navigates properly.
So, I just followed this posting:
https://medium.com/#katharinep/firebase-notification-integration-in-react-native-0-60-3a8d6c8d56ff
Here are what I did:
- created two screens: Home and Notification.
- Re-created the app with latest react-native#0.60.6 and react-navigation#4.0.9
- sent cloud message not from the app but from the firebase cloud messaging
It worked! When a notificaiton arrives the app navigated to the notification screen.
So I tried to track down the source of the problem.
- tried to add more screens
- added more providers and context
- sent message from the app
Finally, I found the source. It was how I used 'navigateRef.js'
Originally I used it like this:
// App.js
import { navigate, setNavigator } from './src/navigationRef';
<App ref={(navigator) => { setNavigator(navigator) }} />
// navigationRef.js
import { NavigationActions } from 'react-navigation';
let navigator;
// nav is coming from react navigation
export const setNavigator = navRef => {
console.log('navigation ref', navRef);
// set navigator
navigator = navRef;
};
export const navigate = (routeName, params) => {
console.log('[navigate dispatch] navigator', navigator);
navigator.dispatch(
NavigationActions.navigate({
routeName,
params
})
);
};
I simply used the exact the code from react-navigation:
https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
// App.js
import NavigationService from './src/NavigationService';
<App
ref={navigationRef =>
{NavigationService.setTopLevelNavigator(navigationRef);}}
/>
// NavigationService.js
import { NavigationActions } from 'react-navigation';
let _navigator;
function setTopLevelNavigator(navigatorRef) {
_navigator = navigatorRef;
}
function navigate(routeName, params) {
_navigator.dispatch(
NavigationActions.navigate({
routeName,
params,
})
);
}
// add other navigation functions that you need and export them
export default {
navigate,
setTopLevelNavigator,
}
Then I worked! I do not know the difference of these two codes.
The first one worked perfectly in debug mode but not in release mode, especially the app is in foreground.
Could anyone tell me the difference? Why the first code does not work?
I am currently using the headless task to receive a push notification and show the local notification. I am currently using react-native-firebase to integrate firebase cloud messaging.
export default bgMessaging = (message) => {
console.log('hello', message)
return Promise.resolve();
}
This is the piece of code which I am using to create task.
And in index.js
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => bgMessaging);
I am using this to registerHeadlessTask.
But when the app is in the killed state I am not getting any console message and don't if my task is running.
Need help to know how can I debug the background task and show custom notification for the killed state.
I solved it as follows:
// index.js
import { AppRegistry, Alert } from 'react-native';
import messaging from '#react-native-firebase/messaging';
import App from './App';
import { name as appName } from './app.json';
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
});
//receive the message in the background
messaging().onMessage(async teste => {
console.log('teste:', teste);
const novo = (title, message) => {
return Alert.alert(title, message);
};
novo(teste.notification.title, teste.notification.body);
});
AppRegistry.registerComponent(appName, () => App);
This is because we have to validate when the push message arrives in the background in the app
I am new to React Native Application. I am using below code to close the application on clicking of a button.
BackHandler.exitApp();
return false;
But application is not properly ended and still is in Taskbar. So when I try to open the application again, componentWillMount never executes.
I am using below version of React Native.
react-native-cli: 2.0.1
react-native: 0.55.4
Any help or advice on how to cleanly close React Native Application?
Thanks in advance.
Google and Apple won't advice to force quit an application so you should avoid doing that so for better user experience.
If you need to recall a function when your app comes back from background you can use react-native's Appstate API. With Appstate you can listen for app states (active, background and inactive) and run your desired function.
AppState can tell you if the app is in the foreground or background,
and notify you when the state changes.
Below is a sample for requesting data and refreshing the list on every time screen comes back foreground.
Sample
import React, { Component } from 'react';
import { Text, View, FlatList, StyleSheet, AppState } from 'react-native';
export default class App extends Component {
state = {
data: []
}
requestItems = () => {
fetch('someurl').then((response) => response.json()).then((responseJSON) => this.setState({data: responseJSON.data}))
}
componentDidMount() {
this.requestItems()
AppState.addEventListener('change', this.requestItems);
}
componentWillUnmount() {
AppState.removeEventListener('change', this.requestItems);
}
renderItem = ({item}) => <Text>{item.text}</Text>
render() {
if (this.state.data.lenght === 0) return <Text>{'Loading'}</Text>
return (
<View style={styles.container}>
<FlatList data={this.state.data} renderItem={this.renderItem} keyExtractor={(item) => item.id} />
</View>
);
}
}
I'm doing an task for listening message (even in background) and show it on UI.
I have done in listening messages real time. But if the app is in background, it doesn't receive messages in that time.
I ask for any ideas, helps.
I searched HeadlessJS, react-native-background-task but not work for me.
Actually, i want to run this app even in Background and Foreground.
Thank you for advanced.
It's my code until now
index.android.js
//Import libraries
import React, { Component } from 'react';
import {
AppRegistry,
Text
} from 'react-native';
import SmsListener from 'react-native-android-sms-listener';
//Main component
export default class Main extends Component {
state = {
lastMessage: ''
}
//Receive messages
listen = SmsListener.addListener(message => {
this.setState({ lastMessage: message.body });
console.log('message');
})
//render UI
render() {
return (
<Text> Message is: {this.state.lastMessage} </Text>
);
}
}
//Register component
AppRegistry.registerComponent('ReadMessageApp', () => Main);
I am developing an android app using react-native, i want to use local push notification for that, like whenever i click on button, push notification should create. how can i do this?
someone please suggest me something.
You could try this with react-native-push-notification
import PushNotification from 'react-native-push-notification';
scheduleNotfication() {
PushNotification.localNotificationSchedule({
message: "My Notification Message", // message
date: new Date(Date.now() + (60 * 1000)) // your required time
});
}
Button
<Button title="title of button" onPress ={this.scheduleNotfication() } >
<Text>show</Text>
</Button>
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button,
TouchableHighlight
} from 'react-native';
import PushNotification from 'react-native-push-notification';
export default class pn extends Component {
scheduleNotfication() {
PushNotification.localNotificationSchedule({
message: "My Notification Message", // message
date: new Date(Date.now() + (60 * 1000)) // your required time
});
}
render() {
return (
<View>
<TouchableHighlight onPress ={this.scheduleNotfication.bind(this) } >
<Text>show</Text>
</TouchableHighlight>
</View>
);
}
}
AppRegistry.registerComponent('pn', () => pn);
This is working perfect and getting local Push Notification for certain time.
You can also try
react-native-notifications
It helps you in local as well as a remote push notification.
1.Remote (push) notifications
2.Local notifications
3.Background/Managed notifications (notifications that can be cleared from the server, like Facebook messenger and Whatsapp web)
4.PushKit API (for VoIP and other background messages)
5.Interactive notifications (allows you to provide additional functionality to your users outside of your application such as action buttons)
Code snippets -->
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button,
TouchableHighlight
} from 'react-native';
import {NotificationsAndroid} from 'react-native-notifications';
export default class pushLocalNotification extends Component {
get_Local_Notfication() {
NotificationsAndroid.localNotification({
title: "Local notification",
body: "This notification was generated by the app!",
extra: "data"
});
}
render() {
return (
<View>
<TouchableHighlight onPress =
{this.get_Local_Notfication.bind(this) } >
<Text>show</Text>
</TouchableHighlight>
</View>
);
}
}
AppRegistry.registerComponent('pushLocalNotification', () =>
pushLocalNotification);
This is working perfectly for me.