Titanium geolocation tracking not work correctly - android

I'm building an app that needs to track location of user and I use
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;
Ti.Geolocation.distanceFilter = 0;
Ti.Geolocation.preferredProvider = Ti.Geolocation.PROVIDER_GPS
Ti.Geolocation.addEventListener('location', locationChange);
On iOS when device is in the move the event is not fired regularly and when it's fired I dont have heading and speed ( even tested it on while driving )
...
heading : -1,
speed : -1
...
but if I run another navigation app on background (like Plans) the event is fired constantly and I have heading and speed of device, as if i'm only getting the events because the other apps.
its the same problem on android the event is not fired correctly
testing with ti SDK 5.1.2 and 5.5.1

This has tripped me up in the past. Add
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST_FOR_NAVIGATION;
Also note that very small numbers in the distance filter may cause some problems.
I use this
if (OS_IOS) {
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST_FOR_NAVIGATION;
Ti.Geolocation.distanceFilter = Alloy.CFG.minUpdateDistance;
Ti.Geolocation.preferredProvider = Ti.Geolocation.PROVIDER_GPS;
Ti.Geolocation.pauseLocationUpdateAutomatically = true;
Ti.Geolocation.activityType = Ti.Geolocation.ACTIVITYTYPE_OTHER_NAVIGATION;
} else { //Android
Ti.Geolocation.Android.manualMode = true;
var gpsProvider = Ti.Geolocation.Android.createLocationProvider({
name: Ti.Geolocation.PROVIDER_GPS,
minUpdateTime: Alloy.CFG.minAge / 1000,
minUpdateDistance: Alloy.CFG.minUpdateDistance
});
var gpsRule = Ti.Geolocation.Android.createLocationRule({
provider: Ti.Geolocation.PROVIDER_GPS,
accuracy: Alloy.CFG.accuracy,
maxAge: Alloy.CFG.maxAge,
minAge: Alloy.CFG.minAge,
});
Ti.Geolocation.Android.addLocationProvider(gpsProvider);
Ti.Geolocation.Android.addLocationRule(gpsRule);
Ti.Geolocation.Android.manualMode = true;
}
The Alloy.CFG settings are set in the config.json file.
{
"global": {
"minUpdateDistance": 10,
"os:android": {
"accuracy": 20,
"minAge": 10000,
"maxAge": 30000
},...

Related

Ionic 2 / Ionic 3 : How to get current location of a device

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.

Android geolocation with cordova not trigger callback error

I have an app working with Cordova, and I have installed this plugin from the official repository:
Plugin installation: cordova plugin add cordova-plugin-geolocation
Repository: https://github.com/apache/cordova-plugin-geolocation
Device ready event:
onDeviceReady: function() {
app.receivedEvent('deviceready');
console.log('deviceready');
loadPosition();
}
In the deviceready event I call to this function:
Load Position Function:
function loadPosition() {
// onSuccess Callback
// This method accepts a Position object, which contains the
// current GPS coordinates
//
var onSuccess = function (position) {
localStorage.setItem("latitude", position.coords.latitude);
localStorage.setItem("longitude", position.coords.longitude);
localStorage.setItem("position", true);
};
// onError Callback receives a PositionError object
//
function onError(error) {
localStorage.setItem("position", false);
alertErrorPosition();
}
function alertErrorPosition() {
navigator.notification.alert(
'Necesitamos utilizar tu ubicación para poder hacer funcionar la aplicación. Reinicia la aplicación o vuélve a instalarla . Gracias.', // message
null, // callback
'¡Error!', // title
'Ok' // buttonName
);
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
}
The problem:
On Android, I don't see the alert error if the App can't obtain the localization (for example, the GPS is not actived), but on iOS, if the user deny the access, I can see the error alert.
If the user has the GPS activated, I don't have any problem and the App obtain correctly the latitude and longitude.
I have tested it in the emulator and in a real device. I'm using Android Studio for testing.
Thanks!!
The effect of turning off GPS on an Android device (e.g. changing setting Location Mode to "Battery Saving") varies depending on the Android version: either the OS is never able to retreive a high-accuracy position, so the TIMEOUT error occurs (PERMISSION_DENIED will not be received on Android) or a low accuracy position will be retrieved and passed instead using Wifi/cell triangulation.
I'd suggest using watchPosition() instead of getCurrentPosition() to retrieve the location; getCurrentPosition() makes a single request for the device position at that current point in time, so the position timeout may occur before the GPS hardware on the device has had a chance to get a position fix, whereas using watchPosition() you can setup a watcher which will call the success function each time the OS receives a location update from the GPS hardware. If you only want a single location, clear the watcher after receiving a position of sufficient accuracy. If GPS is turned off on the Android device when the watcher is added, it will continue to return a TIMEOUT error; my workaround for this is to clear and re-add the watcher after a number of consecutive errors. And before adding the watcher for the first time, you can use this plugin to check if GPS is turned on and if not, offer to redirect the user to the Android Location Settings page so they can turn it on.
So something along these lines:
var MAX_POSITION_ERRORS_BEFORE_RESET = 3,
MIN_ACCURACY_IN_METRES = 20,
positionWatchId = null,
watchpositionErrorCount = 0,
options = {
maximumAge: 60000,
timeout: 15000,
enableHighAccuracy: true
};
function addWatch(){
positionWatchId = navigator.geolocation.watchPosition(onWatchPositionSuccess, onWatchPositionError, options);
}
function clearWatch(){
navigator.geolocation.clearWatch(positionWatchId);
}
function onWatchPositionSuccess(position) {
watchpositionErrorCount = 0;
// Reject if accuracy is not sufficient
if(position.coords.accuracy > MIN_ACCURACY_IN_METRES){
return;
}
// If only single position is required, clear watcher
clearWatch();
// Do something with position
var lat = position.coords.latitude,
lon = position.coords.longitude;
}
function onWatchPositionError(err) {
watchpositionErrorCount++;
if (err.code == 3 // TIMEOUT
&& watchpositionErrorCount >= MAX_POSITION_ERRORS_BEFORE_RESET) {
clearWatch();
addWatch();
watchpositionErrorCount = 0;
}
}
function checkIfLocationIsOn(){
cordova.plugins.diagnostic.isLocationEnabled(function(enabled){
console.log("Location is " + (enabled ? "enabled" : "disabled"));
if(!enabled){
navigator.notification.confirm("Your GPS is switched OFF - would you like to open the Settings page to turn it ON?",
function(result){
if(result == 1){ // Yes
cordova.plugins.diagnostic.switchToLocationSettings();
}
}, "Open Location Settings?");
}else{
if(positionWatchId){
clearWatch();
}
addWatch();
}
}, function(error){
console.error("The following error occurred: "+error);
}
);
}
document.addEventListener("deviceready", checkIfLocationIsOn, false); // Check on app startup
document.addEventListener("resume", checkIfLocationIsOn, false); // Check on resume app from background

Unable to call geolocationerror when gps is disabled

When gps is enabled geolocationsuccess work perfectly. But when gps diabled it not calling geolocationerror in mobile device.Working on ionic framework using phonegap geolocation for checking is gps enable or not. codes are here
var locOptions = {
maximumAge : 10000,
timeout : 5000,
enableHighAccuracy : true
};
function onLocationSuccess(position) {
console.log(position);
// alert('success');
$rootScope.pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': $rootScope.pos}, function address(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
$rootScope.currentposition = results[1].formatted_address;
console.log($rootScope.currentposition);
if($scope.switchToState=='signedIn'){
$ionicLoading.hide();
$http.get($rootScope.url +'api/price/?key=movo1026868hk738hkl')
.success(function(response) {
$rootScope.truckfare=response.datasets;
});
console.log('reached here2');
$state.go('app.home');
}
else{
$ionicLoading.hide();
$state.go('start');
}
}
}
});
}
// onError Callback receives a PositionError object
//
function onLocationError(error) {
alert("Geolocation error: #" + e.code + "\n" + e.message);
}
navigator.geolocation.getCurrentPosition(onLocationSuccess, onLocationError, locOptions);
Geolocation API will not give you an error if the GPS is off because that is not an error state. It will just timeout if it is not able to get a lock in the time limit you specify.
Unfortunately, this is a real problem. If you turn off GPS and Geolocation API times out, you will not be able to make it work again unless you restart a whole application. So even if you turn GPS back online API will not work again unless an application is restarted.
There's a simple workaround here. Before you initialize Geolocation API check if GPS is online. You can do that using this PhoneGap/Cordova plugin:
https://github.com/mablack/cordova-diagnostic-plugin
Essentially, this plugin will solve your initial problem + problem I mentioned you before.

