React-native-maps and Geolocation not getting location properly - android

I am very new to learning React Native and would appreciate any help that can be provided with my code. I am currently working off of tutorials and have been stuck for hours. Hopefully this is enough info to get some help. Thanks in advance!
My goal
I am trying to do three things (in this order):
Get the user's current location
Fetch the items data from an API (example outlined below). It should be noted that eventually the contents of the fetch will be dependent on the user's current location.
Parse the items data to create markers and a unique list of categories and place those on the map with the user's current location at center to begin with.
I am looking to be able to watch the user's location and move and update the map accordingly. I also don't want to show the map until all of the markers are in place.
Here are my react versions: react-native-cli: 2.0.1 react-native: 0.63.2
My Bugs
I am using both the Android Studio emulator as well as the Xcode emulator and am currently running into the following problems:
The iOS emulator on Xcode renders fine the first time, but on subsequent refreshes I see 1 or two of my 5 markers missing.
On Android, the map loads perfectly then appears to immediately redraw itself and center on the Googleplex in California instead of the user's current location.
Emulator location is set to London, UK
I suspect I might have some race condition with fetching the items and current location before the map renders but I can't be sure.
My Code
//my API response structure
{
"id": "96845",
"title": "Item_title_goes_here",
"image": "https://someURL/image.JPG",
"stories": 46,
"lat": some_lat_number,
"lon": some_lon_number,
"category": "category_name",
"description": "long_description"
},
//ajax.js
export default {
async fetchInitialItems() {
try {
const response = await fetch(apiHost + '/api/v1/items/');
const responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
},
async fetchItemDetail(itemId) {
try {
const response = await fetch(apiHost + '/api/items/' + itemId);
const responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
},
};
//ExploreScreen.js (my map component)
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
Image,
Animated,
Dimensions,
TouchableOpacity,
PermissionsAndroid,
ScrollView,
Platform,
StatusBar,
} from 'react-native';
import MapView, {
PROVIDER_GOOGLE,
Marker,
Callout,
Polygon,
} from 'react-native-maps';
import PropTypes from 'prop-types';
import Geolocation from '#react-native-community/geolocation';
import { mapDarkStyle, mapStandardStyle } from '../model/mapData';
import ajax from '../utils/ajax';
import MapCarousel from './MapCarousel';
import Ionicons from 'react-native-vector-icons/Ionicons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import Fontisto from 'react-native-vector-icons/Fontisto';
import StarRating from '../components/StarRating';
/**
|--------------------------------------------------
| Variables
|--------------------------------------------------
*/
const { width, height } = Dimensions.get('window');
const SCREEN_HEIGHT = height;
const SCREEN_WIDTH = width;
const ASPECT_RATIO = width / height;
const LATITUDE_DELTA = 0.0422;
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;
const darkTheme = false;
/**
|--------------------------------------------------
| Component
|--------------------------------------------------
*/
class ExploreScreen extends React.Component {
/****** Props & States ******/
state = {
region: {
latitude: 0,
longitude: 0,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
},
items: [],
markers: [],
categories: [],
currentMapRegion: null,
};
/****** Functions ******/
///when carousel item selected
onCarouselItemSelected() {
alert('carousel item selected');
}
//when the carousel in scrolled
onCarouselIndexChange(itemID) {
const item = this.state.items.find(item => item.id == itemID);
const marker = this.state.markers.find(marker => marker.id == itemID);
const coordinates = { lat: item.lat, lon: item.lon };
this.goToLocation(coordinates);
}
//get current position
getLocation(that) {
Geolocation.getCurrentPosition(
//get the current location
position => {
const region = {
latitude: parseFloat(position.coords.latitude),
longitude: parseFloat(position.coords.longitude),
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
};
that.setState({ region });
},
error => alert(error.message),
{ enableHighAccuracy: true, timeout: 20000 },
);
//get location on location change
that.watchID = Geolocation.watchPosition(position => {
const currentRegion = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
};
this.setState({ region: currentRegion });
});
}
//move map to a lat/lon
goToLocation(coordinates) {
if (this.map) {
this.map.animateToRegion({
latitude: coordinates.lat,
longitude: coordinates.lon,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
});
}
}
//when the region changes for the map
onRegionChangeComplete(region) {
//I dont know what to do here
}
//move map to center of current location
gotToCenter() {
if (this.map) {
this.map.animateToRegion({
latitude: this.state.region.latitude,
longitude: this.state.region.longitude,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
});
}
}
//map the categories store in the state
mapCategories = () => {
const uniqueCategories = [];
this.state.items.map(item => {
if (uniqueCategories.indexOf(item.category) === -1) {
uniqueCategories.push(item.category);
}
});
this.setState({ categories: uniqueCategories });
};
//map the items to markers and store in the state
mapMarkers = () => {
const markers = this.state.items.map(item => (
<Marker
key={item.id}
coordinate={{ latitude: item.lat, longitude: item.lon }}
image={require('../assets/map_marker.png')}
tracksViewChanges={false}
title={item.title}
description={item.description}
/>
));
this.setState({ markers: markers });
};
/****** Lifecycle Functions ******/
async componentDidMount() {
var that = this;
//Checking for the permission just after component loaded
if (Platform.OS === 'ios') {
//for ios
this.getLocation(that);
} else {
//for android
async function requestLocationPermission() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Access Required',
message: 'This App needs to Access your location',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
//To Check, If Permission is granted
that.getLocation(that);
} else {
alert('Permission Denied');
}
} catch (err) {
alert('err', err);
console.warn(err);
}
}
requestLocationPermission();
}
//get location on location change
that.watchID = Geolocation.watchPosition(position => {
const currentRegion = {
latitude: parseFloat(position.coords.latitude),
longitude: parseFloat(position.coords.longitude),
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA,
};
this.setState({ region: currentRegion });
});
console.log(this.state.region);
const items = await ajax.fetchInitialItems();
this.setState({ items });
this.mapMarkers();
this.mapCategories();
}
componentWillUnmount = () => {
Geolocation.clearWatch(this.watchID);
};
render() {
const lat = this.state.region.latitude;
const lon = this.state.region.longitude;
if (this.state.items && lat && lon) {
return (
<View>
<MapView
ref={map => {
this.map = map;
}}
onRegionChangeComplete={this.onRegionChangeComplete.bind(this)}
toolbarEnabled={false}
showsMyLocationButton={false}
provider={PROVIDER_GOOGLE}
style={styles.map}
customMapStyle={darkTheme ? mapDarkStyle : mapStandardStyle}
showsUserLocation={true}
followsUserLocation={true}
region={this.state.region}>
{this.state.markers}
</MapView>
{/* center button */}
<TouchableOpacity
onPress={this.gotToCenter.bind(this)}
style={styles.centerButtonContainer}>
<Ionicons name="md-locate" size={20} />
</TouchableOpacity>
<View style={styles.carousel}>
<MapCarousel
data={this.state.items}
onPressItem={() => {
this.onCarouselItemSelected.bind(this);
}}
onUpdateLocation={this.onCarouselIndexChange.bind(this)}
/>
</View>
</View>
);
} else {
return (
<View style={styles.container}>
<Text style={styles.header}>Loading...</Text>
</View>
);
}
}
}
/**
|--------------------------------------------------
| Styles
|--------------------------------------------------
*/
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
height: '100%',
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
map: {
height: '100%',
},
carousel: {
position: 'absolute',
bottom: 25,
},
header: {
fontSize: 50,
},
//character name
name: {
fontSize: 15,
marginBottom: 5,
},
//character image
image: {
width: 170,
height: 80,
},
//center button
centerButtonContainer: {
width: 40,
height: 40,
position: 'absolute',
bottom: 260,
right: 10,
borderColor: '#191919',
borderWidth: 0,
borderRadius: 30,
backgroundColor: '#d2d2d2',
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 9,
},
shadowOpacity: 0.48,
shadowRadius: 11.95,
elevation: 18,
opacity: 0.9,
},
});
export default ExploreScreen;

