Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Objective

In this chapter, you'll learn how to use Titanium's Geolocation API to retrieve GPS positioning and heading information from mobile devices. In addition you'll learn best practices with respect to using the API.

Contents

The position and heading APIs are part of the Ti.Geolocation module, which contains all the functions, properties, and events necessary to handle location information. In the following sections, you'll learn how to use this API to perform the following activities:

  • Detect if location services are available
  • Obtain the current GPS position
  • Continually monitor the GPS position
  • Use the device's compass
  • Configure location service properties
  • Forward and reverse geocoding

You'll also learn best practices and caveats to consider when using location services in your apps. But first, let's dive into some platform specific considerations when using these services.

iOS Considerations

When using location services with iOS, there's one thing you must do in every Titanium app. iOS, as of version 4.0, requires that you specify a 'purpose' when attempting to access a device's location. To make things simple for developers, Titanium provides the Ti.Geolocation.purpose property. This property will be presented to end users in a permissions dialog when they elect to enable location services for your app.

Any valid string is an acceptable value for Ti.Geolocation.purpose. Here's one simple example of setting this property.

Android Considerations

Adding GPS Support to Android Emulator

The Android emulator, by default, may not be equipped to handle location services. In order to make sure you have location services enabled for your Titanium Android emulator, follow these steps:

  • Open the Android SDK and AVD Manager (found at ANDROID_SDK/tools/android)
  • Select your Titanium Android emulator and click the "Edit.." button
  • In the "Hardware" section, see if "GPS support" is listed
    ** If it is, make sure the "Value" field it set to "yes"
    • If not, click the "New..." button
      • From the "property" list, select "GPS support"
      • Click "OK"
      • Make sure the "Value" field for "GPS support" it set to "yes"
  • Click "Edit AVD" then click "OK" in the resulting dialog
  • Restart your Android emulator, if necessary

You have now enabled location services for your Android emulator. But there's still one more thing to consider when testing location services on the Android emulator. It doesn't generate GPS positions itself. You'l need to manually enter via the Dalvik Debug Monitor Service (DDMS).

Sending GPS info via DDMS

In order to send mock locations to the Android emulator, we need to assert that Android has appropriate permissions to do so. Titanium will take care of this automatically, but you can confirm that these permissions are present by going into your project's build/android directory and checking the AndroidManifest.xml file. Within the <manifest> section, you should see a line that looks like this:

With permissions in place, we can now use DDMS to send mock locations to the Android emulator. To do so, follow these steps:

  • Open DDMS (found at ANDROID_SDK/tools/ddms)
  • Select your emulator from the list of devices in the left pane and click the "Emulator Control" tab in the right pane
  • In the right pane, scroll down to the "Location Controls" section
  • Click the "Manual" tab if it is not already selected
  • While your location based app is running in the emulator, enter values for latitude and longitude and click "Send"

To get more information about providing mock locations to your Android emulator, be sure to check out the official Android documentation on the subject. It gives you details not only on manual mock locations, but also using the GPX and KML formats.

Detect if Location Services are Available

To determine whether or not location services will be available to you on the current mobile device, you simply need to check the boolean property Ti.Geolocation.locationServicesEnabled. With this in mind, the base skeleton of a locations based app might look something like this.

Obtain the Current GPS Position

Many apps only infrequently need to use location services. Whether it's at app startup, on a button click, or at a timed interval, developers have a multitude of opportunities to actively query for location information.

Let's take a look at a very basic example. After asserting that location services are enabled, the Ti.Geolocation.getCurrentPosition() function is used to query for location information. This function takes a single paramater; a callback function whose event object contains the requested location in its coords property. This is an asynchronous call as the GPS functionality may take a moment to work, especially if this is the first time your app is accessing location. Also worth noting is that the location services will return a cached location is your current position cannot be determined.

The output for a successful execution of the above app would look something like this:

Continually monitor the GPS position

Often you will want to know where a mobile device is at all times. The most common example of this is navigation for driving directions. To have the same constant awareness of a device's position in Titanium, you simply need to register the location event with the Ti.Geolocation module.

Here's a simple case showing how location data can be handled via event listener. You'll notice that the data is handled in a nearly identical manner to the Ti.Geolocation.getCurrentPosition() example.

As with the Ti.Geolocation.getCurrentPosition() example, the location data is returned in the event object's coords property. The listener callback will be executed every time your device detects a new location.

Icon

Continually monitoring the GPS for location will consume a mobile device's battery much faster than usual. Be sure that you actually need to be constantly handling the device's location before using this method. If you do, be sure to remove the location event listener via Ti.Geolocation.removeEventListener() when you are not actively using the location information.

Android Lifecycle Events