Tap/Touch events not working on Samsung Android 4.4.4 and 5

I developed an app with Cordova that worked fine until Android 5.0. The issue with the app is that I can swipe however I cannot tap/touch specific elements within my app (actually it works if I tap multiple times). Some taps work like expected such as buttons. However other elements like images etc. it doesn't work (I have images in a carousel that when tapped executes a function)
Can anyone help as to why this is happening and only happening on Android 4.4.4 and up.
My code is below
nova.touch.bindClick = function(selector, func) {
if (nova.application.isTouchable === false) {
$(selector).click(function(e) {
func.call(this, e);
});
return;
}
var isMoving = false;
var startTime = null;
$(selector).bind(this.eventNames.touchstart, function(e) {
isMoving = false;
startTime = new Date();
$(this).addClass("touching");
});
$(selector).bind(this.eventNames.touchmove, function(e) {
isMoving = true;
});
$(selector).bind(this.eventNames.touchend, function(e) {
var $me = $(this);
$me.removeClass("touching");
var duration = new Date() - startTime;
if (!isMoving && duration < 1000) {
$me.addClass("clicking");
func.call(this, e);
setTimeout(function() {
$me.removeClass("clicking");
}, 500);
}
});
};
As stated above this works fine on older versions of Android and all versions of iOS. Only the new versions of Android have this problem.
I had this exact same problem this afternoon. I've found that the Samsung device on this android version is too quick in categorizing a "Touch Move" event with a regular touch/"click" event.
I've found that the following fix solves this problem.
Change:
$(selector).bind(this.eventNames.touchmove, function(e) {
isMoving = true;
});
To:
$(selector).bind(this.eventNames.touchmove, function (e) {
var duration = Date.now() - startTime;
if (!isMoving && duration > 1000) {
isMoving = true;
}
});
1000ms may be too much depending on your circumstances but you could change this accordingly.
Hope this helps!

