Location Error 'Google play services is not available', react native - react-native

In my application, I am using react-native-geolocation-service to get location updates.
For IOS application it works just fine, but for the android application It gives me this error
I have enabled permission and all, here is the watcher
this.watchId = Geolocation.watchPosition(
position => {
// this.setState({ location: position });
// console.log(position);
console.log('got position ')
console.log(position)
this.dispatch({
type: UPDATE_LOCATION,
location: position
})
},
error => {
// this.setState({ location: error });
console.log('error occured')
console.log(JSON.stringify(error))
console.log(error);
},
{
enableHighAccuracy: true,
distanceFilter: 0,
interval: 10000,
fastestInterval: 5000
}
);
No matter if i run the app in an emulator, or a android device error stays the same.
Code is just working fine for ios

In options parameter create ternary. Check mobile Platform, if Android - empty brackets, else - receive object like you need. Something like this:
Platform.OS === 'android' ? {} : { enableHighAccuracy: true, timeout: 20000, maximumAge: 10000 }

Related

React Native + Expo not working background location in some devices

I have an Android app that its built with React Native + Expo. My Expo is currently in version 39.0.0.
The user starts a location service by clicking in a button and when users changes position the app with its new position execute some rules based on location and show some notifications depending of user position.
Everything works great when the app is in foreground, in every tested devices. But, when the app goes to background it stops to work in some devices.
For example, in Xiaomi devices the app works great but in Samsung don't. =[
Can anyone help me?
Here`s part of my "app.json":
"android": {
"package": "br.i.dont.know.whats.going.on",
"versionCode": 86,
"permissions": [
"ACCESS_COARSE_LOCATION",
"ACCESS_FINE_LOCATION",
"ACCESS_BACKGROUND_LOCATION",
"CAMERA",
"READ_EXTERNAL_STORAGE",
"WRITE_EXTERNAL_STORAGE",
"NOTIFICATIONS",
"USER_FACING_NOTIFICATIONS",
"FOREGROUND_SERVICE"
],
This is the location task registered when app starts:
export async function registerFetchTask() {
TaskManager.defineTask(LOCATION_TASK, async ({ data: { locations }, error }) => {
if (error) {
console.error(error);
return;
}
const [location] = locations;
try {
if (location) {
AppState.currentState === "background" && updateChart(location);
}
} catch (err) {
console.error("Error while getting user location: ", err);
}
});
const status = await BackgroundFetch.getStatusAsync();
switch (status) {
case BackgroundFetch.Status.Restricted:
case BackgroundFetch.Status.Denied:
console.log("Background execution is disabled");
return;
default: {
console.debug("Background execution allowed");
let tasks = await TaskManager.getRegisteredTasksAsync();
if (tasks.find(f => f.taskName === LOCATION_TASK) == null) {
console.log("Registering task");
await BackgroundFetch.registerTaskAsync(LOCATION_TASK);
tasks = await TaskManager.getRegisteredTasksAsync();
console.debug("Registered tasks", tasks);
} else {
console.log(`Task ${LOCATION_TASK} already registered, skipping`);
}
console.log("Setting interval to", 5);
await BackgroundFetch.setMinimumIntervalAsync(5);
}
}
}
Task location started when user press the button
await Location.startLocationUpdatesAsync(LOCATION_TASK, {
accuracy: Location.Accuracy.Balanced,
timeInterval: 5000,
distanceInterval: 1, // minimum change (in meters) betweens updates
deferredUpdatesTimeout: 5000,
deferredUpdatesInterval: 5000, // minimum interval (in milliseconds) between updates
// foregroundService is how you get the task to be updated as often as would be if the app was open
foregroundService: {
notificationTitle: 'App is using your location',
notificationBody: 'To turn off, go back to the app.',
},
});

React Native Geolocation is not working properly on IOS

I'm using Geolocation in React-Native to receive my current location to load object around me. Below is my code.
getCurrentPosition() {
console.log("checkLocation", "getCurrentPosition1");
navigator.geolocation.getCurrentPosition(
position => {
const { coords } = position;
if (coords !== undefined) {
console.log("checkLocation", "getCurrentPosition trigger");
this.setState({
currentCoordinate: coords,
prevCoorForGet: coords,
prevCoorForUpdate: coords
});
this.props.saveCurrentLocation({
currentLocation: {
latitude: coords.latitude,
longitude: coords.longitude
}
});
this.loadContent(coords);
}
},
error =>
console.log(
"checkLocation",
"getCurrentPosition " + JSON.stringify(error)
),
{
enableHighAccuracy: true,
timeout: 60000,
maximumAge: 3600000
}
);
}
The problem is this code working fine in the first time. But when I navigate to another scene and go back, It isn't work anymore and give me a time out error. Sometime it works, sometime it doesn't. Please help me fix it.
This one is working fine (both ios and android) in my project even working after navigating between pages and return map screen.
navigator.geolocation.getCurrentPosition(
(position) => {
// user location's latitude and longitude
let latitude = parseFloat(position.coords.latitude);
let longitude = parseFloat(position.coords.longitude);
console.log('location position: ', position);
let region = {
latitude: latitude,
longitude: longitude,
latitudeDelta: 0.0522,
longitudeDelta: 0.0321,
};
// to store region data
this.setState({region: region});
//animate to user current location
this.map.animateToRegion(region,1000)
},
(error) => console.log('position error!!!', error),
{enableHighAccuracy: false, timeout: 3000}
);
I hope it works on your project too
Edit
If still not working
/**
* when return the page this listener will trigger
*/
this.props.navigation.addListener('willFocus', (payload) => {
// call location method again
this.getLocation()
});
Try below code, this seems to work for me
import Geolocation from 'react-native-geolocation-service';
componentWillUnmount() {
Geolocation.stopObserving();
}
use your function in componentWillMount() so that every time the component mounts....it function will be executed

navigator.geolocation.clearWatch is not working - React Native

I want to stop the location request when the app is in background.
React-Native version 0.53.3
This is my code for starting the watch:
this.setState.watchID = navigator.geolocation.watchPosition((lastPosition) => {
this.setState({ position: { longitude: lastPosition.coords.latitude, latitude: lastPosition.coords.longitude } });
if (typeof this.state.geoQuery != "undefined") {
if (this.state.gpsError == true) {
this.setState({
gpsError: false
})
}
this.state.geoQuery.updateCriteria({
center: [lastPosition.coords.longitude, lastPosition.coords.latitude],
radius: 1500
});
}
},
(error) => this.setState({ gpsError: true }),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 0, distanceFilter: 1 });
This is where I want to clear the watch:
componentWillUnmount() {
navigator.geolocation.clearWatch(this.state.watchID);
}
The ID I'm getting is always 0,
I have to force close the APP to stop the location, this translates in lot of battery usage if the user don't force close the APP.
Any ideas? Thanks.
I know this is very late, but I had this problem also in v. 0.66
My problem was that i used useState to set the ID which was then somehow translated into false which is not an ID ofcause..
so the solution was for me to set it back to 0....
if(!ID) {
ID = 0
}
Geolocation.clearWatch(ID)

react-native check and prompt user to enable Network/GPS

I am looking around on how to check if network or GPS are enabled on a device when my application starts. And if they are disabled prompt the user to enable it.
Is this posible in React-native?, and is there any class or tool that could help with this type of dialogs?
So I am going to start answering my own question.
For GPS:
there seems to be a sensible solution. IOS seems to natively request if there is a geolocation request. And for Android this is not natively supported but someone has created a module for that ( https://github.com/webyonet/react-native-android-location-services-dialog-box )
so in my action creator I added the next code:
if(Platform.OS === 'android')
LocationServicesDialogBox.checkLocationServicesIsEnabled({
message: "<h2>Use Location?</h2> \
This app wants to change your device settings:<br/><br/>\
Use GPS for location<br/><br/>",
ok: "YES",
cancel: "NO"
}).then(() => {
locationTracking(dispatch, getState, geolocationSettings)
})
For Network:
There is no native support for neither so i end up doing my own action creator to check.
export function networkCheck(){
return (dispatch) => {
const dispatchNetworkState = (isConnected) => dispatch({
type: types.NETWORK_STATE,
state: isConnected
})
const handle = () => NetInfo.isConnected.fetch().done(dispatchNetworkState)
NetInfo.isConnected.addEventListener('change', handle);
}
}
A little extra:
for GPS i added this to check if the user goes and disable GPS on the middle of the task.
export function locationCheck(geolocationSettings = {enableHighAccuracy: true, timeout: 20000, maximumAge: 10000, distanceFilter:10}){
return (dispatch) => {
navigator.geolocation.watchPosition(
() => {
dispatch({
type: types.LOCATION_STATE,
state: true
})
},
() => {
dispatch({
type: types.LOCATION_STATE,
state: false
})
},
geolocationSettings)
}
}
For enabling location/gps on Android I can recommend this module: https://github.com/Richou/react-native-android-location-enabler
It is using the standard Android dialog for location:
If you use any kind of package to get the user's location, most likely they will automatically ask for the user to enable the hardware part when you request it for the first time.
So, you can do something like this to show the prompt:
CheckForGPSEnablement() {
return new Promise(resolve => {
RNLocation.configure({
distanceFilter: 100, // Meters
desiredAccuracy: {
ios: "best",
android: "balancedPowerAccuracy",
},
// Android only
androidProvider: "auto",
interval: 5000, // Milliseconds
fastestInterval: 10000, // Milliseconds
maxWaitTime: 5000, // Milliseconds
// iOS Only
activityType: "other",
allowsBackgroundLocationUpdates: false,
headingFilter: 1, // Degrees
headingOrientation: "portrait",
pausesLocationUpdatesAutomatically: false,
showsBackgroundLocationIndicator: false,
})
.then(x => {
console.log({ x })
resolve(true)
})
.catch(err => {
console.log({ err })
resolve(false)
})
})
}
In my case I've used react-native-location.
In recent versions of iOS (>= iOS8?) and Android you can show the app permissions dialog and let users turn on/off permissions such as camera and location. There is a native module to do that: https://github.com/yonahforst/react-native-permissions

Determine user location on iOS Simulator with React Native app using Geolocation API

How can make the app that will be run on the iOS simulator get the geolocation.
Currently I can only get the error output I have written for the error callback for the getCurrentPosition() or the watchPosition().
I have this code in one of my components:
componentDidMount: function(){
var geo = navigator.geolocation;
var positionOptions = {
enableHighAccuracy: true,
timeout: 3000,
maximumAge: 0,
};
var success = function(position){
this.setState({
region: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
},
});
};
var error = function(error){
alert('error watchposition:', error.code);
};
var watchID = geo.watchPosition(success, error, positionOptions);
// geo.getCurrentPosition(success, error, positionOptions);
},
Make sure you have a correct custom location in the debug menu for the simulator.
Also make sure location services enabled in the simulator for your app.