Related

[Unhandled promise rejection: TypeError: error is not a function. (In 'error({]

i'm trying to get Latitude and longitude values from a GPS Module Tracker which I have made myself. I'm fetching values from it (Lat, Lng). it does give me the current location but does not move smoothly like a uber car instead it changes location at a fixed point after some time. I have used navigator.geolocation.watchPosition to fetch updated location. Is this not the right way?
App.js
import React, { Component } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
import Display from './src/Display';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true
};
}
componentDidMount() {
fetch('https://api.thingspeak.com/channels/1323137/feeds.json?results=1')
.then((response) => response.json())
.then((json) => {
this.setState({ data: json.feeds });
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({ isLoading: false });
});
}
render() {
const { data, isLoading } = this.state;
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={( id, index ) => index.toString()}
renderItem={({ item }) =>
<Display
value1 = {item.field1}
value2 = {item.field2}
value3 = {item.field3}
/>
}
/>
)}
</View>
);
}
};
Display.js
import React, { Component } from "react";
import { StyleSheet, View, Image, Animated, Text, image, Dimensions } from "react-native";
import MapView, { Marker,PROVIDER_GOOGLE} from "react-native-maps";
const { width, height } = Dimensions.get("window");
export default class App extends React.Component {
constructor(props) {
super(props);
this.State = {
region:
{
latitude: parseFloat(this.props.value1),
longitude: parseFloat(this.props.value2),
latitudeDelta: 0.01,
longitudeDelta: 0.0
}
}
}
componentDidMount() {
this.watchID = navigator.geolocation.watchPosition((position) => {
var lat = parseFloat(position.this.props.value1)
var long = parseFloat(position.this.props.value2)
var latestRegion = {
latitude: lat,
longitude: long,
latitudeDelta: 0.01,
longitudeDelta: 0.0
}
this.setState({region: latestRegion})
})
}
componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchID)
}
render() {
return (
<View style={styles.container}>
<MapView
initialRegion={this.State.region}
provider={PROVIDER_GOOGLE}
showsUserLocation={false}
showsCompass={true}
rotateEnabled={false}
showsBuildings={true}
showsTraffic={true}
showsIndoors={true}
style={{
width,
height,
}}
>
<MapView.Marker
style={{ width: 100, height: 15 }}
title="Uni Bus"
description="Route-1"
resizeMode="contain"
image={require('D:/React Native apps/track-app/assets/Bus_image_2.png')}
coordinate={{
latitude: parseFloat(this.props.value1),
longitude: parseFloat(this.props.value2)
}}
/>
</MapView>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingTop: 25,
padding: -15,
},
});
I'm trying to do this in react native.

