Using Cord-ova to get device position I experience a weird behavior when trying to access position coordinates using the emulator (also deployed the code on my Galaxy S2 ... same issue).
document.addEventListener( "deviceready", onDeviceReady, false);
function onDeviceReady () {
if (navigator.geolocation) {
var options = { timeout: 10000, enableHighAccuracy: true, maximumAge: Infinity };
navigator.geolocation.getCurrentPosition(locationOnSuccess, locationOnSuccess, options);
} else {
alert("Geoloc does not exists");
}
}
var locationOnSuccess = function (pos){
alert('Latitude: ' + pos.coords.latitude);
}
navigator.geolocation exists as it fires the alert
This says latitude undefined and error I get is
11-13 08:44:05.296: D/CordovaLog(1861): file:///android_asset/www/index.html: Line 55 : Uncaught TypeError: Cannot read property 'latitude' of undefined
11-13 08:44:05.296: E/Web Console(1861): Uncaught TypeError: Cannot read property 'latitude' of undefined at file:///android_asset/www/index.html:55
I'm struggling for 1 day now and cannot find anybody having same issue, probably getting blind at looking for too long?
Anybody to help?
Many thanks, S.
Make sure you have enabled this:
(in app/res/xml/config.xml)
<feature name="Geolocation">
<param name="android-package" value="org.apache.cordova.GeoBroker" />
</feature>
(in app/AndroidManifest.xml)
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
also check if your device supports Geolocation
In PhoneGap's documentation the statement to get location updates is defined like the one below.
navigator.geolocation.getCurrentPosition(onSuccess, onError);
So there are success and error cases. But you are calling the same method for both of the cases. So in the case that you don't have geo locations you cannot get the latitude and longitude values. That could cause the error. Instead of showing the error case in else statement, define an error function that shows this in the error case.
First of all change it to locationOnError
navigator.geolocation.getCurrentPosition(locationOnSuccess, locationOnError, options);
navigator.geolocation.watchPosition(coordinates);
function coordinates(p) {
if (lastTrackedLat == null) {
lastTrackedLat = p.coords.latitude;
}
if (lastTrackedLng == null) {
lastTrackedLng = p.coords.longitude;
}
var lastTrackedLatlng = new google.maps.LatLng(lastTrackedLat,lastTrackedLng);
var lat = p.coords.latitude;
var lng = p.coords.longitude;
var Latlng=new google.maps.LatLng(lat,lng);
}
Related
None of the answers on stackoverflow worked for me. A lot of them are for Ionic 1 or those answers are deprecated or they are not working for android device.
I have seen a lot of solutions on stackoverflow about getting current location of device but non of them seems to be working for Android .
what i have tried:-
using geolocation.getCurrentPosition() , which is working for IOS and browser but not for Android.
using this.geolocation.watchPosition() , which is working for IOS and browser but not for Android.
using navigator.geolocation.getCurrentPosition(),which is working for IOS and browser but not for Android.
using fiddle solution provided by this question getCurrentPosition() and watchPosition() are deprecated on insecure origins
Anyway , all of these are deprecated by google due to :-
getCurrentPosition() and watchPosition() are deprecated on insecure
origins, and support will be removed in the future. You should
consider switching your application to a secure origin, such as HTTPS.
See goo.gl/rStTGz for more details.
what worked for me is (https://ionicframework.com/docs/native/background-geolocation/ ) & (https://www.joshmorony.com/adding-background-geolocation-to-an-ionic-2-application/ ) both of these are based on background-geolocation plugin but,it's taking almost 50-55 sec on Android device, again it's working fine for ios
The problem with joshmorony(https://www.joshmorony.com/adding-background-geolocation-to-an-ionic-2-application/ ) solution is foreground is not working for Android physical devices but working fine for browser and ios. Background tracking is working fine , which is taking almost 50 sec to give lat & lng for the first time.
Please help me with this. I want a way to get current location in minimum time. For your info, I am using google javascript map sdk / api .
I tried every solution provided by all of you and others also on internet. Finally i found a solution.You can try this plugin cordova-plugin-advanced-geolocation (https://github.com/Esri/cordova-plugin-advanced-geolocation ) from ESRI . But this plugin will work for Android not IOS. For ios you can go with same old approach . i.e - using this.geolocation.getCurrentPosition(...) or this.geolocation.watchPosition(..).
Add cordova-plugin-advanced-geolocation Plugin Like this :-
cordova plugin add https://github.com/esri/cordova-plugin-advanced-geolocation.git
then Add below line at the top of Class / Component
declare var AdvancedGeolocation:any; //at the top of class
Now add these lines inside relevant function of component ( P.S. - I have included code for both Android & IOS)
//**For Android**
if (this.platform.is('android')) {
this.platform.ready().then(() => {
AdvancedGeolocation.start((success) => {
//loading.dismiss();
// this.refreshCurrentUserLocation();
try {
var jsonObject = JSON.parse(success);
console.log("Provider " + JSON.stringify(jsonObject));
switch (jsonObject.provider) {
case "gps":
console.log("setting gps ====<<>>" + jsonObject.latitude);
this.currentLat = jsonObject.latitude;
this.currentLng = jsonObject.longitude;
break;
case "network":
console.log("setting network ====<<>>" + jsonObject.latitude);
this.currentLat = jsonObject.latitude;
this.currentLng = jsonObject.longitude;
break;
case "satellite":
//TODO
break;
case "cell_info":
//TODO
break;
case "cell_location":
//TODO
break;
case "signal_strength":
//TODO
break;
}
}
catch (exc) {
console.log("Invalid JSON: " + exc);
}
},
function (error) {
console.log("ERROR! " + JSON.stringify(error));
},
{
"minTime": 500, // Min time interval between updates (ms)
"minDistance": 1, // Min distance between updates (meters)
"noWarn": true, // Native location provider warnings
"providers": "all", // Return GPS, NETWORK and CELL locations
"useCache": true, // Return GPS and NETWORK cached locations
"satelliteData": false, // Return of GPS satellite info
"buffer": false, // Buffer location data
"bufferSize": 0, // Max elements in buffer
"signalStrength": false // Return cell signal strength data
});
});
} else {
// **For IOS**
let options = {
frequency: 1000,
enableHighAccuracy: false
};
this.watch = this.geolocation.watchPosition(options).filter((p: any) => p.code === undefined).subscribe((position: Geoposition) => {
// loading.dismiss();
console.log("current location at login" + JSON.stringify(position));
// Run update inside of Angular's zone
this.zone.run(() => {
this.currentLat = position.coords.latitude;
this.currentLng = position.coords.longitude;
});
});
}
EDIT : First installation is always going fine. But Sometimes you might get errors for no reason in subsequent installations. To make this error (any error with this plugin ) go away.Follow these steps :
1. Remove this plugin from your project (including config.xml and package.json).
2. Delete/Remove android platform.
3. Delete plugins folder.
4. Now reinstall this plugin again, following the steps above.
I have gone through the problem and find the solution.
the best way to get geolocation of the user is to use this plugin https://ionicframework.com/docs/native/geolocation/
do not forget to add this is app.moudle.ts as its a provider.
by simply adding this code in app component i was able to get location( do not forget to import and add in constructor)
this.geolocation.getCurrentPosition({ enableHighAccuracy: true }).then((resp) => {
console.log(resp);
}, Error => {
console.log(Error);
}).catch(Error => {
console.log(Error);
})
i only have the same error while i was using ionic cordova run
android --livereload that is insecure origin
but when i use ionic serve i can see the response in browser and also after
using ionic cordova run android
just to confirm response in android i check the chrome debugger.
It works for me
import { Geolocation } from '#ionic-native/geolocation/ngx';
import { NativeGeocoder, NativeGeocoderOptions, NativeGeocoderResult } from '#ionic-native/native-geocoder/ngx';
geoencoderOptions: NativeGeocoderOptions = {
useLocale: true,
maxResults: 5
};
constructor(
private geolocation: Geolocation,
private nativeGeocoder: NativeGeocoder
) {
getCurrentLocation() {
this.geolocation.getCurrentPosition()
.then((resp) => {
this.getGeoencoder(resp.coords.latitude, resp.coords.longitude);
}).catch((error) => {
console.log('Error getting location', error);
});
}
//geocoder method to fetch address from coordinates passed as arguments
getGeoencoder(latitude, longitude) {
this.nativeGeocoder.reverseGeocode(latitude, longitude, this.geoencoderOptions)
.then((result: NativeGeocoderResult[]) => {
const address = this.generateAddress(result[0]);
})
.catch((error: any) => {
// alert('Error getting location' + JSON.stringify(error));
});
}
//Return Comma saperated address
generateAddress(addressObj) {
let obj = [];
let address = "";
for (let key in addressObj) {
obj.push(addressObj[key]);
}
obj.reverse();
for (let val in obj) {
if (obj[val].length)
address += obj[val] + ', ';
}
return address.slice(0, -2);
}
you need to provide the permission for Android app as follows:
<feature name="Geolocation">
<param name="android-package" value="org.apache.cordova.GeoBroker" />
</feature>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
I ran into a similar problem. When I build from the terminal with the --prod flag, I no longer see this error since it is now requesting position over https.
Built without --prod flag
Built using the --prod flag
Edit: Sorry for the format, I hope that this makes a little more sense. I used the following function in a service that I could call from anywhere to get the latitude, longitude, accuracy, and timestamp. The key though is using the --prod flag in the terminal when building the app.
this.geolocation.getCurrentPosition().then(position => {
let locationObj = {
lat: position.coords.latitude,
lon: position.coords.longitude,
timestamp: position.timestamp,
accuracy: position.coords.accuracy
};
resolve(locationObj);
})
this method is working for bot android and browser
watchLocation() {
this.watchLocationUpdates = this.geolocation.watchPosition({ maximumAge: 60000, timeout: 25000, enableHighAccuracy: true })
.subscribe(resp => {
this.latitude = resp.coords.latitude;
this.longitude = resp.coords.longitude;
this.altitude = resp.coords.altitude;
this.accuracy = resp.coords.accuracy;
this.altAccuracy = resp.coords.altitudeAccuracy;
this.heading = resp.coords.heading;
this.speed = resp.coords.speed;
this.timestamp = new Date(resp.timestamp);
});
}
I found solution for me: use google api https://www.googleapis.com/geolocation/v1/geolocate?key={API_KEY}
If platform Android I use google api.
I use cordova
// Platform: android
// 3.5.1
When I use Geolocation
var options = {enableHighAccuracy: true};
navigator.geolocation.getCurrentPosition(that.geoSuccess, that.geoError, options);
this.geoSuccess = function(position) {
console.log("geoSuccess :"+position.coords.latitude+", "+ position.coords.longitude)
that.mylocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
};
I get in the log:
31.4956033, 34.9326514
which is a 3.7 Kilometre from my actual location.
Any idea why? or how to fix?
on ios I get the following position:
31.518463052524, 34.90405467862522
which is my actual position, therefore the code is correct.
When I use google map (on the android device) my position is correct, therefore it's not hardware problem.
in my manifest I have:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
I noticed this problem as well. However, when I polled my location for change using watchPosition, it fixed it for me. From what I can tell, the initial GPS fix is inaccurate. Given time it closes the distance.
Something like:
watchID = navigator.geolocation.watchPosition(onSuccess, onError, options);
function onSuccess(position) {
var myLatLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(myLatLng);
if(marker!=null)
marker.setMap(null);
marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: 'My Location'
});
}
You need to ask for high accuracy
var options = {enableHighAccuracy: true};
navigator.geolocation.getCurrentPosition(that.geoSuccess, that.geoError, options);
Geolocation options
I'm using Phonegap Build to develop an application for iOS and Android.
I'd like to determine the locale (e.g. 'en-US') for the device, though I'd settle for the current language setting, or even the app store my app was installed from (it's been a long day).
Following the instructions here for the Globalization plugin I think I have everything right, but nothing seems to work on either the iPhone 6 or Samsung Galaxy Nexus I'm using for testing.
The relevant part of my config.xml looks like this:
<gap:plugin name="org.apache.cordova.globalization" />
My function for getting locale from the plugin looks like this:
var getPhoneGapLocaleName = function() {
var loc = 'unknown';
if (navigator.globalization !== undefined) {
navigator.globalization.getLocaleName(
function (locale) {
if (locale !== undefined) {
loc = locale.value;
}
},
function () {
// nothing
}
);
}
return loc;
};
Note: on both devices navigator.globalization.getLocaleName is present and appears correct, evaluating to a function resembling what I'd expect based on the documentation.
The problem here was that the variable 'loc' was declared outside the scope of the success or failure callbacks, which of course happen after a few brief moments.
I fixed this by changing the function thus:
var refreshPhoneGapLocaleName = function() {
if (navigator.globalization !== undefined) {
navigator.globalization.getLocaleName(
function (locale) {
if (locale !== undefined) {
localStorage['pg.locale'] = locale.value;
}
},
function () {
// nothing
}
);
}
};
Now calling it in onDeviceReady in order to refresh the values when the app starts.
A few moments later (not immediately) the following function can be used to retrieve the locale value:
var getLocale = function() {
return localStorage['pg.locale']();
};
The greatest thing about StackOverflow is how often it helps one to resolve one's own silly mistakes. :)
Although previous answers are returning the desired result, and giving an option to retrieve the current phonegap locale name, they did not explain the topic starter why his function did not work, and how to adjust his function to work in the way he intended (i.e. not using localStorage and not showing the locale in the console but giving the answer in real-time as a result)
I am posting this answer since I was looking for a quick function to get the device locale, and this post was my first result. While the opening post gave me everything I needed, I would like to answer this question for future visitors with the same purpose I had. Sorry for posting to a topic this old, but I hope I can help others with my answer.
The reason the function of topic starter does not work is the following: the plugin returns the locale in an asynchronous way. Therefore, the loc =locale.value line is only executed after the function's return statement. To fix this, we can write a wrapper function to simplify the plugins output as follows. Keep in mind that we need to use this function asynchronously, since the plugin result is also asynchronous.
The function:
var getPhoneGapLocaleName = function ( callback ) {
var unknownLocation = 'unknown'; //Default value
if ( navigator.globalization !== undefined ) {
navigator.globalization.getLocaleName(
function ( locale ) {
if ( locale !== undefined ) {
callback( locale.value );
} else {
callback( unknownLocation );
}
},
function () {
callback( unknownLocation );
}
);
} else {
callback( unknownLocation );
}
};
Use the function like this:
getPhoneGapLocaleName( function( loc ){ console.log( 'The locale was set as follows: ' + loc ); } );
Try this code
When the browser is set to the en_US locale, this should display a popup dialog with the text language: English:
navigator.globalization.getPreferredLanguage(
function (language) {alert('language: ' + language.value + '\n');},
function () {alert('Error getting language\n');}
);
Full Example
<!DOCTYPE HTML>
<html>
<head>
<title>getPreferredLanguage Example</title>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function checkLanguage() {
navigator.globalization.getPreferredLanguage(
function (language) {alert('language: ' + language.value + '\n');},
function () {alert('Error getting language\n');}
);
}
</script>
</head>
<body>
<button onclick="checkLanguage()">Click for language</button>
</body>
</html>
I have website using javascript geolocation api and want it to open in a webview. I set up these permissions in the manifest file:
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
In my activity, I also set webview settings:
webview.getSettings().setDatabaseEnabled(true);
webview.getSettings().setDomStorageEnabled(true);
webview.getSettings().setGeolocationDatabasePath("/data/data/com.my.app/databases");
webview.getSettings().setGeolocationEnabled(true);
And I also handled javascript geolocation dialog:
webview.setWebChromeClient(new WebChromeClient(){
#Override
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
});
Geolocation itself is working, but I am not able to cache geoposition into the database. It should be doing it by itself into CachedGeoposition.db, but when I start the webview, i get this strange SQLite error:
E/SQLiteLog(22653): (14) cannot open file at line 30174 of [00bb9c9ce4]
E/SQLiteLog(22653): (14) os_unix.c:30174: (2) open(/CachedGeoposition.db) -
D/WebKit (22653): ERROR:
D/WebKit (22653): SQLite database failed to load from /CachedGeoposition.db
D/WebKit (22653): Cause - unable to open database file
D/WebKit (22653):
D/WebKit (22653): external/webkit/Source/WebCore/platform/sql/SQLiteDatabase.cp
p(71) : bool WebCore::SQLiteDatabase::open(const WTF::String&, bool)
When I check existence of CachedGeoposition.db file in File Explorer, it is always there,
and permissions of the db are set to -rw-------.
Did I miss something in settings what could cause database not to open correctly?
I'm new to Android and trying to find solution for 2 days now. Any help would be greatly appreciated. Thank you.
I'll post a solution that worked for me in the hope that it might provide some ideas on where the error might be. It would also help if you could provide details about the device(emulator)/os on which you're testing.
I tested on (with no errors):
(Emulator) Galaxy Nexus (2.3.3) (data/data/package.name/files/CachedGeoposition.db file created)
(Emulator) Galaxy Nexus (3.0) (data/data/package.name/files/CachedGeoposition.db file created)
HTC One S (4.1.1) (data/data/package.name/files/CachedGeoposition.db file created)
Galaxy S3 (4.3) (couldn't see the file since my phone is not rooted and there are some 'run-as' bugs on 4.3)
Nexus 7 (4.4.4) - the webview above KIT KAT has changed a bit and the
file is no longer there, but no error was shown (even when providing a wrong 'databases' folder path)
(Emulator) Galaxy S4 (5.0) (same as on 4.4.4)
AndroidManifest permissions (pretty much the same):
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Web view settings:
WebSettings webSettings = webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setGeolocationDatabasePath(getFilesDir().getPath());
webSettings.setGeolocationEnabled(true);
Web chrome client (the same):
webview.setWebChromeClient(new WebChromeClient(){
#Override
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
});
Test html file for getting the geolocation:
<!DOCTYPE html>
<html>
<head>
<script>
var x = document.getElementById("demo");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, showError);
} else {
x.innerHTML = "Geolocation is not supported by this browser.";
}
}
function showPosition(position) {
var latlon = position.coords.latitude + "," + position.coords.longitude;
document.getElementById("locationHolder").innerHTML = latlon;
}
function showError(error) {
switch(error.code) {
case error.PERMISSION_DENIED:
x.innerHTML = "User denied the request for Geolocation.";
break;
case error.POSITION_UNAVAILABLE:
x.innerHTML = "Location information is unavailable";
break;
case error.TIMEOUT:
x.innerHTML = "The request to get user location timed out.";
break;
case error.UNKNOWN_ERROR:
x.innerHTML = "An unknown error occurred.";
break;
}
}
</script>
</head>
<body>
<p id="demo">Click the button to get your position.</p>
<div id="locationHolder">No location</div>
<button onclick="getLocation()">Get position</button>
</body>
</html>
Also, for a local test, you could created a file containing the html under '/assets/www/index.html' and use the following code to load it into the webview:
try {
String html = readAssetFile("www/index.html");
webview.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null);
} catch (IOException e) {
}
Read asset file method:
private String readAssetFile(String filePath) throws IOException {
StringBuilder buffer = new StringBuilder();
InputStream fileInputStream = getAssets().open(filePath);
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
String str;
while ((str=bufferReader.readLine()) != null) {
buffer.append(str);
}
fileInputStream.close();
return buffer.toString();
}
I couldn't reproduce your error without providing a wrong hardcoded path to the 'databases' folder.
The line
D/WebKit (22653): SQLite database failed to load from /CachedGeoposition.db
is interesting
Try setting the appropriate DB path in WebSettings.setDatabasePath as well, it could be that this is used as the root for the geo db path
I know this is an old question but anyone with this issue might find interesting focusing on this function:
mWebView.getSettings().setGeolocationDatabasePath(getFilesDir().getPath());
Geolocation uses databases to persist cached positions and permissions between sessions.
This call sets the location of the database.
Instead of setting a fixed path as parameter you should get it dynamically calling:
getFilesDir().getPath()
I'm writing web application for mobile phones and I need to use geolocation.
I wrote: (javascript)
function GeoLocationStart(){
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(onSuccess,onError);
}
else{
alert("Functionality not available");
}
}
function onSuccess(position) {
var initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
map.setCenter(initialLocation);
var userMarker = new google.maps.Marker({
position: initialLocation,
map: map,
title: "You're here",
icon: face
});
userMarker.setMap(map);
var userhtml = "It's you!";
var UserInfoWindow = new google.maps.InfoWindow({content: userhtml});
google.maps.event.addListener(userMarker, 'click', function() {
UserInfoWindow.open(map, userMarker);
});
};
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
It works fine but without GPS.
Though I set in Android manifest file permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
app doesn't start even searching sattelites. (Of course I checked GPS on my phone, it works in other applications)
How to switch GPS on?
Thanks
I found a solution.
After location had found using wireless network, GPS stopped to work because the goal has been achieved - location is defined!
To continue searching position I wrote
var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { frequency: 3000 });
so GPS launched.