expo-location (React-Native) : Location.getCurrentPositionAsync() never returns anything - react-native

I'm developing a cross platform mobile App.
I'm testing my code on a Android Studio emulator (google pixel 5, api level 30) and i'm using expo version : ~43.0.2 and expo-location version : ~13.0.4
I've already asked for the location permission, and it works. But when I call the following code i log "there" but never "here":
console.log("there")
const userLocation = await Location.getCurrentPositionAsync()
console.log("here")
Indeed, the function Location.getCurrentPositionAsync() seems locked
A similar issue has been know in the past according to these links:
React Native Expo-Location returns Location service unavailable during initial useEffect
https://forums.expo.dev/t/getcurrentpositionasync-doesnt-return-any-value-infinity-loading/23643
But it's also the code in the Expo doc :
https://snack.expo.dev/#charliecruzan/expo-map-and-location-example
. Bellow the entire app class :
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import {Text, TextInput, Pressable, View, Alert} from 'react-native';
import * as Location from "expo-location"
export default class App extends React.Component{
state = {
errorMessage: "",
location: {}
}
getAddress(){
return this.state.address
}
_getLocation = async ()=>{
const {status} = await Location.requestForegroundPermissionsAsync();
if (status !== "granted"){
console.log("PERMISSION LACK!")
this.setState({
errorMessage:"PERMISSION NOT GRANTED"
});
}
console.log("there")
const userLocation = await Location.getCurrentPositionAsync();
console.log("here")
console.log(JSON.stringify(userLocation))
this.setState({
location: userLocation
})
}
render(){
this._getLocation()
return (
<View>
<Text>Salut</Text>
</View>
);
}
}
What did i missed?

Add accuracy and maximumAge in parameters with Location.Accuracy.Highest and 10000 respectively as shown below:
JavaScript:
const userLocation = await Location.getCurrentPositionAsync({accuracy: Location.Accuracy.Highest, maximumAge: 10000});
The solution came from How to use getCurrentPositionAsync
function in expo-location | Tabnine.

As explained in this reddit post, the location service only works in emulators if you are logged into a google account.

Related

get current position in expo

I am building a project in react-native and i need to find my current location. My teacher told me to use Location.getCurrentPositionAsync. But the position I always find is: 37.421998333333335 - -122.084. because?
import React, { Component, useState} from 'react';
import {View, StyleSheet,Dimensions} from 'react-native';
import * as Location from 'expo-location';
import MapView from 'react-native-maps';
const { height } = Dimensions.get("window");
export default class TrainMap extends Component {
constructor(){
super();
this.state={location:"",latitude:null,longitude:null}
}
async locationPermissionAsync() {
let canUseLocation = false;
const grantedPermission = await Location.getForegroundPermissionsAsync()
if (grantedPermission.status === "granted") {
canUseLocation = true;
} else {
const permissionResponse = await Location.requestForegroundPermissionsAsync()
if (permissionResponse.status === "granted") {
canUseLocation = true;
}
}
if (canUseLocation) {
const location = await Location.getCurrentPositionAsync(
)
console.log("received location:", location);
this.state.location = location.coords.latitude + " - " + location.coords.longitude;
this.state.latitude=location.coords.latitude;
this.state.longitude=location.coords.longitude;
console.log("Position is: "+this.state.location)
}
}
componentDidMount() {
this.locationPermissionAsync()
};
render(){}
}
how can i get my current location?
Ahh since youre using an android emulator, the lat long which youre getting is the default one which represents the where the emulator currently is at.
YOu can change the lat long on emulator via How to emulate GPS location in the Android Emulator?
check this blog
Youll get an idea how to change, but rest assured in physical device youll get the updated lat long,

compiled application not loading in real device