How to track current user properly by using react-native-map

I'm getting current user latitude and longitude and showing them on the map. But when I start tracking the user it shows error sometimes as displayed in image.
But on emulator is working totally fine. This behavior is happening only on Real device.
but some times it works properly as displayed in the image
.
I am unable to figure out, why this is happening. My code is below
import React, { Component } from "react";
import {
StyleSheet,
PermissionsAndroid,
View,
Text,
Image
} from "react-native";
import { AskPermission } from "../../components/AskPermissions";
import MapView, { PROVIDER_GOOGLE, Marker, Polyline } from "react-native-maps";
import haversine from "haversine";
class TrackCurrentUser extends Component {
state = {
region: {
latitude: 0,
longitude: 0,
latitudeDelta: 0.0922, // must give some valid value
longitudeDelta: 0.0421 // must give some valid value
},
error: "",
routeCoordinates: [],
distanceTravelled: 0, // contain live distance
prevLatLng: {} // contain pass lat and lang value
};
// getLocation Permission and call getCurrentLocation method
componentDidMount() {
const permission = PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION;
AskPermission(permission);
this.getCurrentLocation();
}
// getting the current Location of a user...
getCurrentLocation = () => {
navigator.geolocation.watchPosition(
position => {
const { latitude, longitude } = position.coords;
const { routeCoordinates } = this.state;
const newCoordinate = { latitude, longitude };
let region = {
latitude: parseFloat(position.coords.latitude),
longitude: parseFloat(position.coords.longitude),
latitudeDelta: 5,
longitudeDelta: 5
};
this.setState({
initialRegion: region,
region: region,
routeCoordinates: routeCoordinates.concat([newCoordinate]),
distanceTravelled:
this.state.distanceTravelled + this.calcDistance(newCoordinate),
prevLatLng: newCoordinate
});
},
error => console.log(error),
{
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000,
distanceFilter: 1
}
);
};
// animate to current user Location
goToInitialLocation = () => {
let initialRegion = Object.assign({}, this.state.initialRegion);
initialRegion["latitudeDelta"] = 0.005;
initialRegion["longitudeDelta"] = 0.005;
this.mapView.animateToRegion(initialRegion, 2000);
};
// lat & lng for Marker
getMapRegion = () => ({
latitude: this.state.region.latitude,
longitude: this.state.region.longitude
});
// calculate the total distance
calcDistance = newLatLng => {
// console.warn("Method Called");
const { prevLatLng } = this.state;
return haversine(prevLatLng, newLatLng) || 0;
};
render() {
return (
<View style={{ flex: 1 }}>
<MapView
style={{ flex: 0.9 }}
provider={PROVIDER_GOOGLE}
region={this.state.mapRegion}
followUserLocation={true}
ref={ref => (this.mapView = ref)}
zoomEnabled={true}
showsUserLocation={true}
onMapReady={this.goToInitialLocation}
initialRegion={this.state.initialRegion}
>
<Polyline coordinates={this.state.routeCoordinates} strokeWidth={5} />
<Marker coordinate={this.getMapRegion()} title={"Current Location"}>
<Image
source={require("../../images/car.png")}
style={{ height: 35, width: 35 }}
/>
</Marker>
</MapView>
<View style={styles.distanceContainer}>
<Text>{parseFloat(this.state.distanceTravelled).toFixed(2)} km</Text>
</View>
</View>
);
}
}
export default TrackCurrentUser;
const styles = StyleSheet.create({
distanceContainer: {
flex: 0.1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "transparent"
}
});
waiting for your solution to solve this problem.
After few months I again started to work on maps and started looking on my old code to find the issue again and luckily this time I found the problem.
Problem
Problem was with onMapReady
onMapReady={this.goToInitialLocation}
// animate to current user Location
goToInitialLocation = () => {
let initialRegion = Object.assign({}, this.state.initialRegion);
initialRegion["latitudeDelta"] = 0.005;
initialRegion["longitudeDelta"] = 0.005;
this.mapView.animateToRegion(initialRegion, 2000);
};
Solution
I removed this code and following line in getCurrentLocation function.
this.map.animateToRegion(region, 1000);
Now the getCurrentLocation function looks like
getCurrentLocation = () => {
navigator.geolocation.watchPosition(
position => {
const { latitude, longitude } = position.coords;
const { routeCoordinates } = this.state;
const newCoordinate = { latitude, longitude };
let region = {
latitude: parseFloat(position.coords.latitude),
longitude: parseFloat(position.coords.longitude),
latitudeDelta: 5,
longitudeDelta: 5
};
this.setState({
initialRegion: region,
region: region,
routeCoordinates: routeCoordinates.concat([newCoordinate]),
distanceTravelled:
this.state.distanceTravelled + this.calcDistance(newCoordinate),
prevLatLng: newCoordinate
});
},
//animate to user's current location
this.map.animateToRegion(region, 1000);
error => console.log(error),
{
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000,
distanceFilter: 1
}
);
};