Cordova application in background having strange behaviour on Android

I am working on a Cordova application which needs to send current location of user to server after every 10 seconds. For that, I am using Geolocation plugin. Here are my code snippets:
$rootScope.startListeningForLocation = function() {
$rootScope.locationListenerId = setInterval(function() {
navigator.geolocation.getCurrentPosition(
$rootScope.onSuccessForLocation,
$rootScope.onErrorForLocation_High,
{maximumAge:600000, timeout:7000, enableHighAccuracy: true}
);
}, 5000);
};
$rootScope.onSuccessForLocation = function(position) {
var lat = position.coords.latitude, lng=position.coords.longitude;
gLat = lat;
gLng = lng;
}
function startLocationRefreshLoop() {
if(locationReloadInterval) clearInterval(locationReloadInterval);
var locationReloadInterval = setInterval(function() {
$('#btn-location').trigger('click');
}, LOCATION_UPDATE_INTERVAL);
}
...
<div id='btn-location' ng-show="false" ng-click='updateLocationToServer()'></div>
...
$rootScope.updateLocationToServer = function() {
if(!isConnected()) {
dbService.logLocation();
} else {
var prom = Api.post(apiURL+'/employee/'+$rootScope.user.id+'/current_location', {location:{latitude: gLat, longitude: gLng}});
prom.then(function(data) {
console.log('updateLocation::> ' + JSON.stringify(data) + 'gLat:' + gLat + ', gLng' + gLng);
});
}
};
Everything works very fine when app is in foreground i.e. the app gets the location stored in gLat and gLng variables and send it to server every 10 seconds. But when goes to background and phone is in sleep mode, it is showing some strange behaviour. Strange in the sense that instead of calling updateLocationToServer() every 10 seconds, it gets called after every minute and sometimes it gets more worse. I don't know how 10 seconds are being interpreted as one minute in sleep mode. I want to know what are the possible reasons for such a delay? My application is mainly for taxi drivers and want to keep track of them all the time. The client's whole business depends on this thing and its like make it or break it thing. Your suggestions please.
Edit: And my client is using 3G and 4G network to test the app.

Categories

Resources