I am using i18next for localization. I am able to change manually using i18next changelanguage method. But I need to manually change language while change the system language. So is there any package to detect language change in react native
Use react-native-device-info
npm install --save react-native-device-info
getDeviceLocale()
Gets the device locale.
const deviceLocale = DeviceInfo.getDeviceLocale();
// iOS: "en"
// Android: "en-US"
// Windows: ?
Update:
We can AppState if the app is in the foreground or background, and notify you when the state changes.
If user moved the application to background state, the language has been changed and then open the app again.
While application coming to the foreground state we can check for the language with DeviceInfo.getDeviceLocale().
It's the good way to tell that the device's language has been changed or not.
Without moving to background, user will not change the language right?
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});
}
Related
Is there a way to monitor when a phone has their location settings (not permissions) turned on or off?
I know there's a way to check with react-native-device-info with the code below, but is there a way to add a listener to constantly check?
DeviceInfo.isLocationEnabled().then((enabled) => {
// true or false
});
When users change location setting, Users open setting page. It means you should know if app is foreground or background.
In that case, you can use AppState (https://reactnative.dev/docs/appstate).
To monitor when a phone has their location settings (not permissions) turned on or off, You can implement like this.
import {AppState} from 'react-native';
useEffect(() => {
const subscription = AppState.addEventListener('change', (nextAppState) => {
// if app is foreground.
if (nextAppState === 'active') {
DeviceInfo.isLocationEnabled().then((enabled: boolean) => {
// true or false
});
}
});
return () => {
subscription.remove();
};
}, []);
I'm trying to find a way to execute a function upon termination of the app, what function can I use to do this in react native?
Basically, whenever the user closes the app (completely terminate).
This might help:
AppState.addEventListener('change', state => {
if (state === 'active') {
// do this
} else if (state === 'background') {
// do that
} else if (state === 'inactive') {
// do that other thing
}
});
You can use the AppState API provided by react-native in your root component where you register/mount your app.
There you can add an onChange eventlistener to AppState which executes your custom function whenever AppState.currentState.match(/inactive|background/) returns true. Your custom function however should be isolated from your other component states.
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
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.
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>
);
}
}