So I have built an app in ionic2 that tracks the phone's current location. I have built it in android and works fine when the location is on but when I built it on iOS the app doesn't show on Privacy>Location Services and doesn't track the phone's current location.
const watchOptions = {
enableHighAccurary: true,
maximumAge:5000,
timeout: 5000
}
if(state == 'login'){
this.watch = this.geolocation.watchPosition(watchOptions).subscribe(pos => {
if(pos.coords != undefined){
console.log('tracking');
this.firebaseApp.database().ref("LOCATION").child(this.user.$key).update({
lat: pos.coords.latitude,
lng: pos.coords.longitude,
timeStamp: moment().format('MMMM Do YYYY, hh:mm A').toString(),
fName: this.user.fName,
lName: this.user.lName,
status: 'login'
});
}
});
}
else{
this.watch.unsubscribe();
}
You have to enter NSLocationWhenInUseUsageDescription-key and NSLocationAlwaysAndWhenInUseUsageDescription-key to .plist-file.
You find this file in "platforms/ios"
Related
I am new to mobile development. I am trying to access my current location in the ios simulator running IOS 14.4 and I keep getting the "Location Permission denied" error even after setting up the custom location in the simulator as suggested by some answers on this platform, here. The code that I am running is this
Geolocation.getCurrentPosition(
position => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
coordinates: this.state.coordinates.concat({
latitude: position.coords.latitude,
longitude: position.coords.longitude
})
});
},
error => {
Alert.alert(error.message.toString());
},
{
showLocationDialog: true,
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 0
}
);
I have set up these permissions in my info-plist.
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Description</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Will you allow this app to always know your location?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Do you allow this app to know your current location?</string>
I am not entirely sure what I might be doing wrong here. This is the only code currently that tries to access the location.
Is there any other reason why this error should persist even after setting the current location as the custom location in Features->Location->customlocation? as suggested by the other answers on this platform.
It's required to ask location access permission at run-time before you run code that requires location access.
react-native-permissions is the standard library for cross-platform permissions
Follow installation instruction here - https://www.npmjs.com/package/react-native-permissions
import { request, PERMISSIONS, RESULT } from "react-native-permissions";
function getUserLocation() {
Geolocation.getCurrentPosition(
(position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
coordinates: this.state.coordinates.concat({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
}),
});
},
(error) => {
Alert.alert(error.message.toString());
},
{
showLocationDialog: true,
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 0,
}
);
}
request(PERMISSIONS.IOS.LOCATION_ALWAYS).then((result) => {
switch (result) {
case RESULTS.UNAVAILABLE:
console.log(
"This feature is not available (on this device / in this context)"
);
break;
case RESULTS.DENIED:
console.log(
"The permission has not been requested / is denied but requestable"
);
break;
case RESULTS.LIMITED:
console.log("The permission is limited: some actions are possible");
break;
case RESULTS.GRANTED:
console.log("The permission is granted");
// Permission has been granted - app can request location coordinates
getUserLocation();
break;
case RESULTS.BLOCKED:
console.log("The permission is denied and not requestable anymore");
break;
}
});
I am working on IOT project with react native in which Phone must connect to a protected WiFi(no internet connection). I should programmatically turn on WiFi and connect to the protected ssid. So, I used the following library: https://github.com/JuanSeBestia/react-native-wifi-reborn.
On android, I have full control on device and everything works like a charm. On the other hand, on ios, I can't turn wifi on and even after that user turns the wifi on, it seems defined functions in library like connectToProtectedSSID just doesn't work.
Any advice would be appreciated.
P.s. I exactely followed the document in the library including location access in both platforms.
Finally, the solution for both platforms:
iOS:
with the following approach app will turn on WIFI and connect to the specific SSID (at least for iOS 13):
You should add these capabilities to your app :
Access WiFi Information
Hotspot Configuration ( this is missed in the README ! )
(iOS 13) "Privacy - Location When In Use Usage
Description" or "Privacy - Location Always and When In Use Usage
Description" in Settings -> info
import WifiManager from "react-native-wifi-reborn";
ConnectToNetwork = async () => {
WifiManager.connectToProtectedSSID("YourSSIDName", "YourPassword", false)
.then(
() => {
//console.log("connectToProtectedSSID successfully!");
},
(reason) => {
//console.log("connectToProtectedSSID failed!");
//console.log(reason);
}
);
}
Android:
Don't forget to turn on location!
disconnecting from the current SSID and connecting to the desired one:
import RNAndroidLocationEnabler from 'react-native-android-location-enabler';
import WifiManager from "react-native-wifi-reborn";
ConnectToNetwork() {
WifiManager.setEnabled(true);
WifiManager.disconnect();
//WifiManager.forceWifiUsage(true);
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: '',
message:'',
buttonNegative: '',
buttonPositive: '',
},
).then((granted) => {
//console.log(granted);
if (granted === PermissionsAndroid.RESULTS.GRANTED)
{
//console.log("granted");
RNAndroidLocationEnabler.promptForEnableLocationIfNeeded({interval: 10000, fastInterval: 5000})
.then(data => {
WifiManager.connectToProtectedSSID("YourSSIDName", "YourPassword", false)
.then(
() => {
//console.log("connectToProtectedSSID successfully!");
},
(reason) => {
//console.log("connectToProtectedSSID failed!");
//console.log(reason);
}
);
//console.log("location enabled");
//WifiManager.connectToProtectedSSID("", "", false)
WifiManager.getCurrentWifiSSID().then(
ssid => {
if(ssid =="YourSSIDName"){
}
else {
}
//console.log("Your current connected wifi SSID is " + ssid);
},
() => {
//console.log("Cannot get current SSID!");
}
);
}).catch(err => {
//console.log("not permitted to enable location");
});
}
else
{
//console.log("not granted");
// Permission denied
}
// expected output: "Success!"
});
}
There is no public API to control the Wifi on iOS.
Method setEnabled is only for android.
This package
I need solution for i want to update location every 30 seconds.
I'm using this package for background geolocation updates when its working fine, but when i move my phone (iphone6) it send my location to firebase. I'm using location changes of this package because postTemplate is not working on IOS device and stoOnStillActivity:true for if activity is still it wont send location.
BackgroundGeolocation.configure({
locationProvider: BackgroundGeolocation.ACTIVITY_PROVIDER,
desiredAccuracy: BackgroundGeolocation.MEDIUM_ACCURACY,
stationaryRadius: 10,
distanceFilter: 10,
debug: true,
interval: 30000,
stopOnStillActivity: true,
})
This one sending location to firebase
BackgroundGeolocation.on('location', (location) => {
BackgroundGeolocation.startTask(taskKey => {
firestore()
.collection('testlocation')
.add({
name: 'DEVICE',
lat: location.latitude,
lon: location.longitude,
dat: new Date,
})
.then(() => {
console.log('Location added BITCH!')
}).catch(e => console.log(e))
console.log("Stark task started successfully", new Date, location.latitude, location.longitude)
BackgroundGeolocation.endTask(taskKey)
})
})
Building an app with RN I use the following to receive user's location :
navigator.geolocation.getCurrentPosition(
(position) => {
//do stuff with location
},
(error) => {
//error or locaiton not allowed
},
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
);
Which immediately invokes the inquiry for user to accept geolocation permissions. What I'm trying to achieve now is to have an explicit screen before prompting user to click on a button to accept those permissions. In order to get there, I need some way to check if he has accepted those permissions before or not. Caching it in storage would be a bad solution - it might go out of sync if user changes permissions in settings.
How can I check if user has accepted geolocation permissions without triggering the permission alert?
You can use this library https://github.com/yonahforst/react-native-permissions to check if user has accepted location permission.
Like this:
Permissions.getPermissionStatus('location')
.then(response => {
this.setState({ locationPermission: response })
})
In v2.x.x of react-native-permissions (https://github.com/react-native-community/react-native-permissions)
import { Platform } from "react-native";
import { PERMISSIONS, request } from "react-native-permissions";
import * as Geolocation from "#react-native-community/geolocation";
try {
request(
Platform.select({
android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE
})
).then(res => {
if (res == "granted") {
Geolocation.getCurrentPosition( // do location staffs);
Geolocation.watchPosition( // do watch location staffs );
} else {
// console.log("Location is not enabled");
}
});
} catch (error) {
console.log("location set error:", error);
}
Check this library, this would help you to check location is enabled or not.
https://www.npmjs.com/package/react-native-device-info#isLocationEnabled
Note : Above will not check permission enabled on not. It will just check location truned on or not
I'm developing cross platform applications. I'm able to request access to location using the Phone Gap API. If the user clicks okay, then I'm able to get the latitude and longitude using PhoneGap API and send it to the server.
However, I'm facing issues if the user clicks "Don't Allow" initially. After that, if he tries to refresh page, I want the device to show the popup again to request access to the location.
How do we do that in Single Page Applications?
var loadPanelMessage = ko.observable("Sipping..."),
loadPanelVisible = ko.observable(false),
lat = ko.observable(''),
lon = ko.observable('');
navigator.geolocation.getCurrentPosition(onSuccess, onError);
var onSuccess = function (position) {
lat(position.coords.latitude);
lon(position.coords.longitude);
timestamp(position.timestamp);
};
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
//How should I handle the error, so that it asks for Geolocation again?
}
You cannot reshow that popup, it is shown by iOS and once user click's "Don't Allow" you cannot force that popup. All you can do is to let your user know about the situation and direct the user to iOS settings to enable location services for your app.
Here is a nice read about the problem:
https://medium.com/on-startups/96fa4eb54f2c
Based on the cordova plugins here org.apache.cordova.geolocation
All you need to do is a watchPosition to check the PositionError, and use also the cordova-plugin-dialogs to show the native notification
navigator.geolocation.watchPosition((function(_this) {
return function(position) {
// Do something here
};
})(this), function(error) {
var errorButton, errorMsg, errorTitle;
errorTitle = "Location Services";
errorButton = "Ok";
if (error.code === 1) {
errorMsg = "\"AppName\" needs access to your location. Please turn on Location Services in your device settings.";
}
if (error.code === 2) {
errorMsg = "This device is unable to retrieve a position. Make sure you are connected to a network";
}
if (error.code === 3) {
errorMsg = "This device is unable to retrieve a position. Make sure you have Location Services enabled for \"AppName\"";
}
if (error.code === 1 || error.code === 2 || error.code === 3) {
return navigator.notification.alert(errorMsg, errorDismissed(), errorTitle, errorButton);
}
}, {
enableHighAccuracy: true,
maximumAge: 20000,
timeout: 10000
});