For the life of me, I can't figure it out. All it shows is spinning without end and i am confused on the order of the life cycle happening. Basically, it goes to login or home screen and it works correctly on emulator but not on real device. I am on react 16.8.6 and react-native 0.60.5 environment.
I am getting started with RN and my debugging tools are not great. But for now just used Alert to see and the logic that was supposed to redirect to login/home screen is never reached. The Alerts shown are in the following order:
BS
mount2
render
mount1
My code is below: if the token exists, load home screen. else load auth screen is what I wanted to achieve but for now the line:
this.props.navigation.navigate(!goToLogin ? 'App' : 'Auth');
is never reached and so, spins a lot. Any help?
import React, {Component} from 'react';
import {StatusBar, View, Alert} from 'react-native';
import {
getUserToken,
loggedInToAssociation,
extractToken,
} from '../shared/loggedinUser';
import {setLanguage} from '../shared/localization';
import {appOptions} from '../config';
import Spinner from '../components/Spinner';
export default class AuthLoadingScreen extends Component {
constructor() {
super();
this.state = {
languageLoaded: false
};
}
componentDidMount() {
Alert.alert("mount1","oumnt1") // shown
loggedInToAssociation()
.then(details => {
// details is an array now
setLanguage(details['language']);
this.setState({languageLoaded: true});
Alert.alert("mount2","oumnt2") // SHOWN
})
.catch(err => {
setLanguage(appOptions.defaultLanguage);
this.setState({languageLoaded: true});
Alert.alert("mount3","oumnt3")
});
}
// Fetch the token from storage then navigate to our appropriate place
_bootstrapAsync = async () => {
const userToken = await getUserToken();
Alert.alert("bs","bs") // SHOWN
const tokenInfo = extractToken(userToken, 'both');
let goToLogin = true; // force user to go to the login page
if (tokenInfo.length == 2) {
goToLogin = false;
}
Alert.alert("bs2","bs2") // NEVER SHOWN
this.props.navigation.navigate(!goToLogin ? 'App' : 'Auth');
};
// Render any loading content that you like here
render() {
if (this.state.languageLoaded){
this._bootstrapAsync().then(s=>{
console.log(s)
}).catch(e=>{
console.log(e)
})
}
return (
<View>
<Spinner />
<StatusBar barStyle="default" />
</View>
);
}
}
did you check your debug console when running on device? There might be an unhandled promise rejection. The promise didn't go through but nowhere to handle the catch (consider try-catch scenario for this context).
It might be having a problem with this method.
extractToken(userToken, 'both')

How to Implement UPI Payment in my React-Native-App with Expo?

I want to add UPI payment in my App and currently using expo tool to create the app but now I got stuck as there is unable to find any direct implementation by using js only and require me to eject from expo. If there is any way by which I can implement the UPI without exiting from expo as it expo makes things really easy.
I have tried to implement the simple code provided in the docs for react-native-upi-payment but it is not moving ahead and require me to move through android manifest which is not inside the expo project.
import React from 'react'
import RNUpiPayment from 'react-native-upi-payment'
import { View, StyleSheet, Container } from 'react-native'
import { Input, Button } from 'react-native-elements'
import { Constants } from 'expo'
export default class PaymentScreen extends React.Component {
static navigationOptions = {
header: null
}
goToBhimUPI = () => {
RNUpiPayment.initializePayment({
vpa: 'someupi#ybl', // or can be john#ybl or mobileNo#upi
payeeName: 'Name',
amount: '1',
transactionRef: 'some-random-id'
}, this.successCallback, this.failureCallback);
}
failureCallback = (data) =>{
console.log(data)
}
successCallback = (data) => {
console.log(data)
}
render() {
return(
<Button
containerStyle = {styles.button}
type = 'clear'
title = 'Bhim UPI'
onPress = {this.goToBhimUPI}
/>
)
}
}
I expect this module to take me to the UPI payment gateway and return to the place from where it is called. Currently this is giving me error:(undefined is not an object(evaluating 'UpiModule.intializePayment'))
you can do this using react-native-upi-payment for all types of upi available or else phonepesdk for only phonepe integration

React Native Expo.Font.loadAsync doesn't load Material Icons

