controllergeolocationappcelerator

How to pass variables from a library to a controller in Appcelerator/Titanium?


I am trying to put the geolocation functionality (getting latitude and longitude) into a library and return latitude and longitude because coordinates are called throughout the app. I can call the geo library from controller.js, the lat and long are shown up in the console, but how can I use the coordinates in the calling function from controller.js?

in app/lib/geo.js

exports.getLongLat = function checkLocation(){
if (Ti.Geolocation.locationServicesEnabled) {
    Titanium.Geolocation.getCurrentPosition(function(e) {
        if (e.error) {
            Ti.API.error('Error: ' + e.error);
            } else {
                Ti.API.info(e.coords);
                var latitude = e.coords.latitude;
                var longitude = e.coords.longitude;
                console.log("lat: " + latitude + " long: " + longitude);
            }
        });
    } else {
        console.log('location not enabled');
}

};

controller.js

geolocation.getLongLat(); //this calls the library, but I don't know how I can get the coordinates "back" into the controller.js file for using it in the var args below.

var args ="?display_id=check_if_in_dp_mobile&args[0]=" + lat + "," + lon;

Solution

  • Creating a reusable library for this is a great idea, and you are on the right path. The challenge with getCurrentPosition is that it is asynchronous, so we have to get the data from it a little differently.

    Note in geo.js, the line Titanium.Geolocation.getCurrentPosition(function(e) {..., there is a function being passed to getCurrentPosition. This is a callback function that is executed one the phone has received the location data. This is because getCurrentPosition is asynchronous, meaning that the code in that callback function won't execute until a later point in time. I have some notes on async callbacks here.

    With your getLongLat function, the main thing we need to do is pass a callback to it that can in turn be passed to getCurrentPosition. Something like this:

    exports.getLongLat = function checkLocation(callback){
        if (Ti.Geolocation.locationServicesEnabled) {
            //we are passing the callback argument that was sent from getLongLat
            Titanium.Geolocation.getCurrentPosition(callback);
        } else {
            console.log('location not enabled');
        }
    };
    

    Then when you execute the function, you will pass the callback to it:

    //we moved our callback function here to the controller where we call getLongLat
    geolocation.getLongLat(function (e) {
        if (e.error) {
            Ti.API.error('Error: ' + e.error);
        } else {
            Ti.API.info(e.coords);
            var latitude = e.coords.latitude;
            var longitude = e.coords.longitude;
            console.log("lat: " + latitude + " long: " + longitude);
        }
    }); 
    

    In this case, we're basically moving the contents of that function originally being passed to getCurrentPosition out to where you are calling getLongLat in your controller. Now you will be able to do something with the coords data when the callback executes.

    Another place where callbacks occur in Titanium apps is with making network requests with Ti.Network.HttpClient. Here is a similar example of what you are trying to do by building a library for your geolocation queries only with making HTTPClient requests.