How to get notified in React-Native when a device goes offline? - react-native

I tried to listen to the isConnected event of NetInfo, but somehow this only fires once, shortly after the app starts. When I deactivate my connection it doesn't fire again.
I tried this in the iOS simulator, so it could be a simulator issue, but I'm not sure.
...
componentWillMount() {
NetInfo.isConnected.addEventListener(
"connectionChange",
this.handleConnectionChange
);
}
componentWillUnmount() {
NetInfo.isConnected.removeEventListener(
"connectionChange",
this.handleConnectionChange
);
}
handleConnectionChange = online => this.setState({ online });
...

Related

setBackgroundHandler not triggered in specific IOS device

I'm using react-native-firebase for notifications and facing a problem.
When the app is in background mode, somehow it cannot trigger the function callingAPIS() on an 14.4 IOS device (android, IOS 14.4.2 working fine).
I figured out that when I connect the release version of app with Xcode, it working but when plug out callingAPIS is not triggered.
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
callingAPIS();
});
if (Platform.OS === 'ios') {
messaging().onNotificationOpenedApp(remoteMessage => {
console.log('FIREBASE IOS Background', remoteMessage);
});
}
function HeadlessCheck({isHeadless}) {
if (isHeadless) {
// App has been launched in the background by iOS, ignore
return null;
}
return <MyApp />;
}
AppRegistry.registerComponent(appName, () => HeadlessCheck);
Anyone facing this problem?

IOS Expo Push Notifications when app is in foreground

reading from the expo docs:
For iOS, you would be wise to handle push notifications that are
received while the app is foregrounded, because otherwise the user
will never see them. Notifications that arrive while the app are
foregrounded on iOS do not show up in the system notification list. A
common solution is to just show the notification manually. For
example, if you get a message on Messenger for iOS, have the app
foregrounded, but do not have that conversation open, you will see the
notification slide down from the top of the screen with a custom
notification UI.
What I don't understand is what is the best approach for that? is there an Expo API for showing such messages? or should I create an alert component of my own? It is not really clear from the docs.
Thanks.
This answer is outdated as of February 20, 2020. Please see https://stackoverflow.com/a/60344280/2441420 for how to show iOS Notification when your application is in the Foreground
There isn't an Expo API for showing those messages. You can use any 'toast' library of your choosing and display the notification message, but that should be all your code.
For example, this is how we are doing right now:
export default class HomeScreen extends React.Component {
componentDidMount() {
this.notificationSubscription = Notifications.addListener(
(notification) => this.handlePushNotification(notification),
);
}
handlePushNotification(notification) {
const { navigation } = this.props;
PushNotificationsService.handleNotification(notification, navigation);
}
(...)
import Toast from 'react-native-root-toast';
export default class PushNotificationsService {
static handleNotification(notification, navigation) {
if (notification.data.screen && notification.origin === 'selected') {
navigation.navigate(notification.data.screen);
}
Toast.show(notification.data.message);
}
}
Toast libraries include:
react-native-root-toast
react-native-easy-toast
react-native-simple-toast
Now you can just add that in one of your app entry point. The shouldShowAlert is what you want here
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
App.json :
{
"expo": {
"notification": {
"iosDisplayInForeground": true
}
}
DEMO
I'm not sure exactly when this was added to Expo, but as of Expo version 36 is easily doable.
To show Expo Push Notifications on iOS when your app is in the foreground, please do the following:
import { Vibration } from "react-native";
import { Notifications } from "expo";
import * as Permissions from "expo-permissions";
import Constants from "expo-constants";
registerForPushNotificationsAsync = async () => {
if (Constants.isDevice) {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
let token = await Notifications.getExpoPushTokenAsync();
console.log("Go to https://expo.io/notifications and copy the token below to easily send yourself a notification.");
console.warn("Notifications on iOS (and I believe Android) ONLY WORK ON A PHYSICAL DEVICE, not a simulator or emulator!!!")
console.log(token);
this.setState({ expoPushToken: token });
} else {
alert("Must use physical device for Push Notifications");
}
};
componentDidMount() {
this.registerForPushNotificationsAsync();
this._notificationSubscription = Notifications.addListener(
this._handleNotification
);
}
_handleNotification = async notification => {
if (notification.remote) {
Vibration.vibrate();
const notificationId = Notifications.presentLocalNotificationAsync({
title: "Follow #technoplato",
body: "To learn yourself goodly (also follow PewDiePie)",
ios: { _displayInForeground: true } // <-- HERE'S WHERE THE MAGIC HAPPENS
});
}
};
Quick and Easy Sanity Check
1) Go here: https://expo.io/notifications
2) Copy the token that is output to the terminal when your application is run.
3) Open your application on iOS.
4) Send a notification to yourself from https://expo.io/notifications and observe that it shows up even when your app is foregrounded.
Notes
Notifications WILL NOT BE RECEIVED ON AN IOS SIMULATOR
Expo makes Notifications ridiculously easy. I honestly can't believe it.
No idea why displayInForeground is false by default and not more prominent in the documentation. I'll submit a PR for it if I can.
Code originally found at this Snack: https://snack.expo.io/#documentation/pushnotifications?platform=ios
LocalNotification.ios._displayInForeground found here: https://docs.expo.io/versions/v36.0.0/sdk/notifications/#localnotification