I have a React Native, React hybrid app. For React Native i am using react-native-elements.
My app is run using Expo and was built out with the react-native init. I am getting the Material Icons (missing) RSD;
Through much searching, i have found the #expo/vector-icons but it doesn't seem to work. My App.js looks like this;
import React from 'react'
import { Font, AppLoading } from 'expo'
import { MaterialIcons } from '#expo/vector-icons'
import HybridApp from './src/App'
export default class NativeApp extends React.Component {
constructor() {
super()
this.state = {
fontsAreLoaded: false
}
}
async componentWillMount() {
await Font.loadAsync(MaterialIcons.font)
this.setState({ fontsAreLoaded: true })
}
render() {
const { fontsAreLoaded } = this.state
return !fontsAreLoaded ? <AppLoading /> : <HybridApp />
}
}
As you can see, i am waiting for the font to load... all to no avail.
After hours wracking my brain on this, the answer was there in front of me the whole time.
Presumably, React Native Elements refers to Material icons as Material Icons, not MaterialIcons.
This means that the default import from #expo/vector-icons does not work as their reference to Material icons is different.
The solution is to manually select Material icons from expo, replacing this line;
await Font.loadAsync(MaterialIcons.font)
with
await Font.loadAsync({
'Material Icons': require('#expo/vector-icons/fonts/MaterialIcons.ttf')
})
I hope this saves someone some time in the future.
The icons are actually fonts and must first be loaded. It seems they are autoloaded sometimes and others times are not.
So to ensure they are loaded, do this:
import FontAwesome from './node_modules/#expo/vector-icons/fonts/FontAwesome.ttf';
import MaterialIcons from './node_modules/#expo/vector-icons/fonts/MaterialIcons.ttf';
...
async componentWillMount() {
try {
await Font.loadAsync({
FontAwesome,
MaterialIcons
});
this.setState({ fontLoaded: true });
} catch (error) {
console.log('error loading icon fonts', error);
}
}
...
render() {
if (!this.state.fontLoaded) {
return <AppLoading />;
}
Then when you reference the type, it must be the same type that the component you are using is expecting.
For example, react native elements expects these types: material-community, font-awesome, octicon, ionicon, foundation, evilicon, simple-line-icon, zocial, or entypo
See complete answer here:
http://javascriptrambling.blogspot.com/2018/03/expo-icon-fonts-with-react-native-and.html
This question is old, but what worked for me and quite straightforward is
import { Ionicons } from "#expo/vector-icons";
await Font.loadAsync({...Ionicons.font, ...other imports })
Check if you have any dependency warnings when you run the app. I had an expo-font version warning, when I fixed it this error went away.
Some dependencies are incompatible with the installed expo package version:
- expo-font - expected version range: ~8.4.0 - actual version installed: ^9.1.0

How to get the device token in react native

I am using react-native 0.49.3 version, My Question is how to get the device token in react native for both IOS and Android I tried with this link but it not working for me, right now I tried in IOS. how to resolve it can one tell me how to configure?
I tried different solutions and I've decided to use React Native Firebase.
Here you will find everything about Notifications.
Also, you can use the others libraries that come with Firebase, like Analytics and Crash Reporting
After set up the library you can do something like:
// utils/firebase.js
import RNFirebase from 'react-native-firebase';
const configurationOptions = {
debug: true,
promptOnMissingPlayServices: true
}
const firebase = RNFirebase.initializeApp(configurationOptions)
export default firebase
// App.js
import React, { Component } from 'react';
import { Platform, View, AsyncStorage } from 'react-native';
// I am using Device info
import DeviceInfo from 'react-native-device-info';
import firebase from './utils/firebase';
class App extends Component {
componentDidMount = () => {
var language = DeviceInfo.getDeviceLocale();
firebase.messaging().getToken().then((token) => {
this._onChangeToken(token, language)
});
firebase.messaging().onTokenRefresh((token) => {
this._onChangeToken(token, language)
});
}
_onChangeToken = (token, language) => {
var data = {
'device_token': token,
'device_type': Platform.OS,
'device_language': language
};
this._loadDeviceInfo(data).done();
}
_loadDeviceInfo = async (deviceData) => {
// load the data in 'local storage'.
// this value will be used by login and register components.
var value = JSON.stringify(deviceData);
try {
await AsyncStorage.setItem(config.DEVICE_STORAGE_KEY, value);
} catch (error) {
console.log(error);
}
};
render() {
...
}
}
Then you can call the server with the token and all the info that you need.