When monitoring location events continually in Android, apps will continue to receive events even when in the background. As mentioned above, this can be a major drain on the battery life of a mobile device. While this is sometimes the desired behavior, most apps only need location data while active.

In order to manage our location events such that we only receive them while our app is active, we need to take advantage of Titanium's access to the Android lifecycle events. There are 3 events that are significant, each of which can be handled via addEventListener() on the Ti.Android.currentActivity object:

  • destroy - This event is fired when your activity is destroyed. Location events should always be removed in this event.
  • pause - This event is fired when an activity moves to the background. If you intend to suspend your location data handling when your app is in the background, you need to remove location event listeners in this event.
  • resume - This event is fired when an activity comes to the foreground. If you previously removed location events in a pause event, this is where you would add them again to reenable them.

Below is a demonstration of how you would handle these events in order to only manage location events when your app is active. The key part to note is that pausing and resuming your location event handling is the responsibility of the Android Activity object accessible through the Titanium API as Ti.Android.currentActivity.

Use the Device's Compass

A mobile device's compass can be used to determine its heading. By using heading, the added dimension of direction can be added to a location based mobile app. With this addition, developers can add features like more robust navigation or even augmented reality.

Just as with location, Titanium has events and functions for both continual and one-time monitoring of heading. For continual monitoring, the heading event needs to be registered with the Ti.Geolocation module. In the case of needing only the current heading, a simple call to the Ti.Geolocation.getCurrentHeading() function is necessary. As you may have noticed, this is very similar to how location is handled.

The below includes both of the methods for determining heading mentioned above.

The console output of your program will contain the heading information, which will be sent continuously from the heading event. The data for each heading entry will be structured in the following manner.

Configure Location Service Properties

You may find when continually monitoring location services that you need additional control over their delivery. With the default configuration, the amount of data returned from location and heading events may be overwhelming. To help this situation, Titanium offers the following properties of the Ti.Geolocation module:

  • accuracy - The target accuracy of all location data received. The following Ti.Geolocation constants represent the valid values for this property:
    • ACCURACY_BEST - Location data will be of the highest possible accuracy of which the device is capable
    • ACCURACY_HUNDRED_METERS - Location data will be accurate within 100 meters
    • ACCURACY_KILOMETER - Location data will be accurate within 1 kilometer
    • ACCURACY_NEAREST_TEN_METERS - Location data will be accurate within 10 meters
    • ACCURACY_THREE_KILOMETERS_ - Location data will be accurate within 3 kilometers
  • distanceFilter - The minimum change of position (in meters) before a location event is fired. The default is 0, meaning that location events are continuously generated.
  • headingFilter - The minium change of heading (in degrees) before a heading event is fired. The default is 0, meaning that heading events are continuously generated.
  • preferredProvider - Allows you to specify the preferred method for receiving a location. The following Ti.Geolocation constants represent your possible choices:
    • PROVIDER_NETWORK - Give the network based location provider preference
    • PROVIDER_GPS - Give the GPS location preference

Using the event-driven location example at the beginning of this chapter, let's modify it to use some of the above properties.

Forward and Reverse Geocoding

Another feature of location services that is built into the Titanium API is geocoding. This is the process of converting an address into a geographic location (forward geocoding), or vice versa (reverse geocoding). For example, let's say we wanted to know the latitude and longitude of the Appcelerator headquarters in Mountain View, California. All we need to do is use the Ti.Geolocation.forwardGeocoder() function, giving it the address and a callback as parameters. Here's the code:

And here is the output of a forward geocoding of Appcelerator HQ. As you can see, it delivers the geographic location of the given address in latitude and longitude.

Now let's say we just have latitude and longitude and we want to figure out what places of interest are in the area. This case can occur if you accept these coordinates from user input, or if you want to get further information in your location events. To do so, we use the Ti.Geolocation.reverseGeocoder() function. To this function we pass a latitude, longitude, and callback function. Let's see what we get when we use the random coordinates (50,50), as in the below sample.

Here's the output:

While the above output shows only one place, you'll notice that the places property is an array. This means that on any given call to Ti.Gelocation.reverseGeocoder() you may receive a number of entries in the places property, if multiple places are found in the area of your query.

Summary

In this chapter we learned how we can leverage a mobile device's native location services to add the context of a physical location to our apps. Using Titanium's APIs we are able to proactively query or passively listen for a device's current GPS position and heading. By using the configuration properties found in the Ti.Geolocation module like accuracy and distanceFilter we can further refine a location based experience.

Finally, we learned how to use additional location based features like forward and reverse geocoding to get even more location details. In the next chapter, we'll learn how we can use the native mapping functionality of mobile devices via the Titanium.Maps module. We'll be able to take the techniques learned in this chapter and apply them to the next in order to create a visual representation of our location data.

  • No labels