Interact with a marker with user location

I have implemented react-native-maps with Expo, and I want to create a little game. I have the user location and I want to create an event for example; if I'm from 5 meters of a marker, I want to to do something.
I don't know if it's possible, I think there is something to do with the lat and long of the user with the the lat and long of the marker... There is my code:
import React, { Component } from 'react';
import {
Text,
View
} from 'react-native';
import { MapView,Location,Permissions } from 'expo';
export default class Game extends Component {
static navigationOptions = {
title: 'Map',
};
constructor(props){
super(props)
this.state = {
locationResult:{ latitude: 0, longitude: 0},
errorMessage: null,
hasLocationPermissions: false,
region: null,
location:null
}
}
_OnDragEnd = result =>{
this.setState({locationResult: result.coordinate})
console.log(this.state.locationResult)
console.log(result.coordinate)
if (result.coordinate == this.state.locationResult){
console.log('ok')
}else{
console.log('pas ok')
}
}
componentDidMount() {
this._getLocationAsync();
}
_handleMapRegionChange = region => {
console.log(region);
this.setState({ region });
};
_getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
this.setState({
errorMessage: 'Permission to access location was denied',
});
} else {
this.setState({ hasLocationPermissions: true });
}
let location = await Location.getCurrentPositionAsync({});
this.setState({
region: {
latitude: location.coords.latitude,
longitude: location.coords.longitude,
latitudeDelta: 0.0922 / 10,
longitudeDelta: 0.0421 / 10 },
locationResult:{
latitude: location.coords.latitude,
longitude: location.coords.longitude},
location
});
};
_reachSpawn = async () => {
}
mapStyle = require('./mapStyle.json');
render() {
return (
<View style={{flex:1}}>
<Text style={{height:40,backgroundColor: '#6AC4ED'}}>Score: </Text>
<MapView
showsUserLocation
followsUserLocation
style={{flex:1}}
region={this.state.region}
zoomEnabled={false}
pitchEnabled={false}
scrollEnabled={false}
customMapStyle={this.mapStyle}
provider={MapView.PROVIDER_GOOGLE}
rotateEnabled={false}
showsCompass={true}
>
{/* <MapView.Marker
//image = '../../../assets/DarkSamus.png'
coordinate={this.state.locationResult}
title="My Marker"
description="Some description"
draggable
onDragEnd={e => this._OnDragEnd(e.nativeEvent)}
image={require('../../../assets/soldier-6.png')}
/> */}
{
SPAWNS.map((m, i) =>
<MapView.Marker
coordinate={m.latLong}
title={m.title}
description={m.description}
key={`marker-${i}`}
pinColor= '#20794C'
image={require('../../../assets/zombie-4.png')}
/>
)
}
</MapView>
</View>
);
}
}
const SPAWNS = [
{
key: 'Zombie',
title: 'Zombie Level 1',
description: 'Kill him to get 1 point',
latLong: {
latitude: 48.78356518226211,
longitude: 2.3951343385137105,
},
},
{
key: 'Zombie',
title: 'Zombie Level 1',
description: 'Kill him to get 1 point',
latLong: {
latitude: 48.869702,
longitude: 2.335888,
},
},
{
key: 'Zombie',
title: 'Zombie Level 1',
description: 'Kill him to get 1 point',
latLong: {
latitude: 48.77993070617117,
longitude: 2.3956984115292626,
},
},
{
key: 'Zombie',
title: 'Zombie Level 1',
description: 'Kill him to get 1 point',
latLong: {
latitude: 48.780455052145385,
longitude: 2.4131448702847615,
},
},
];

