I have created an ionic angularjs ngCordova mobile app, wherein I have used ngCorodova geolocation plugin in order to get user location. when I am testing this on browser it works fine. but when same I [android-app.apk] I install on mobile app [obviously after checking "unknown sources" option]; I am not able to get the location. I see in app setting, permission is there to access location on mobile. Also, When event is trigerred it shows GPS symbol on top bar but it disappears.
Can anybody help me with this?
Below is the code for location in my controller.js
.directive('reverseGeocode', function ($cordovaGeolocation, $rootScope) {
return {
restrict: 'E',
template: '<div></div>',
link: function (scope, element, attrs) {
var geocoder = new google.maps.Geocoder();
var posOptions = {timeout: 10000, enableHighAccuracy: true};
$cordovaGeolocation
.getCurrentPosition(posOptions)
.then(function (position) {
var lati = position.coords.latitude;
var longi = position.coords.longitude;
// console.log(angular.toJson($rootScope.lati) + " - " );
var request = new XMLHttpRequest();
var method = 'GET';
//var url = 'http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+long+'&sensor=true';
var async = true;
//alert(url);
//request.open(method, url, async);
//alert(angular.toJson(request.open(method, url, async)));
// var data = JSON.stringify(request.responseText);
// alert(JSON.stringify(request.responseText));
var latlng = new google.maps.LatLng(lati, longi);
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
//alert(results[1].address_components[1].long_name);
$rootScope.colony = results[1].address_components[1].long_name;
//alert(results[1].address_components[1].long_name);
//alert(results[1].address_components[1].long_name);
//alert(angular.toJson(results[1].address_components[1].long_name));
element.text(results[1].formatted_address);
} else {
element.text('Location not found');
}
} else {
element.text('Geocoder failed due to: ' + status);
}
});
}, function(err) {
// error
});
var watchOptions = {
frequency : 1000,
timeout : 3000,
enableHighAccuracy: false // may cause errors if true
};
var watch = $cordovaGeolocation.watchPosition(watchOptions);
watch.then(
null,
function(err) {
// error
},
function(position) {
var lat = position.coords.latitude
alert("abc >>" + lat);
var long = position.coords.longitude
});
watch.clearWatch();
// OR
$cordovaGeolocation.clearWatch(watch)
.then(function(result) {
// success
}, function (error) {
// error
});
},
replace: true
}
})
In html file I am using it as :
<h6>
User Colony: {{ colony }}
<reverse-geocode lat={{lati}} lng={{longi}}></reverse-geocode>
</h6>
<a href="#" ng-click="showStores(colony)" class="button button-block button-positive">
Browse Store
</a>
which triggeres the directive and find lat and long of user.
When testing on browser, it works perfectly but not on mobile itself.
In android it is super complicated to work with the GPS user, remember that often the geolocation we get is from the browser and not the GPS itself, and this varies a lot in the devices. For your help, I recommend installing cordova.plugins.diagnostic
function onDeviceReady() {
cordova.plugins.diagnostic.isLocationAuthorized(function(enabled){
//alert("gps es : " + (enabled ? "enabled" : "disabled"));
}, function(error){
//alert("error: "+error);
});
cordova.plugins.diagnostic.isLocationEnabled(function(enabled){
if(!enabled){
alert("gps not actived");
}else{
navigator.geolocation.getCurrentPosition(onSuccess, onError, {enableHighAccuracy: true,timeout: 5000,maximumAge: 5000});
}
}, function(error){
console.log("The following error occurred: "+error);
});
}
Always trying to see if I can get a latitude and longitude and if that is not activated or not you can get, it sends a message to the user. I hope it helps you.
Related
I am creating a log file, and then saving the coordinates when app run in background through backgroundGeolocation. The problem is when app runs in background mode then it's not saving the coords in log file, actually I am doing this for testing purposes that does this plugin working fine or not.
document.addEventListener("deviceready",onDeviceReady,false);
// PhoneGap is ready to be used!
//
function onDeviceReady() {
window.logToFile.setLogfilePath('/myapp/log.txt', function () {
backgroundGeolocation.configure(callbackFn, failureFn, {
desiredAccuracy: 10,
stationaryRadius: 20,
distanceFilter: 30,
interval: 60000
});
backgroundGeolocation.start();
}, function (err) {
// logfile could not be written
// handle error
});
var callbackFn = function(location) {
window.logToFile.debug('[js] BackgroundGeolocation callback: ' + location.latitude + ',' + location.longitude);
backgroundGeolocation.finish();
};
var failureFn = function(error) {
console.log('BackgroundGeolocation error');
};
}
I'm trying to get current geolocation in Ionic 2 to work on Android devices. In the browser it works well, but when I run the ionic cordova run android command to deploy on device the geolocation doesn't execute at all, and I get the following errors:
Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode. main.js:48746
Native: deviceready did not fire within 2000ms. This can happen when plugins are in an inconsistent state. Try removing plugins from plugins/ and reinstalling them. cordova.js:1223 (anonymous) # main.js:48746
deviceready has not fired after 5 seconds. main.js:48741
DEVICE READY FIRED AFTER 3656 ms main.js:119892
Ionic Native: deviceready event fired after 3519 ms main.js:122839
Ionic Storage driver: asyncStorage main.js:50230
navigator.geolocation works well main.js:8291
PlacesPage ionViewDidLoad error: this.getGeolocation is not a function
Mainly, what I don't understand is that I get the this.getGeolocation is not a function because how did that change from browser to device?
import { Geolocation } from '#ionic-native/geolocation';
...
constructor(private geolocation: Geolocation) {}
...
ionViewDidLoad() {
if(this.platform.is('cordova') === true){
document.addEventListener("deviceready", onDeviceReady, false);
}else{
console.log('Browser geolocation')
this.getGeolocation();
}
function onDeviceReady() {
console.log("navigator.geolocation works well");
this.getGeolocation();
}
}
getGeolocation(){
console.log('Starting Geolocation');
var options = {
enableHighAccuracy: true
};
this.geolocation.getCurrentPosition(options)
.then((position) => {
console.log('Geolocation successful');
this.currentLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
let query = '?lat=' + position.coords.latitude + '&lng=' + position.coords.longitude;
this.updatePlaces(query);
}).catch((error) => {
console.log('Error getting location', error);
});
}
I have tried removing all plugins and reinstalling them. I have added a Content-Security-Policy to index.html.
Can anybody tell me what's wrong or guide me in a right direction? Thanks.
your code doesn't seems correct to me. Change your code to below:
import { Geolocation } from '#ionic-native/geolocation';
...
constructor(private geolocation: Geolocation) {}
...
ionViewDidLoad() {
if(this.platform.is('cordova') === true){
document.addEventListener("deviceready", onDeviceReady, false);
}else{
console.log('Browser geolocation')
this.getGeolocation();
}
}
function onDeviceReady() {
console.log("navigator.geolocation works well");
this.getGeolocation();
}
getGeolocation(){
console.log('Starting Geolocation');
var options = {
enableHighAccuracy: true
};
this.geolocation.getCurrentPosition(options)
.then((position) => {
console.log('Geolocation successful');
this.currentLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
let query = '?lat=' + position.coords.latitude + '&lng=' + position.coords.longitude;
this.updatePlaces(query);
}).catch((error) => {
console.log('Error getting location', error);
});
}
I seem to have solved the issue. The problem was that I have been mixing the implementation of Cordova's geolocation and the implementation for Ionic. In Ionic it's not needed to add the event listener (I guess it handles that under the hood) as seen in the docs, so the proper implementation should be like this:
import { Geolocation } from '#ionic-native/geolocation';
...
constructor(private geolocation: Geolocation) {}
...
ionViewDidLoad() {
this.getGeolocation();
}
getGeolocation(){
console.log('Starting Geolocation');
var options = {
enableHighAccuracy: true
};
this.geolocation.getCurrentPosition(options)
.then((position) => {
console.log('Geolocation successful');
this.currentLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
let query = '?lat=' + position.coords.latitude + '&lng=' + position.coords.longitude;
this.updatePlaces(query);
}).catch((error) => {
console.log('Error getting location', error);
});
}
I already had this code before I implemented the event listener, but at that time the plugins were failing, so it was an attempt to fix that, which got to implement the event listener. Thanks to #Prerak Tiwari for making me think in the right direction.
I want to check the location and store the required data in the internal storage of the mobile. To stop this task, use has to tap stop button in the main ui. As this task started, no matter the state of the app, that task should do its work.
I can implement this using native android command. But I want to implement this using cordova and I can't figure out a way to do this..
If this task cannot be done using cordova, can I do it using native android and inject to the cordova app..??
Please help..
You can do this using the ng-cordova geolocation watcher, it watches geolocation properties such as lat, lon, and speed.
first intall ng-cordova and inject it
bower install ngCordova
angular.module('myApp', ['ngCordova'])
then install the geolocation plugin
cordova plugin add org.apache.cordova.geolocation
then you want to create a watcher, make sure to fire it after a device ready event or it will cause problems
This is what device ready function looks like
document.addEventListener("deviceready", function () {
$cordovaPlugin.someFunction().then(success, error);
}, false);
here is the watcher controller:
module.controller('GeoCtrl', function($cordovaGeolocation) {
var watchOptions = {
frequency : 1000,
timeout : 3000,
enableHighAccuracy: false // may cause errors if true
};
var watch = $cordovaGeolocation.watchPosition(watchOptions);
watch.then(
null,
function(err) {
// error
},
function(position) {
var lat = position.coords.latitude
var long = position.coords.longitude
});
watch.clearWatch();
// OR
$cordovaGeolocation.clearWatch(watch)
.then(function(result) {
// success
}, function (error) {
// error
});
});
As you watch their geolocation info you can push it into a local database like http://pouchdb.com/ or couch db or a server database. If you want to use this in any state of the app you can make it into a service,
here is an example in a app i built
service.watchSpeed = function () {
console.log('watcher');
ionic.Platform.ready(function () {
var watchOptions = {
frequency: 15 * 60 * 1000,
timeout: 1 * 60 * 1000,
enableHighAccuracy: true // may cause errors if true
};
service.watch = $cordovaGeolocation.watchPosition(watchOptions);
service.watch.then(
null,
function (err) {
service.watchSpeed();
},
function (position) {
if (service.maxspeed.ToUseApp !== 0) {
var lat = position.coords.latitude;
var long = position.coords.longitude;
var speed = position.coords.speed;
service.speed = speed;
if (speed > service.maxspeed.ToUseApp) {
$state.go('overspeed');
}
if ($ionicHistory.currentStateName() === 'overspeed' && speed < service.maxspeed.ToUseApp) {
$ionicHistory.goBack();
}
} else {
console.log('speed watcher has been killed, why master??');
}
});
});
};
then in my home controller i call the watcher
ionic.Platform.ready(function () {
ffService.getMaxSpeed();
});
In a simple Ionic app I have to get current location on map. It's works fine in browser when i click find me, but it's not working on actual Android device.
I'm using the following code
View.html
<ion-view view-title="{{navTitle}}">
<ion-content>
<div id="map" data-tap-disabled="true"></div>
</ion-content>
<ion-footer-bar class="bar-stable">
<a ng-click="centerOnMe()" class="button button-icon icon ion-navigate">Find Me</a>
</ion-footer-bar>
</ion-view>
controllers.js
.controller('googlemap', function($scope, $ionicLoading, $compile) {
$scope.navTitle = 'Google Map';
$scope.$on('$ionicView.afterEnter', function(){
if ( angular.isDefined( $scope.map ) ) {
google.maps.event.trigger($scope.map, 'resize');
}
});
function initialize() {
//var myLatlng = new google.maps.LatLng(43.07493,-89.381388);
var myLatlng = new google.maps.LatLng(18.520430300000000000,73.856743699999920000);
var mapOptions = {
center: myLatlng,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"),
mapOptions);
//Marker + infowindow + angularjs compiled ng-click
var contentString = "<div><a ng-click='clickTest()'>Click me!</a></div>";
var compiled = $compile(contentString)($scope);
var infowindow = new google.maps.InfoWindow({
content: compiled[0]
});
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Pune(India)'
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
$scope.map = map;
}
initialize();
$scope.centerOnMe = function() {
if(!$scope.map) {
return;
}
$scope.loading = $ionicLoading.show({
content: 'Getting current location...',
showBackdrop: false
});
navigator.geolocation.getCurrentPosition(function(pos) {
$scope.map.setCenter(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
$scope.loading.hide();
}, function(error) {
alert('Unable to get location: ' + error.message);
});
};
$scope.clickTest = function() {
alert('Example of infowindow with ng-click')
};
})
Also in my device on the device Location but still I have problem.I got following output on my screen for long time.
Isn't it easier to just use the ngCordova $cordovaGeoLocationPlugin ? You can get the position from this plugin ( latitude and longitude) and then pass this in GoogleAPI. I think it will be lot easier that way.
ngCordova geoLocationPlugin
Just a suggestion.
This example works perfect in case you start the app with GPS on. But starting with GPS off in you device, and after that, entering in the app and selecting GPS on, the function returns always GPS timeout ERROR = 3. Any solution for that?
I have posted this error here:
When I start the App with GPS off , and later GPS is activated, Location is not detected
I followed this tutorial http://www.mobiledevelopersolutions.com/home/start/twominutetutorials/tmt4part1 and i have one problem. The geolocation doesn't work on the default Android browser. It does work on Chrome, IE and Chrome for Android. But not the default Android browser.
I think i have to put { enableHighAccuracy: true } somewhere put i can't get it figured out.
This is the code:
var mapdata = { destination: new google.maps.LatLng(51.3704888, 6.1723862) };
// Home page
$('#page-home').live("pageinit", function() {
$('#map_square').gmap(
{ 'center' : mapdata.destination,
'zoom' : 12,
'mapTypeControl' : false,
'navigationControl' : false,
'streetViewControl' : false
})
.bind('init', function(evt, map) {
$('#map_square').gmap('addMarker',
{ 'position': map.getCenter(),
'animation' : google.maps.Animation.DROP
});
});
$('#map_square').click( function() {
$.mobile.changePage($('#page-map'), {});
});
});
function fadingMsg (locMsg) {
$("<div class='ui-overlay-shadow ui-body-e ui-corner-all fading-msg'>" + locMsg + "</div>")
.css({ "display": "block", "opacity": 0.9, "top": $(window).scrollTop() + 100 })
.appendTo( $.mobile.pageContainer )
.delay( 2200 )
.fadeOut( 1000, function(){
$(this).remove();
});
}
//Create the map then make 'displayDirections' request
$('#page-map').live("pageinit", function() {
$('#map_canvas').gmap({'center' : mapdata.destination,
'mapTypeControl' : true,
'navigationControl' : true,
'navigationControlOptions' : {'position':google.maps.ControlPosition.LEFT_TOP}
})
.bind('init', function() {
$('.refresh').trigger('tap');
});
});
$('#page-map').live("pageshow", function() {
$('#map_canvas').gmap('refresh');
});
// Request display of directions, requires jquery.ui.map.services.js
var toggleval = true; // used for test case: static locations
$('.refresh').live("tap", function() {
// START: Tracking location with device geolocation
if ( navigator.geolocation ) {
fadingMsg('Using device geolocation to get current position.');
navigator.geolocation.getCurrentPosition (
function(position ) {
$('#map_canvas').gmap('displayDirections',
{ 'origin' : new google.maps.LatLng(position.coords.latitude, position.coords.longitude),
'destination' : mapdata.destination, 'travelMode' : google.maps.DirectionsTravelMode.DRIVING},
{ 'panel' : document.getElementById('dir_panel')},
function (result, status) {
if (status === 'OK') {
var center = result.routes[0].bounds.getCenter();
$('#map_canvas').gmap('option', 'center', center);
$('#map_canvas').gmap('refresh')
} else {
alert('Unable to get route');
}
}
);
},
function(){
alert('Unable to get location');
$.mobile.changePage($('#page-home'), { });
});
} else {
alert('Unable to get location.');
}
// END: Tracking location with device geolocation
$(this).removeClass($.mobile.activeBtnClass);
return false;
});
// Go to map page to see instruction detail (zoom) on map page
$('#dir_panel').live("tap", function() {
$.mobile.changePage($('#page-map'), {});
});
// Briefly show hint on using instruction tap/zoom
$('#page-dir').live("pageshow", function() {
fadingMsg("Tap any instruction<br/>to see details on map");
});
Thx for the help!
This is how you may need to call.
navigator.geolocation.getCurrentPosition(successCallback,
errorCallback,
{maximumAge:Infinity, timeout:0, enableHighAccuracy: true });
Ofcourse here you can change maximumAge and timeout values, but this is where you set enableHighAccuracy.
So just specify this as third param in your getcurrentposition method.
EDIT :
navigator.geolocation.getCurrentPosition (
function(position ) {
$('#map_canvas').gmap('displayDirections',
{ 'origin' : new google.maps.LatLng(position.coords.latitude, position.coords.longitude),
'destination' : mapdata.destination, 'travelMode' : google.maps.DirectionsTravelMode.DRIVING},
{ 'panel' : document.getElementById('dir_panel')},
function (result, status) {
if (status === 'OK') {
var center = result.routes[0].bounds.getCenter();
$('#map_canvas').gmap('option', 'center', center);
$('#map_canvas').gmap('refresh')
} else {
alert('Unable to get route');
}
}
);
},
function(){
alert('Unable to get location');
$.mobile.changePage($('#page-home'), { });
},
{ enableHighAccuracy: true } );
Since you want to use geolocation, have you set the sensor to true? Because if you set it false, it won't work.
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true"></script>