Cordova geolocation plugin doesn't work on android - javascript

I'm using cordova ,geolocation plugin for showing latitude and longitude on android. There are plenty of question same as this so I read and tried their solution but couldn't fix the problem. The code below works perfectly on browser.
I tried 3 method, first: "navigator.geolocation.watchPosition" which returns wrong result(37.42,-122.08) in emulator(Android Studio) and doesn't return anything in device.
I also tried "navigator.geolocation.getCurrentPosition" with both "enableHighAccuracy" set 'true' and 'false' and I get timeOut error alerted.
When I delete deviceready, I don't get the timeOut, just wrong result from all three methods.
(function (window) {
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
var minAccuracyInMetres = 50;
var positionWatcher;
positionWatcher = navigator.geolocation.watchPosition(
geolocationSuccess2,
geolocationError2,
{ maximumAge: 0, timeout: 100000, enableHighAccuracy: true });
function geolocationSuccess2(position) {
// Reject if accuracy is not sufficient
if (position.coords.accuracy > minAccuracyInMetres) {
return;
}
// Only single position required so clear watcher
navigator.geolocation.clearWatch(positionWatcher);
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
};
function geolocationError2(error) {
console.warn("Error while retrieving current position. " +
"Error code: " + error.code + ",Message: " + error.message);
}
//2
var onSuccess1 = function (position) {
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
};
function onError1(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n' + 'highaccuracy: true');
}
var options1 = { maximumAge: 0, timeout: 300000, enableHighAccuracy: true };
navigator.geolocation.getCurrentPosition(onSuccess1, onError1, options1);
//3
var onSuccess = function (position) {
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n')
};
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n' + ' high accuracy:false');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError, { enableHighAccuracy: false, timeout: 300 * 1000, maximumAge: 0 });
}
})(window);
I get the watchPosition part from another question in stackoverflow.
I use cordova version: 6.4.0.
I deleted the plugin and tried again but it didn't work.
the device I'm testing with is a lenovo tablet.
Thanks a lot.
UPDATE: my Geolocation version is: 2.4.0 Is it important???

After two days of struggling I turned on "High accuracy" in location settings. The app Works now!!!

Related

How to return coordinates from a service in angularJS / cordova