Expo React-native using Android: How to run app in background?

Is there an alternative way or tricks to run expo app in background using android? I've been searching for a couple of days looking for answer. There's answers but its complicated for beginners, I'm creating an app that track the location of user every 5 seconds and send the location to the server using node. Its working fine, my only problem is when its in the background my app stops sending data to server.
App.js
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
Dimensions
} from 'react-native';
import { BackgroundFetch, TaskManager } from 'expo';
import MapView from 'react-native-maps';
import {Marker} from 'react-native-maps'
export default class App extends Component {
state = {
mapRegion: null,
hasLocationPermissions: false,
locationResult: null,
marker: {
latitude: 0,
longitude: 0
},
latitude: 0,
longitude: 0,
location: null,
errorMessage: null
};
componentDidMount() {
//var handle = Interaction
this.getBackgroundStat()
this.watchCurLocation();
}
getBackgroundStat = async () =>{
const test = await BackgroundFetch.getStatusAsync({});
console.log(test)
}
watchCurLocation = () =>
setTimeout(() => {
this.watchCurLocation();
}, 5000);
}
getLocationAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
this.setState({
errorMessage: 'Permission to access location was denied',
});
return;
}
const location = await Location.getCurrentPositionAsync({});
console.log(location)
this.setState({ location });
};
getCurrentLocation = () =>
navigator.geolocation.getCurrentPosition(
(position) => {
let currentUserPosition = position.coords;
//alert(JSON.stringify(currentUserPosition));
},
(error) => {
console.log(error);
},
{
enableHighAccuracy: true,
timeout: 2000,
maximumAge: 0,
distanceFilter: 1
}
);
_handleMapRegionChange = mapRegion => {
//console.log(mapRegion);
this.setState({ mapRegion });
};
_watchLocationAsync = async () =>{
let watchlocation = Location.watchPositionAsync({enableHighAccuracy:true,timeInterval:4000, distanceInterval:0}, (pos)=>{
console.log(pos)
return pos
});
return watchlocation
}
_getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
this.setState({
locationResult: 'Permission to access location was denied',
});
} else {
this.setState({ hasLocationPermissions: true });
}
let location = await Location.getCurrentPositionAsync({});
let marker = Object.assign({}, this.state.marker)
marker.latitude = location.coords.latitude
marker.longitude = location.coords.longitude
this.setState({ locationResult: JSON.stringify(location) });
this.setState({marker})
// Center the map on the location we just fetched.
this.setState({ mapRegion: { latitude: location.coords.latitude, longitude: location.coords.longitude, latitudeDelta: 0.0922, longitudeDelta: 0.0421 } });
};
componentWillUnmount(){
navigator.geolocation.clearWatch(this.watchId);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Pan, zoom, and tap on the map!
</Text>
{
this.state.locationResult === null ?
<Text>Finding your current location...</Text> :
this.state.hasLocationPermissions === false ?
<Text>Location permissions are not granted.</Text> :
this.state.mapRegion === null ?
<Text>Map region doesn't exist.</Text> :
<MapView
style={{ alignSelf: 'stretch', height: 400 }}
initialRegion={this.state.mapRegion}
onRegionChange={this._handleMapRegionChange}
>
<MapView.Marker
coordinate={this.state.marker}
title="GpS locator"
description="My current location"
>
</MapView.Marker>
</MapView>
}
<Text>
Location: {this.state.locationResult}
{"\n\n"}
MyOwnLocation: {this.state.latitude} {"\n\n"}
MyOwnLocation2: {this.state.longitude}
</Text>
</View>
);
}
}
Expo SDK 32 was just released that has background task support including location tracking.
Blog post about it here:
https://blog.expo.io/expo-sdk-v32-0-0-is-now-available-6b78f92a6c52
And docs here:
https://docs.expo.io/versions/v32.0.0/sdk/task-manager
https://docs.expo.io/versions/v32.0.0/sdk/location
And you might find this example helpful.
https://twitter.com/r13127igOr/status/1082761408905920512
I am using react-native-background-task and it is working fine. It works both for IOS and Android. Did you check it out ?
https://www.npmjs.com/package/react-native-background-task