NetInfo in react-native is returning isConnected as false even when network is connected

We are using react-native NetInfo in following way.
export default class NetworkStatus extends React.PureComponent {
constructor(props){
super(props);
NetInfo.addEventListener(
'change',
this.onConnectivityChange
);
}
onConnectivityChange = (status) => {
NetInfo.isConnected.fetch().then(isConnected => {
console.log('*********Network status ' + (isConnected ? 'online' :
'offline'));
});
}
Launched the app in Offline Mode. We got the following console.
*********Network status offline.
Then we turned on wifi and it is connected. But we got offline console twice.
*********Network status offline.
*********Network status offline.
Is this a bug in NetInfo Library. Is there a way to fix it.
versions used :
"react": "16.0.0-alpha.6"
"react-native": "0.44.0",
you have to change
NetInfo.addEventListener(
'change',
this.onConnectivityChange
);
to
NetInfo.addEventListener(
'connectionChange',
this.onConnectivityChange
);
If you are facing this problem in the simulator then it is because of net connectivity because react-native uses sockets to run the app once you turn off the internet connection sockets gets disrupted and even you turn it on sockets are not restored. Please try using it in actual phone or release mode. It works fine.
componentDidMount() {
NetInfo.isConnected.addEventListener('connectionChange', this.handleConnectivityChange)
}
componentWillUnmount() {
NetInfo.isConnected.removeEventListener('connectionChange', this.handleConnectivityChange)
}
handleConnectivityChange = (isConnected: any) => {
if (isConnected) {
this.setState({ isConnected })
} else {
this.setState({ isConnected })
}
}
I stubbled on this while trying to fix the same problem on an older app which used 0.57.8.
Turns our that react native's NetInfo had a bug which was later fixed.
To fix this I had to change the code to use NetInfo from #react-native-community/netinfo instead of the one that shipped with react native.
I hope this can help others.

How can I detect screen unlock with React Native?

Does anyone know a way in which I can detect when the user has opened their phone? To my understanding android.intent.USER_PRESENT is broadcast when the device is unlocked (e.g. correct password entered), however, I do not know how to detect the broadcast in with React native. Does anyone have a solution?
Look into AppState API in FB(Face Book)
It has 3 states on FB and 5 total. I only see 3 in FB but the other 2 may or may not be suppprted.
Active - The app is running in the foreground
background - The app is running in the background. The user is either in another app or on the home screen.
inactive - This is a state that occurs when transitioning between foreground & background, and during periods of inactivity such as entering the Multitasking view or in the event of an incoming call
Check out apples Docs for more on these.
You're going to have to test what state is hit when you the phone is in the lockscreen. I can't tell you what state to use because I have never tested the api out.
as you can see from the code below the test is done in a conditional statement
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active')
I'm taking facebooks example here but attach the change event listiner in componentDidMount and remove in ComponentWillUnmount and the code will run accourding to the state.
import React, {Component} from 'react'
import {AppState, Text} from 'react-native'
class AppStateExample extends Component {
state = {
appState: AppState.currentState
}
componentDidMount() {
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (nextAppState) => {
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
console.log('App has come to the foreground!')
}
this.setState({appState: nextAppState});
}
render() {
return (
<Text>Current state is: {this.state.appState}</Text>
);
}
}

Check for internet connection returns wrong results

I am trying to check whether the user is connected to internet. I am using NetInfo like this (from the documentation):
componentDidMount() {
NetInfo.isConnected.addEventListener('change', this.handleConnectionChange);
NetInfo.isConnected.fetch().done(
(isConnected) => { this.setState({ status: isConnected }); }
);
}
componentWillUnmount() {
NetInfo.isConnected.removeEventListener('change', this.handleConnectionChange);
}
handleConnectionChange = (isConnected) => {
this.setState({ status: isConnected });
console.log(`is connected: ${this.state.status}`);
}
The strange is that the first time loading the screen where I am doing this is working fine. But when I start turning on/of my wifi the results are different: sometimes it detects the change sometime no. Someone having the same issue?
In my experience, the iOS simulator doesn't 'notice' when the internet connection is re-connected when using the React Native NetInfo class.
It is rather annoying. However, for me it works as intended on a real device.