I'm having trouble passing the data from my geolocationService to my weatherCtrl. I want to pass the position in my controller so I can send my openweather api's request.
Also, i have troubles understanding how is the data stored in services and how to use them correctly.
Here are my js files.
geolocationService.js
angular.module('app').service('geolocationService', function() {
geolocationSuccess = function(position){
alert(
'Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
return position;
}
geolocationError = function(error) {
alert(
'code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
this.getGeolocation = function(){
navigator.geolocation.getCurrentPosition(geolocationSuccess,geolocationError);
}});
weatherCtrl.js
angular.module('app').controller('weatherCtrl',['$scope', '$http', 'cityService', 'geolocationService',
function($scope, $http , cityService, geolocationService){
$scope.searchCity = function () {
var apiKey = "****";
var apiLang = "en"
var url = "http://api.openweathermap.org/data/2.5/forecast/daily?q="+$scope.city+"&APPID="+apiKey+"&units=metric&lang="+apiLang;
$http.get(url).success(httpSuccess).error(function(){
alert("Erreur : données non récupérées");
});
}
$scope.Math = Math;
httpSuccess = function(response){
$scope.weather = response;
}
$scope.setCity = function (city){
cityService.set(city);
}
$scope.geolocate = function (){
$scope.position = geolocationService.getGeolocation();
}
}
]);
So when I call geolocate(), the geolocationSuccess function is called but I don't know how to return the position correctly.
You return the position in your geolocationSuccess function, but didn't assign it to any variable.
because navigator.geolocation.getCurrentPosition is an async call.
ref: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition
so I do geolocationService.setGeolocation first, you can bind it to any other function, just be aware of async issue.
I add a Promise way to solve async issue, check the bottom.
weatherCtrl.js
app.controller('weatherCtrl', ['$scope', 'geolocationService',
function ($scope, geolocationService) {
geolocationService.setGeolocation();
$scope.geolocate = function () {
$scope.position = geolocationService.getGeolocation();
// now you can use $scope.position object.
console.log($scope.position);
}
}
]);
geolocationService.js
angular.module('app').service('geolocationService', function () {
var currentPosition = {};
geolocationSuccess = function (position) {
alert(
'Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
// set any properties you needs
currentPosition.latitude = position.coords.latitude;
currentPosition.longitude = position.coords.longitude;
// no need to return position here;
}
geolocationError = function (error) {
alert(
'code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
this.setGeolocation = function (position) {
navigator.geolocation.getCurrentPosition(geolocationSuccess, geolocationError);
}
this.getGeolocation = function () {
return currentPosition;
}
});
Deal with Async: Using Promise Approach:
weatherCtrl.js
app.controller('weatherCtrl', ['$scope', 'geolocationService',
function ($scope, geolocationService) {
$scope.geolocate = function () {
geolocationService.getGeolocation().then(pos => {
$scope.position = pos;
console.log($scope.position);
})
.catch(err => console.error(err));
}
}
]);
geolocationService.js
angular.module('app').service('geolocationService', function () {
this.getGeolocation = function () {
return new Promise(function (resolve, reject) {
navigator.geolocation.getCurrentPosition(function (position) {
resolve(position);
}, function (error) {
reject(error);
});
})
}
});

Pass data to array javascript

How do I data is returned for an array and not for the functions onSuccess and onError?
function onSuccess(position) {
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
}
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 });
Example of what I need:
geolocation = navigator.geolocation.watchPosition(null, null, { timeout: 30000 });
if(!geolocation.error)
alert(geolocation.coords.latitude);
Plugin: https://github.com/apache/cordova-plugin-geolocation
I guess from your question that you would like your code to execute linearly. But it cannot. The block of code is executed, then, eventually, the location arrives and the callback is called. But it happens at a different time (even a few ms count) and in a different stack trace. This is how asynchronous Javascript works.
If you're not familiar with the concept, you should go read some articles on the subject. For your reference, I've translated your code into Promise code, which is one of the best technique available to help with asynchronicity.
new Promise(function(resolve, reject) {
navigator.geolocation.watchPosition(resolve, reject, { timeout: 30000 });
})
.then(function(location) {
console.log(location.coords.latitude);
})
.catch(function (error) {
console.log('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
});
BTW, do yourself a favor and use console.log. alert() is so 2000's! :)

How to launch Navigator in cordova in ios

I have an app where (AngularJs+cordova), I need to get current position of the user and navigate to destination using google maps.
I am unable to get it work in iOS:
I have tried:
/* $scope.launchNavigator = function() {
console.log("$scope.launchNavigator...");
var deviceType = (navigator.userAgent.match(/iPad/i))  == "iPad" ? "iPad" : (navigator.userAgent.match(/iPhone/i))  == "iPhone" ? "iPhone" : (navigator.userAgent.match(/Android/i)) == "Android" ? "Android" : (navigator.userAgent.match(/BlackBerry/i)) == "BlackBerry" ? "BlackBerry" : "null";
cordova.plugins.diagnostic.isLocationEnabled(onRequestSuccess, onRequestFailure);
if(deviceType === 'Android'){
cordova.plugins.locationAccuracy.request(onRequestSuccess, onRequestFailure, cordova.plugins.locationAccuracy.REQUEST_PRIORITY_HIGH_ACCURACY);
}
else {
// vm.showGPSAlert = true;
// vm.GPSTextAlert = "Please enable Location Services in Settings and Try again"
//function onDeviceReady() {
cordova.plugins.diagnostic.switchToLocationSettings();
//navigator.geolocation.getCurrentPosition(onSuccess, onError);
//}
}
}
function onRequestSuccess(success){
function onDeviceReady() {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
}
function onSuccess(position){
console.log('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
latitudeStart = position.coords.latitude;
longitudeStart = position.coords.longitude;
launchnavigator.isAppAvailable(launchnavigator.APP.GOOGLE_MAPS, function(isAvailable){
var app;
console.log("Location navigate .lat." + )
if(isAvailable){
app = launchnavigator.APP.GOOGLE_MAPS;
}else{
console.warn("Google Maps not available - falling back to user selection");
app = launchnavigator.APP.USER_SELECT;
}
launchnavigator.navigate([vm.dest.latitude,vm.dest.longitude], {
app: app,
start: [latitudeStart,longitudeStart]
});
});
}
function onError(){
}
function onRequestFailure(error){
console.error("Accuracy request failed: error code="+error.code+"; error message="+error.message);
if(error.code !== cordova.plugins.locationAccuracy.ERROR_USER_DISAGREED){
if(window.confirm("Failed to automatically set Location Mode to 'High Accuracy'. Would you like to switch to the Location Settings page and do this manually?")){
cordova.plugins.diagnostic.switchToLocationSettings();
}
}
}*/
<--the above doesn't work for both iOS and Android-->
For android, following works:
/*Get Direction*/
function onDeviceReady() {
//window.open = cordova.InAppBrowser.open;
console.log("Hello... Device redy");
var latitudeStart = '';
var longitudeStart = '';
$scope.launchNavigator = function() {
function onRequestSuccess(success){
console.log("Successfully requested accuracy: "+success.message);
if(navigator.geolocation){
console.log("navigator.geolocation works well");
}
else{
console.log("navigator.geolocation doesnt works well");
}
console.log("Luanch navigate..");
var onSuccess = function(position) {
console.log('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
latitudeStart = position.coords.latitude;
longitudeStart = position.coords.longitude;
launchnavigator.isAppAvailable(launchnavigator.APP.GOOGLE_MAPS, function(isAvailable){
var app;
if(isAvailable){
app = launchnavigator.APP.GOOGLE_MAPS;
}else{
console.warn("Google Maps not available - falling back to user selection");
app = launchnavigator.APP.USER_SELECT;
}
launchnavigator.navigate([vm.dest.latitude,vm.dest.longitude], {
app: app,
start: [latitudeStart,longitudeStart]
});
});
};
// onError Callback receives a PositionError object
//
function onError(erro) {
console.log('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError,{enableHighAccuracy:true});
}
function onRequestFailure(error){
console.error("Accuracy request failed: error code="+error.code+"; error message="+error.message);
if(error.code !== cordova.plugins.locationAccuracy.ERROR_USER_DISAGREED){
if(window.confirm("Failed to automatically set Location Mode to 'High Accuracy'. Would you like to switch to the Location Settings page and do this manually?")){
cordova.plugins.diagnostic.switchToLocationSettings();
}
}
}
cordova.plugins.locationAccuracy.request(onRequestSuccess, onRequestFailure, cordova.plugins.locationAccuracy.REQUEST_PRIORITY_HIGH_ACCURACY);
}
the above doesn't work for both iOS and Android
Firstly, I would use cordova-plugin-device to determine the platform rather than user agent sniffing - it is more robust.
Secondly, it appears you have a function dependent on the deviceready event which is invoked on the successful outcome of a plugin result:
function onRequestSuccess(success){
function onDeviceReady() {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
}
Cordova plugins are dynamically loaded before the deviceready event is invoked, so it's likely that the inner function is never invoked.
Thirdly, the success callback function for both cordova.plugins.diagnostic.isLocationEnabled() and cordova.plugins.locationAccuracy.request() appears to be onRequestSuccess().
Both of the former are invoked in serial synchrony but their callbacks are invoked asynchronously, so this is likely to lead to problems.
I would try something like this:
function onDeviceReady(){
console.log("onDeviceReady...");
$scope.launchNavigator = function() {
console.log("$scope.launchNavigator...");
cordova.plugins.diagnostic.isLocationEnabled(function(enabled){
if(!enabled){
if(device.platform === 'Android'){
cordova.plugins.locationAccuracy.request(getCurrentPosition,
function(error){
console.error("Accuracy request failed: error code="+error.code+"; error message="+error.message);
if(error.code !== cordova.plugins.locationAccuracy.ERROR_USER_DISAGREED){
if(window.confirm("Failed to automatically set Location Mode to 'High Accuracy'. Would you like to switch to the Location Settings page and do this manually?")){
cordova.plugins.diagnostic.switchToLocationSettings();
}
}
}, cordova.plugins.locationAccuracy.REQUEST_PRIORITY_HIGH_ACCURACY);
}
else {
// vm.showGPSAlert = true;
// vm.GPSTextAlert = "Please enable Location Services in Settings and Try again"
//function onDeviceReady() {
cordova.plugins.diagnostic.switchToLocationSettings();
//navigator.geolocation.getCurrentPosition(onSuccess, onError);
//}
}
}else{
getCurrentPosition();
}
}, function onLocationEnabledFailure(error){
console.error("Failed to check if location is enabled");
});
function getCurrentPosition(){
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
function onSuccess(position){
console.log('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
latitudeStart = position.coords.latitude;
longitudeStart = position.coords.longitude;
launchnavigator.isAppAvailable(launchnavigator.APP.GOOGLE_MAPS, function(isAvailable){
var app;
console.log("Location navigate .lat." + )
if(isAvailable){
app = launchnavigator.APP.GOOGLE_MAPS;
}else{
console.warn("Google Maps not available - falling back to user selection");
app = launchnavigator.APP.USER_SELECT;
}
launchnavigator.navigate([vm.dest.latitude,vm.dest.longitude], {
app: app,
start: [latitudeStart,longitudeStart]
});
});
}
function onError(positionError){
// Handle Error
}
} //$scope.launchNavigator
}// onDeviceReady
In general, I would highly recommend using Safari Remote Debugging and Chrome Remote Debugging tools to debug your app while running on iOS and Android devices respectively.
Using the step-through debugger with appropriate breakpoints will highlight issues such as those present in your code snippet.
See the Debugging Cordova apps section in the Cordova docs for details.

Add href to .text output in jquery

I'm using firebase to get this data,
I'd like to add href tags to message.userName output
$('#winners').text('Winner:' + ' ' + message.userName + ' ' + ' '+ 'score:' + ' ' + message.score + ' ' + ' '+ 'Start time:' + ' ' + message.startTime + ' ' + ' '+ 'End time:' + '' + message.endTime );
I've tried
$('#winners').text('Winner:' + ' ' + '<a href=\"scoreTracker.php?id='+message.userID +'\"> + ' message.userName + ' ' + ' '+ 'score:' + ' ' + message.score + ' ' + ' '+ 'Start time:'
+ ' ' + message.startTime + ' ' + ' '+ 'End time:' + '' + message.endTime + '<\a>' );
To avoid XSS attacks (among other weird problems), append an anchor element and set its text. This means you don't have to worry about escaping anything.
$('#winners').append([
'Winner: ',
$('<a>')
.attr('href', 'scoreTracker.php?id=' + encodeURIComponent(message.userId))
.text(
message.userName + ' score: ' + message.score + ' Start time: ' + message.startTime + ' End time: ' + message.endTime
)
]);
If your HTML gets much more complicated, might I suggest a JavaScript template engine? I use Swig for most projects, but there are many choices.
you have to use append() , or html()
$('#winners').append('Winner:' + ' ' + message.userName + ' ' + ' '+ 'score:' + ' ' + message.score + ' ' + ' '+ 'Start time:' + ' ' + message.startTime + ' ' + ' '+ 'End time:' + '' + message.endTime );
this may help you to understand better :
http://api.jquery.com/category/manipulation/dom-insertion-inside/
Both #Brad and #ProllyGeek are correct -- but #Brad's solution is best given the potential risk of XSS attacks. Here is his code, just cleaned up a bit for better readability. :)
$('#winners').append([
'Winner: ',
$('<a />')
.attr('href', 'scoreTracker.php?id=' + encodeURIComponent(message.userId)
.text(message.userName + ' score: ' + message.score + ' Start time: ' + message.startTime + ' End time: ' + message.endTime)
]);
Hope this helps!

Speed Coordinate shows null value in GeoLocation PhoneGap

i am creating android application that gets Lat Lng and check the speed of user i am using PhoneGap GeoLocation Api but i am getting only Longitude and Latitude but in Altitude and Speed it shows null
here is the JavaScript that i get from PhoneGap website
<script type="text/javascript">
document.addEventListener("deviceready", onDeviceReady, false);
// PhoneGap is ready
//
function onDeviceReady() {
var options = { enableHighAccuracy: true };
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
// onSuccess Geolocation
//
function onSuccess(position) {
var element = document.getElementById('time');
element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' +
'Longitude: ' + position.coords.longitude + '<br />' +
'Altitude: ' + position.coords.altitude + '<br />' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '<br />' +
'Speed: ' + position.coords.speed + '<br />' +
'Timestamp: ' + new Date(position.timestamp) + '<br />';
setTimeout('loop();',100);
}
// onError Callback receives a PositionError object
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
function loop(){
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
</script>
I am check this in Android Mobile as well as emulator same result both places that is null
The Html part is
<body>
<p id="time">Finding geolocation...</p>
Source
it might be device specific, as to whether or not those parameters are supported "If the implementation cannot provide {those variables you're having trouble with} information, the value of this attribute must be null."

Categories