React Native Maps - OnRegionChange stutters the map

I'm having a weird issue with the React Native Maps library. At the moment when I follow all the documentation correctly, every time I move the map, it appears to stutter and move back to the original location. Or sporadically it will move to the location I want to (With stutter)
App.js
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import MapView from "react-native-maps";
import Geolocation from 'react-native-geolocation-service';
import {YellowBox} from 'react-native';
type Props = {};
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
region: {
latitude: 53.41058,
longitude: -2.97794,
latitudeDelta: 0.1,
longitudeDelta: 0,
}
}
}
componentDidMount() {
Geolocation.getCurrentPosition(
(position) => {
console.warn(position.coords.latitude);
console.warn(position.coords.longitude);
this.setState({
region: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.02,
longitudeDelta: 0,
}
});
},
(error) => {
console.warn(error.code, error.message);
},
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000},
)
}
onRegionChange(region) {
this.setState({
region: region
});
}
render() {
return (
<MapView
style={styles.map}
region={this.state.region}
showsUserLocation={true}
onRegionChange={region => {
this.setState({region});
}}
/>
);
}
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
});
However, if I change onRegionChange to onRegionChangeCompleted, I can move around the map just fine. But then I cannot tilt and when I turn the map using my fingers it will sometimes snap back to the original location.
Has anyone else had this weird issue or is there something I'm doing wrong?
Change onRegionChange to onRegionChangeComplete and it should work smoothly as expected now.
:)
Removing region = {this.state.region} from MapView solved this for me.
for anyone that couldn't solve the problem with the above answers, this answer on https://github.com/react-native-maps/react-native-maps/issues/3639 from #jalasem worked for me, here is a condensed version:
import React, { useEffect, useRef } from 'react'
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps'
const INITIAL_REGION = {
latitude: 44.49317207749917,
longitude: 20.896348971873522,
latitudeDelta: 4.136923536294034,
longitudeDelta: 5.68705391138792,
}
const Map = ({ location }) => {
const mapRef = useRef(null)
useEffect(() => {
// receive a point on the map through props
if (location) {
console.log('change location, location: ', location)
mapRef.current.animateToRegion({
latitude: location.latitude,
longitude: location.longitude,
latitudeDelta: 0.2,
longitudeDelta: 0.2,
})
}
}, [location])
return (
<MapView
provider={PROVIDER_GOOGLE}
initialRegion={INITIAL_REGION}
ref={mapRef}
/>
)
}
export default Map
I needed a way to change the location if a user clicked on a button outside the map, while also being able to move around the map freely, so this solution worked best for me.

Categories

Resources