Professional Android Sensor Programming - Greg Milette - E-Book

Professional Android Sensor Programming E-Book

Greg Milette

4,7
32,99 €

oder
-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.
Mehr erfahren.
Beschreibung

Learn to build human-interactive Android apps, starting with device sensors This book shows Android developers how to exploit the rich set of device sensors--locational, physical (temperature, pressure, light, acceleration, etc.), cameras, microphones, and speech recognition--in order to build fully human-interactive Android applications. Whether providing hands-free directions or checking your blood pressure, Professional Android Sensor Programming shows how to turn possibility into reality. The authors provide techniques that bridge the gap between accessing sensors and putting them to meaningful use in real-world situations. They not only show you how to use the sensor related APIs effectively, they also describe how to use supporting Android OS components to build complete systems. Along the way, they provide solutions to problems that commonly occur when using Android's sensors, with tested, real-world examples. Ultimately, this invaluable resource provides in-depth, runnable code examples that you can then adapt for your own applications. * Shows experienced Android developers how to exploit the rich set of Android smartphone sensors to build human-interactive Android apps * Explores Android locational and physical sensors (including temperature, pressure, light, acceleration, etc.), as well as cameras, microphones, and speech recognition * Helps programmers use the Android sensor APIs, use Android OS components to build complete systems, and solve common problems * Includes detailed, functional code that you can adapt and use for your own applications * Shows you how to successfully implement real-world solutions using each class of sensors for determining location, interpreting physical sensors, handling images and audio, and recognizing and acting on speech Learn how to write programs for this fascinating aspect of mobile app development with Professional Android Sensor Programming.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 692

Bewertungen
4,7 (18 Bewertungen)
13
5
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Table of Contents

Part I: Location Services

Chapter 1: Introducing the Android Location Service

Methods Used to Determine Location

Summary

Chapter 2: Determining a Device's Current Location

Know Your Tools

Setting up the Android Manifest

Determining the Appropriate Location Provider

Receiving Location Updates

Implementing the Example App

Summary

Chapter 3: Tracking Device Movement

Collecting Location Data

Viewing the Tracking Data

Filtering Location Data

Continuous Location Tracking and Battery Life

Summary

Chapter 4: Proximity Alerts

App Structure

Proximity Alert Limitations

More Efficient Proximity Alert

Summary

Part II: Inferring Information from Physical Sensors

Chapter 5: Overview of Physical Sensors

Definitions

Android Sensor API

Sensing the Environment

Sensing Device Orientation and Movement

Summary

Chapter 6: Errors and Sensor Signal Processing

Definitions

Filters

A Better Determination of Orientation by Using Sensor Fusion

Summary

Chapter 7: Determining Device Orientation

Previewing the Example App

Determining Device Orientation

NorthFinder

Summary

Chapter 8: Detecting Movement

Acceleration Data

Implementation

Summary

Chapter 9: Sensing the Environment

Barometer vs. GPS for Altitude Data

Example App Overview.

Summary

Chapter 10: Android Open Accessory

A Short History of AOA

The Android Development Kit (ADK)

AOA Sensors versus Native Device Sensors

AOA Beyond Sensors

AOA Limitations

AOA and Sensing Temperature

Taking an Android Accessory to the Consumer Market

Summary

Part III: Sensing the Augmented, Pattern-Rich External World

Chapter 11: Near Field Communication (NFC)

What Is RFID?

What Is NFC?

Building an Inventory Tracking System

Android APIs

Future Considerations

Go Forth and NFC!

Summary

Chapter 12: Using the Camera

Using the Camera Activity

Creating a Simple Barcode Reader

Summary

Chapter 13: Image-Processing Techniques

The Structure of Image-Processing Programs

Detecting Faces

Image-Processing Resources

Summary

Chapter 14: Using the Microphone

Introducing the Android Clapper

Using MediaRecorder to Analyze Maximum Amplitude

Implementing a Clapper

Analyzing Raw Audio

Using Loud Noise Detection

Using Consistent Frequency Detection

Summary

Part IV: Speaking to Android

Chapter 15: Designing a Speech-enabled App

Know Your Tools

User Interface Screen Flow

Voice Action Types

Voice User Interface (VUI) Design

Testing Your Design

Summary

Chapter 16: Using Speech Recognition and Text-To-Speech APIs

Text-To-Speech

Speech Recognition

Summary

Chapter 17: Matching What Was Said

Parts of a Voice Command

Word Spotting

Matching Command Words in Persistent Storage

Multi-part Commands

Using a Grammar

Summary

Chapter 18: Executing Voice Actions

Food Dialogue VUI Design

Defining and Executing Voice Actions

Executing VoiceActionCommands

Implementing an AlertDialog for Voice Actions

Implementing Multi-Turn Voice Actions

Making a Best Guess

Responding When Recognition Fails

Summary

Chapter 19: Implementing Speech Activation

Implementing Speech Activation

Implementing Persistent Speech Activation

Summary

Introduction

Advertisement

Part I

Location Services

Chapter 1:

Introducing the Android Location Service

Chapter 2:

Determining a Device's Current Location

Chapter 3:

Tracking Device Movement

Chapter 4:

Proximity Alerts

Chapter 1

Introducing the Android Location Service

What's in this chapter?

Providing overview of how location information is provided in Android

Presenting an overview of GPS

Discussing why A-GPS is used in Android

Providing an overview of the network location provider

Location information is becoming increasingly important in the world of mobile development. Apps that were once location agnostic now make use of location information to provide a richer user experience. Being able to combine a simple web search engine with up-to-the-minute location information allows Android devices to provide a level of functionality that was previously not possible. The capability to easily retrieve and provide location data to apps is becoming a major feature of today's mobile platforms. Android provides this functionality with its location service.

Android's location service provides access to facilities that can be used to determine a device's current location. This information can be used for a wide variety of functions and can allow a device and the software that runs on it to have a better understanding of its surroundings.

Methods Used to Determine Location

Android makes use of different methods to provide location information to an app. In Android, these facilities are called location providers, and each has its own unique set of strengths and weaknesses. In addition, because location providers have such unique characteristics, they each lend themselves to be used differently in different situations.

The following sections give some high-level explanations as to how the different location acquisition methods work. Although an app has little control over how the providers work, it can decide which location provider to use. Understanding how each provider works goes a long way in understanding its limitations and characteristics.

GPS Provider

The Global Positioning System (GPS) uses a system of satellites orbiting the planet to help a receiver (an Android handset in this case) determine its current location. The term GPS refers to the entire GPS system, which consists of satellites, receivers, and the control stations that monitor and adjust it. The receiver that is located in the phone is useless without the rest of the system.

How It Works

In general, a GPS receiver uses information from the GPS satellites orbiting the earth to calculate its current location. The GPS system contains 27 satellites that continually orbit the earth, transmitting information to would-be receivers. Each satellite follows a defined path, ensuring that at least four satellites are “visible” from any point on earth at any given time. Being able to have a “line of sight” to at least four satellites is necessary to determine location using GPS. Figure 1.1 shows a depiction of the GPS satellite constellation.

Figure 1.1 GPS satellite constellation

Each GPS satellite in the constellation continuously transmits its current position (ephemeris data) and almanac data. The almanac data includes data about each satellite in the constellation, including orbiting data as well as information about the overall state of the system as a whole. To say it another way, ephemeris data is information about a single satellite, and almanac data is information about every satellite. Every satellite transmits both. Though both the ephemeris data and almanac data provide location data for a given satellite, the ephemeris data provides accuracy for location calculation.

To calculate its location, a GPS receiver must be able to determine its distance from multiple satellites. It does this using the ephemeris data. Included in the data that is transmitted from the satellite, along with the position data, is the time at which the transmission started. Each GPS satellite contains a highly accurate timekeeping mechanism that allows the satellite to keep its time in sync with the rest of the satellites. To produce an accurate location calculation, the GPS satellites and GPS receivers must have their clocks highly synchronized. Even the slightest difference in time can cause large errors when computing location.

Using the transmission start time, the GPS receiver can calculate the time it took for the transmission to be received (the receiver knows when the transmission ended). This calculation is made with the assumption that the radio waves that transmit the data travel at the speed of light in a vacuum (which is not always the case). Using the start time, end time, and a constant for the speed of light, a GPS receiver can calculate the distance of the satellite from the receiver.

Using the distance from multiple satellites, the GPS receiver can triangulate its current location. Essentially, the point at which all the spheres intersect is the location of the receiver. A minimum of three satellites is needed to determine a two-dimensional location (latitude and longitude). Communications from additional satellites allow a GPS receiver to determine additional positional information such as altitude. A GPS receiver will not limit itself to only four satellites. In general as the number of satellites from which the receiver can receive data increases, so does the accuracy of the location (there is an upper limit, however).

GPS is useful for determining current location, but it does have some drawbacks (especially for mobile platforms), one of which is the time it can take to calculate the current position. Before the location can be calculated, multiple satellites must be found. Many satellites are orbiting the earth, but only a handful can be “seen” at any given time because most will be below the horizon and blocked by the earth (remember, a line of sight is needed). The almanac used by the GPS system can provide assistance in determining which satellites should be used for a given location at a given time. However, if the GPS does not have a relatively current almanac, it will need to have the almanac data transmitted by a GPS satellite. This can be a slow process.

GPS Improvements

Although standard GPS can provide accurate location data, the limitations it imposes make it difficult for mobile devices to use it. To help circumvent some the limitations of standard GPS, modern mobile devices make use of assisted GPS (A-GPS) and possibly simultaneous GPS (S-GPS).

A-GPS

A-GPS uses the mobile network to transmit the GPS almanac along with other pieces of information to a mobile device. This use of the mobile network allows for faster transmission of the almanac, which may lead to faster determination of the device's current location. In addition, because the almanac contains information about all of the GPS satellites, the device will know the approximate location of the GPS satellites in its line of sight. This will also improve the time it takes to acquire a GPS location.

Examination of the GPS configuration file provides some insight into where the A-GPS data comes from. Listing 1.1 shows an example of a GPS configuration file that is used in Android for a device located in North America.

Listing 1.1: An example of a GPS configuration file located in /system/etc/gps.conf

NTP_SERVER=north-america.pool.ntp.org XTRA_SERVER_1=http://xtra1.gpsonextra.net/xtra.bin XTRA_SERVER_2=http://xtra2.gpsonextra.net/xtra.bin XTRA_SERVER_3=http://xtra3.gpsonextra.net/xtra.bin

Listing 1.1 shows that the GPS configuration file can specify the location of the A-GPS data to download (XTRA_SERVER_1, XTRA_SERVER_2, and XTRA_SERVER_3) as well as a Network Time Protocol (NTP) server that can be used to coordinate time (NTP_SERVER). NTP can be used to force coordination of time. This is important because GPS relies heavily on the clocks of a GPS receiver and the GPS satellites being in sync. Although the use of NTP does not guarantee true time synchronization down to the millisecond, it does help to prevent large time differences. Because of the numbers used in calculating times, like the speed of light, a small difference in time can lead to large inaccuracies in location calculations.

Though most users can read /system/etc/gps.conf, increased permissions are required to write to the file. Generally, users should not need to edit this file.

S-GPS

Devices that use standard GPS may use the same hardware to communicate with GPS satellites and make mobile phone calls. This means that only one of these actions can take place at a time. S-GPS addresses this issue by adding additional hardware that allows the GPS radio and the cellular network radio to be operational simultaneously. The ability to have two radios active can speed up GPS data transmission because it allows the data to be received while the cellular network radio is active.

Limitations

Although GPS can provide the most accurate location data, it does have limitations that may be difficult to work around. First is the fact that a GPS receiver needs a clear path to a GPS satellite. This means that GPS receivers are unlikely to work indoors, and may even have problems outside in areas where the sky is not visible (such as dense forests). Additionally, because multiple GPS satellites are needed to produce location information, it may take a substantial amount of time to acquire a location. This is exacerbated by that fact that devices may contain low-powered GPS radios. For these reasons, other sources of location information are sometimes needed.

Objects that obstruct a GPS signal may cause the signal to be reflected before it reaches the GPS receiver. As stated earlier, the time it takes a signal to reach the GPS receiver is used to calculate the distance between the GPS satellite and the GPS receiver. GPS signals that are reflected off of objects have a different path from the GPS satellite to the GPS receiver and cause the distance calculation to be erroneous. These types of errors are called multipatherrors and can cause the location to appear to jump from one place to another. This is often seen in urban areas where GPS signals frequently bounce off of tall buildings.

Controlling GPS

For most cases, GPS should “just work” as far as app developers are concerned. Typically, there will be no reason to interfere with the source of the A-GPS data, or when the A-GPS data should be purged and reinitialized.

However, Android does provide an API for controlling certain aspects of GPS data. The LocationManager class (which is introduced in detail in the next chapter) contains a sendExtraCommand() method that can be used to manipulate device GPS state. The LocationManager.sendExtraCommand() method takes three parameters: a string specifying the location provider, the extra command, and a Bundle that provides additional information for performing the command.

At the time of this writing, the GPS location provider supports only three extra commands:

delete_aiding_data

force_time_injection

force_extra_injection

The delete_aiding_data command is used to remove the A-GPS data that has been previously downloaded. It is the only extra command that makes use of the Bundle parameter, which is used to control what A-GPS data should be removed. The Bundle can contain Boolean values with keys to indicate which data to remove. The keys can be any of the following strings:

ephemeris

almanac

position

time

iono

utc

health

svdir

scsteer

sadata

rti

celldb-info

all

Passing a null for the Bundle causes all the A-GPS data to be removed.

The force_time_injection command causes the current time to be retrieved from the configured NTP server and updated for the purposes of GPS calculations.

The force_extra_injection command causes the A-GPS data to be downloaded from one of the configured servers and used by the GPS location provider.

Network Provider

In Android, network-based location can use different methods for determining the location of a device. As of this writing, the network location provider can provide location information using cell towers, or based on wireless network information.

Using Wireless Network Access Points

Providing location information based on wireless network access points is one of the ways that Android supports location resolution with the network provider. Although it does require that the Wi-Fi radio is active, the Wi-Fi radio often consumes less battery power than the GPS hardware.

How It Works

Wi-Fi-based location detection works by having a device track what Wi-Fi access points it can detect and the current signal strength of those access points. The device then makes a query to the Google location service (which is different from the Android location service), which provides location data based on the Wi-Fi information. The Wi-Fi information collected by the device includes the mandatory access control (MAC) addresses of the Wi-Fi access points that are in range and the strength of the signal being received from those access points.

To provide location information based on visible Wi-Fi access points, the Google location service must obtain information about Wi-Fi access points and their locations. This information is collected by Android devices when a user enables use of Google's location service in the Location Settings screen. Figure 1.2 shows the confirmation screen that is presented to a user when enabling the Google location service as a source of location data.

Figure 1.2 Confirmation screen displayed when enabling Google's location service

Pressing Agree on this screen allows the device to record Wi-Fi information as well as current location information (possibly provided by GPS) and transmit this information to Google. This essentially allows Google use each and every Android device as a way to update the Wi-Fi location information and constantly maintain up-to-date data.

One of the main benefits of the Wi-Fi location source is that it allows devices to acquire location information in areas where GPS cannot provide location data. As stated in the previous section, GPS is problematic when used indoors or even in an urban environment where tall buildings can cause signal problems. In contrast, an urban environment may increase the accuracy of Wi-Fi-based location because of the abundance of Wi-Fi networks available to determine a device's current location.

Limitations

As with GPS, using Wi-Fi networks as a source of location information does have its limitations. First, to determine the location, Wi-Fi networks must be in range. Additionally, the networks must have a publicly broadcasted service set identifier (SSID) that has not been configured to be ignored by Android. Access points that have an SSID that ends in _nomap will not have their information sent to the Google location service.

Additionally, changes to the location of Wi-Fi access points can cause inaccuracies in the location data that is produced. For example, many people now have wireless networks in their homes for daily use. Assuming an Android device has been configured to use the Google location service, Android would have sent the access point MAC address and location to the Google location service. If the user were to change the location of that access point (take it to a vacation home, for example), the location service might determine the device to be in the wrong location when the Wi-Fi location source is used.

Although the location service does allow for access point location to be updated via Android devices, Google does not allow users to explicitly set the location of an access point. An Android device will push the information to the location service, which may wait until other devices can confirm the change before the location service is updated.

Using Cell IDs

In addition to using Wi-Fi information to determine device location, Android can also use the cellular network. The cellular network is used in a similar way as Wi-Fi access points to determine device location.

How It Works

To function properly, a cellular device must be in contact with a cell tower. As a device moves, it may connect to a different cell tower as the signal strength of an approaching cell tower becomes stronger. Knowing the unique ID of the tower that a device is currently connected to, and possibly the towers that a device was previously connected to, can provide insight to where the device is located assuming the location of a given cell tower is known.

Android and the Google location service work together to map cell tower IDs to location data in a way that is similar to Wi-Fi data. Once a device has been configured to use the network provider, it collects data on the current cell tower ID in addition to the visible wireless networks. For cell towers, this data includes the cell tower the device is currently connected to and the device's current GPS location. With this information, the Google location service can develop a “map” of cell towers that includes their locations.

By again allowing Android devices to update cell ID information, the Google location service can maintain a constantly updated store of information that increases in accuracy as the number of entries increases.

When a device needs to find its current location, it sends the ID of the cell tower it is currently connected to, as well as historic information about past cell towers it has used, to the Google location service. With this information, the Google location service can provide information about the device's current location based on the data it has about the cell tower network. If the IDs of multiple cell towers are sent to the Google location service, it can use triangulation to provide increased location accuracy. The Google location service cannot do this if the device submits only a single cell tower ID.

Limitations

The limitations for using cell tower IDs are similar to the limitations that exist when using Wi-Fi networks to determine location. However, because the location of cell towers is less likely to change than the location of wireless access points, some of the complications that may exist when using Wi-Fi access points are removed.

However, just like Wi-Fi access point data, the Google location service must have data on the cell tower IDs that are sent by a device in order to provide location data.

Summary

This chapter presented an overview of how the location providers available in Android work and discussed their limitations. The decision of which location provider to use in which situation can be a complex topic, and is discussed at length in the following chapters.

Chapter 2

Determining a Device's Current Location

What's in this chapter?

Introduction to the Android Location API components

Introduction to the different sources of location information in Android

Example usage of the Location API to determine a device's current location

Mobile app developers often have to determine the device's current location. Knowing a device's location enables app developers to add increased functionality to a wide range of apps. Location data is a key component to apps like Google Maps and Google Navigator, and is also used in Google search, Twitter, and Facebook to add another dimension to the data they are already collecting.

For developers who have made the decision to include location data, Android provides a fairly robust API to its location service. Although on the surface this API may seem trivial to use, plenty of details — such as battery life and accuracy of location data — need to be considered.

As an introduction to the topic of location services in Android, this chapter provides a guided tour of the location portions of the API. In addition, the chapter presents an app that answers the most basic Android question (“Where am I?”) and presents location data on the screen. Figure 2.1 shows the app's screen.

Figure 2.1 Current location app

Know Your Tools

This chapter starts the discussion of the location service by first taking a bird's-eye view of some of the tools that Android has to offer. One of the first things I do when I need to solve a problem is to take a look at what tools I have to work with. For Android, the majority of the classes that you will need when working with location data are located in the android.location package. For the example app, you will need to use five members of the location package. These just happen to be the five members of that package that you will frequently use when dealing with location data in Android.

Classes:

LocationManager

LocationProvider

Location

Criteria

Interfaces:

LocationListener

Figure 2.2 shows a high-level overview of how the location components fit together. Because these members are so important and used so frequently, the following sections discuss each one in a little more detail.

Figure 2.2 Android location components

LocationManager

The main point of entry when using the location service in Android is the LocationManager. The LocationManager allows an app to tell Android when it is interested in receiving updated location information and when it no longer wants location updates. In addition, the LocationManager provides information about the current state of the location system such as available location providers, enabled location providers, and GPS status information. The LocationManager can also provide the last known (cached) location of the device.

LocationProvider

LocationProvider is an abstraction for the different sources of location information in Android. Android provides different sources of location data that have drastically different characteristics. Though each provider generates location data differently, they all communicate with an app the same way and provide similar data to an app in the same manner.

Location

The Location class is what encapsulates the actual location data provided to an app from a location provider. It contains the quantifiable data such as latitude, longitude, and altitude. Once an app has received a Location object, it can start the application-specific processing on that data.

One important point about the Location class is that, although it has properties for a wide range of location data, not all location providers will populate all the properties. For example, if an app uses a location provider that does not provide altitude, the Location instance will not contain altitude information. The Location class also provides methods that allow an app to check if an instance contains the information (hasAltitude() in this case).

Criteria

An app can use the Criteria class to query the LocationManager for location providers that contain certain characteristics. This is useful for times when an app is less concerned with which actual providers are used and more concerned that location providers have some common characteristics. The Criteria class prevents an app from worrying about the implementation details of working with individual location providers directly. Once instantiated, an app can set/unset attributes on a Criteria class to reflect the characteristics of the location providers that it is interested in. Table 2.1 provides the list of the attributes on the Criteria class that can be used to select a location provider.

Table 2.1 Location Criteria Attributes

Attribute

Explanation

Possible Values

accuracy

Indicates the overall level of accuracy for a location provider.

Criteria.ACCURACY_FINE

or

Criteria.ACCURACY_COURSE

altitudeRequired

Indicates whether a location provider needs to provide altitude information.

True or false

bearingRequired

Indicates whether a location provider needs to provide bearing (the direction being traveled) information.

True or false

bearingAccuracy

Required accuracy for bearing information.

Criteria.ACCURACY_HIGH

or

Criteria.ACCURACY_LOW

costAllowed

Indicates whether the location provider is allowed to cost the user money.

True or false

horizontalAccuracy

Required accuracy for latitude and longitude values.

Criteria.ACCURACY_LOW

,

Criteria.ACCURACY_MEDIUM

, or

Criteria.ACCURACY_LOW

powerRequirement

Amount of battery power required by the location provider.

Criteria.POWER_LOW

,

Criteria.POWER_MEDIUM

, or

Criteria.POWER_LOW

speedRequired

Indicates whether a location provider needs to provide speed information.

True or false

speedAccuracy

Required accuracy for speed information.

Criteria.ACCURACY_HIGH

or

Criteria.ACCURACY_LOW

verticalAccuracy

Required accuracy for altitude information.

Criteria.ACCURACY_HIGH

or

Criteria.ACCURACY_LOW

LocationListener

The LocationListener interface contains a group of callback methods that are called in reaction to changes in a device's current location or changes in location service state. The LocationManager enables an app to register/unregister a location listener implementation that can be used to process the changes in state.

There are two ways to receive location updates from the location service: a LocationListener and a PendingIntent. This chapter focuses on using a LocationListener; the use of a PendingIntent is deferred until the next chapter.

Now that the tools needed to implement the app have been introduced, the following sections dig into the mechanics of requesting and processing the location information.

Setting up the Android Manifest

As with many of the services that Android provides, the location service requires an app to declare its intentions to use it in the Android manifest. The Android manifest declaration must define the precision of the location data that will be requested. Like any other Android permission, the end user will be shown the list of requested permissions at install time and will be able to decline installation upon seeing that list. Some users are a little squeamish at the thought of allowing an app to determine their location if it is not clear why the app would need this information. Adding superfluous permissions is a good way to scare users away.

The two permissions that deal with live location data are android.permission.ACCESS_FINE_LOCATION and android.permission.ACCESS_COARSE_LOCATION. As the names might indicate, the permissions define the level of accuracy that will be provided to an app from the location service. Ultimately, these permissions define which location providers can be used in an app. Because the android.permission.ACCESS_FINE_LOCATION permission provides more accurate location data, it can be used without explicitly specifying android.permission.ACCESS_COARSE_LOCATION to grant permission for both fine-grained and coarse-grained location data. However, android.permission.ACCESS_COARSE_LOCATION only allows for coarse-grained location data to be provided to an app.

For the app in this chapter, highly accurate location data is desired. So, the following code snippet is added to AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Failure to request the correct permissions causes ajava.lang.SecurityExceptionto be thrown at run time when requesting location updates.

Determining the Appropriate Location Provider

Multiple sources of location data in Android provide varying levels of accuracy and battery consumption. Determining when to use the different providers can have a big impact on the overall user experience of an app. The location providers available in Android are:

GPS location provider

Network location provider

Passive location provider

An app can declare which location provider to use in one of two ways: by explicitly registering each desired location provider with the LocationManager, or by specifying attributes in a Criteria object and passing that object to the LocationManager. Using the Criteria object is useful for allowing the user to customize the source of location data at run time. This may be of importance to a user because use of some location providers can cost them money.

GPS Location Provider

The GPS location provider uses orbiting satellites and time to determine the current location of a device, and tends to produce the most accurate location data. However, because it relies on a separate radio, the GPS provider can also consume more battery power than other location providers. This can be a major issue depending on the length of time an app needs to actively be receiving and processing location data.

In addition to consuming more battery power, the GPS location provider can also take a long time to acquire a fix (location data). Time to first fix (TTFF) values of over a minute are common, and can vary drastically from device to device or between different versions of Android. In addition, obtaining a GPS fix indoors is unlikely because a direct line to the sky is usually required. TTFF is important to pay attention to because it is generally a bad idea to block the user from performing a task while an app is waiting for location data.

Network Location Provider

The network location provider uses two data sources to provide a location fix: Wi-Fi network location and cell-tower location. The TTFF for the network provider can be substantially less than the TTFF for the GPS provider. However, the network provider produces much less accurate location data. Depending on the needs of an app, it might be worth trading the location accuracy of the GPS provider for the low TTFF values of the network provider. The network provider may also consume less battery power than the GPS provider because it allows the user to leave the GPS radio and (possibly) the Wi-Fi radio off.

Passive Location Provider

The passive location provider allows an app to receive location information without having to explicitly request location update information from the LocationManager. The passive provider provides location updates when another app has explicitly requested location updates with either the GPS or network providers. This allows an app to piggy-back on the location information requested from another app and prevent Android from making a special request for location data.

At first glance, it may not be obvious how to use this provider. Essentially, the passive location provider allows an app to receive location updates in the background without consuming any additional battery power, because it receives updates only when something else is receiving updates.

This implies that an app does not have any control over which other providers are used to receive location updates, or the frequency at which the updates will arrive (the other apps have defined this when setting up the LocationManager). Because of this, use of the passive provider mandates the use of the android.permission.ACCESS_FINE_LOCATION permission so that data from both the GPS and network providers can be received. The Location object that is received will contain information about the source of the location data.

The passive provider is not guaranteed to receive any location updates. If no other apps are receiving location updates, the passive provider will not receive any either. Because of this, the passive provider is generally not appropriate to use when an app is in the foreground and actively interacting with the user. Use the passive location provider to keep application data up to date while running in the background and without explicitly requesting location data.

It is good form for apps to be a “good citizens” on an Android device and remove requests for location updates when they app exit. If an app makes the distinction of closing as opposed to backgrounding (user clicks “back” as opposed to user pressing “home”), then the app should unregister for updates even when using the passive provider.

Accuracy versus Battery Life

The common theme when choosing location providers is deciding between increased accuracy and increased battery consumption. Although most apps that need location data could benefit from more accurate data, many of them do not truly need the accuracy, especially at the expense of additional battery power.

Table 2.2 provides a summary of the location providers available in Android.

Table 2.2 Location Providers

Determining which location providers are the appropriate the source of location data is an important decision when using location services. As with many other development decisions, trade-offs exist that need to be considered.

Receiving Location Updates

Before getting knee-deep into Java code, one more topic warrants discussion: how an app actually gets notified about location updates. Recall from an earlier discussion that location data can be delivered to an app in two ways: a direct call to a LocationListener, or by a broadcasted Intent. The LocationListener approach is the simpler approach (and the one used for this chapter's example app), but the broadcast Intent approach can offer more flexibility, especially if location update information needs to be provided to more than one application component.

In either case, an app must tell the LocationManager when it is ready to start receiving updates as well as when it no longer wants location updates. How the location updates get sent to an app is defined by how an app registers for location updates with the LocationManager.

Receiving Location Updates with a LocationListener

Objects that implement LocationListener are notified of location updates by a call to their onLocationChanged() method. The specific LocationListener instances which will be notified about a location update are registered with LocationManager. When the LocationManager has a new location to offer, it makes a call to onLocationChanged() for each listener. Further discussion of LocationListener usage is deferred to when the Java code for the example app is introduced in the section “Implementing LocationListener.”

Receiving Location Updates with a Broadcast Intent

Having an Intent broadcasted with location updates can offer increased flexibility in situations where an app needs the update to be received by multiple application components. To make use of the broadcasted Intent, an app needs to implement a BroadcastReceiver and register it to receive location update Intent(s). This can happen either in an Android manifest or at run time. The app created in Chapter 4 includes use of a broadcast Intent.

Implementing the Example App

This section provides the details of how to put all the pieces of the location API together and start getting location data.

The example app has an activity, CurrentLocationActivity, that displays the current location and contains a button that allows the user to enable/disable location providers. Once the app gets a single location, it displays some of the location details on the screen. This will enable the user to see with the location service in action on an actual device and enable the user to start getting a feel for how accurate the various location providers are as well as how their TTFF values differ. It is important to understand the details of accuracy/TTFF and how they correlate to different providers when making app development decisions.

Implementing LocationListener

To implement LocationListener, a class must contain a concrete implementation for the following methods:

abstract void onLocationChanged(Location location)

abstract void onProviderDisabled(String provider)

abstract void onProviderEnabled(String provider)

abstract void onStatusChanged(String provider, int status, Bundle extras)

These methods are discussed in the following sections.

onLocationChanged()

The method that an app is most likely to interact with is onLocationChanged(). This is the method that is called when a new location is ready for consumption by an app. The single parameter to this method is a Location object that contains the details of the location (latitude, longitude, altitude, and so on). At times, this will be the only method an app needs to implement from the LocationListener. However, the app will need to provide an implementation for the other methods to avoid compilation errors, the implementations can be left empty (I like to add a comment indicating that they were intentionally left blank for future developers). For this app, the onLocationChanged() method simply takes the Location object it was passed and uses its data to populate the UI views (see Listing 2.1).

Listing 2.1: Receiving a location update

onProviderDisabled() and onProviderEnabled()

The onProviderDisabled() and onProviderEnabled() methods provide a way for an app to be notified when the user enables or disables a location provider from the location settings menu. Imagine, for example, that a user is currently running an app and decides to put the app in the background by pressing the home button and returning to the desktop. From there, the user can navigate to the device settings and enable or disable different location providers. These actions may be of interest to an app. If the user were to enable the GPS provider, the app would be able to get more accurate location information for the device.

The onProviderDisabled() and onProviderEnabled() methods are Android's way of letting an app know when the state of a provider changes. Each method provides a string parameter that specifies the name of the location provider that was either enabled or disabled. The String provider name can be matched to the static constants in LocationManager to determine which provider had its state changed. These methods work well with LocationManager.getProviders(), which can be used to initially register providers that are currently enabled and dynamically add or remove more providers as they are enabled or disabled when onProviderEnabled() or onProviderDisabled() is called.

onStatusChanged()

The onStatusChanged() method is called when a provider either goes offline or comes back online. This is a different scenario than in the previous section where the user enabled or disabled the provider. In this scenario, the user has not changed the location settings; instead, the status of the actual provider has changed.

The parameters to this method are a string that represents the provider, an int representing the current status, and a Bundle that has optional data. The provider name is the same string that is passed to both onProviderEnabled() and onProviderDisabled(). The status will be one of the three values listed in Table 2.3.

Table 2.3 onStatusChanged() Status Values

Value

Status

LocationProvider.OUT_OF_SERVICE

The

LocationProvider

is currently offline and probably will not come back online anytime soon.

LocationProvider.TEMPORARILY_UNAVAILABLE

The

LocationProvider

is currently offline and should come back online soon.

LocationProvider.AVAILABLE

The

LocationProvider

is currently online.

The Bundle parameter contains optional provider-specific information. For example, a bundle for the GPS provider will contain the number of satellites used to come up with the location update.

Obtaining a Handle to LocationManager

Because the LocationManager is the front door into the location service, the app needs to get a reference to it. This is done with a call to Activity.getSystemService(LOCATION_SERVICE). This is generally done in the onCreate() method of an Activity because multiple calls to the LocationManager throughout the lifetime of an Activity are common. Because the onCreate() method is the first method to be called in an activity's life cycle, it is appropriate to acquire the location manager reference here. For the example app in this chapter, the remainder of the onCreate() method is spent retrieving references to the UI views that will hold and present the location data. Listing 2.2 shows the implementation for the onCreate() method.

Listing 2.2: Obtaining a reference to the LocationManager

Listing 2.3 shows the layout for the activity that will display the current location data: latitudeValue, longitudeValue, providerValue, accuracyValue, timeToFixValue, and enabledProviderValue.

Listing 2.3: Layout for CurrentLocationActivity

<?xml version="

1.0

" encoding="

utf

-

8

"?> <RelativeLayout xmlns:android="

http://schemas.android.com/apk/res/android

" android:orientation="

vertical

" android:layout_width="

match_parent

" android:layout_height="

match_parent

"> <TextView android:id="@+

id/latitudeLabel

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/latitudeLabel

" android:layout_alignParentTop="

true

" android:layout_marginRight="

4dip

" /> <TextView android:id="@+

id/latitudeValue

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:layout_alignTop="@

id/latitudeLabel

" android:layout_toRightOf="@

id/latitudeLabel

" /> <TextView android:id="@+

id/longitudeLabel

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/longitudeLabel

" android:layout_below="@

id/latitudeLabel

" android:layout_marginRight="

4dip

" /> <TextView android:id="@+

id/longitudeValue

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:layout_alignTop="@

id/longitudeLabel

" android:layout_toRightOf="@

id/longitudeLabel

" /> <TextView android:id="@+

id/providerLabel

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/providerLabel

" android:layout_below="@

id/longitudeLabel

" android:layout_marginRight="

4dip

" /> <TextView android:id="@+

id/providerValue

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:layout_alignTop="@

id/providerLabel

" android:layout_toRightOf="@

id/providerLabel

" /> <TextView android:id="@+

id/accuracyLabel

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/accuracyLabel

" android:layout_below="@

id/providerLabel

" android:layout_marginRight="

4dip

" /> <TextView android:id="@+

id/accuracyValue

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:layout_alignTop="@

id/accuracyLabel

" android:layout_toRightOf="@

id/accuracyLabel

" /> <TextView android:id="@+

id/accuracyUnits

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/metersUnit

" android:layout_alignTop="@

id/accuracyLabel

" android:layout_toRightOf="@

id/accuracyValue

" android:layout_marginLeft="

4dip

" /> <TextView android:id="@+

id/timeToFixLabel

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/timeToFixLabel

" android:layout_below="@

id/accuracyLabel

" android:layout_marginRight="

4dip

" /> <TextView android:id="@+

id/timeToFixValue

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:layout_alignTop="@

id/timeToFixLabel

" android:layout_toRightOf="@

id/timeToFixLabel

" /> <TextView android:id="@+

id/timeToFixUnits

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/secondsUnit

" android:layout_alignTop="@

id/timeToFixLabel

" android:layout_toRightOf="@

id/timeToFixValue

" android:layout_marginLeft="

4dip

" /> <TextView android:id="@+

id/enabledProvidersLabel

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:text="@

string/enabledProvidersLabel

" android:layout_below="@

id/timeToFixLabel

" android:layout_marginRight="

4dip

" /> <TextView android:id="@+

id/enabledProvidersValue

" android:layout_height="

wrap_content

" android:layout_width="

wrap_content

" android:layout_alignTop="@

id/enabledProvidersLabel

" android:layout_toRightOf="@

id/enabledProvidersLabel

" /> <Button android:id="@+

id/changeLocationProviderSettings

" android:layout_height="

wrap_content

" android:layout_width="

match_parent

" android:text="@

string/changeLocationProviderSettingsText

" android:onClick="

onChangeLocationProvidersSettingsClick

" android:layout_alignParentBottom="

true

" /> </RelativeLayout>

Code snippet current_location.xml

Now that the app has a reference to the LocationManager, it is ready to request location information for the Location Service.

Requesting Location Updates

The app is now ready to ask Android to provide it with location information when it becomes available. It is important to understand that an app cannot ask Android to provide it with on-demand location information. Apps can only request to be notified when updated location information is available.

This app needs only a single location update, so a call to one of the LocationManager.requestSingleLocation() methods is needed. Examining the Android reference docs reveals two flavors of the LocationManager.requestSingleLocation() methods. One flavor passes a PendingIntent in order to broadcast an Intent with location data and the other passes a LocationListener in order to receive direct callbacks. Again, this app uses the LocationListener approach. The CurrentLocationActivity has been made a LocationListener by having it implement the LocationListener interface. This allows the app to keep all the location code in one class.

Before a LocationListener can be registered with the LocationManager, the app developer must decide which location provider(s) the app will use. For this app, the decision is left to the end user because the app will use only the location providers that the user has enabled. To get the list of enabled location providers, a Criteria object is created and the attributes are set to include both the network and GPS location providers. Both the network and GPS providers provide at least a coarse location fix, so passing Criteria.ACCURACY_COARSE to Criteria.setAccuracy() will include both providers for consideration. The initialized Criteria instance is then passed to the getProviders() method along with a boolean (hard-coded to true) to indicate that only enabled location providers should be returned. Each location provider in the returned list is then used to obtain location data.

Because the app needs a new location every time the CurrentLocationActivity is presented to the user (because the user is allowed to enable or disable location providers in-app), the onResume() method is where the LocationManager is formally asked to provide a location update as they become available, as shown in Listing 2.4.

Listing 2.4: Registering with the LocationManager

code snippet CurrentLocation.java

Thus far, this chapter has discussed how to register a LocationListener to receive updates. The final step is unregistering for those location updates when they are no longer required by the app.

Cleaning up After Yourself

At this point, the app is ready to start receiving and processing location data in CurrentLocationActivity. The last part of the implementation is to have the app clean up after itself by unregistering the location listener when it no longer needs location updates. Forgetting to unregister a location listener could cause the providers and underlying hardware to remain active, thus wasting battery life. Not removing a location listener registration for the GPS provider causes (an enabled) GPS provider to actively retrieve and compute location data. This is visible to the user because the GPS provider has its own icon alerting the user to the issue. Leaving the GPS running when it is no longer needed is bad practice and can result in negative feedback in the Android Market.

The app doesn't need any location updates when the CurrentLocationActivity is not interacting with the user. As shown in Listing 2.5, it will unregister the LocationListener on the onPause() method.

Listing 2.5: Removing a LocationListener

@Override protected void onPause() { super.onPause(); locationManager.removeUpdates(this); }

Had the BroadcastReceiver approach been used, the app would have again called locationManager.removeUpdates(), and would have passed in the PendingIntent that was passed to registerSingleUpdate().

Now that the app has code to initialize itself, process location updates, and clean up after itself, the next step in the example app implementation is responding to the user enabling/disabling location providers while the app is running.

Launching the Location Settings Activity

The final detail of the app worth discussing is the button on the screen that enables the user to change location provider settings. In order to receive location data from a specific location provider, an app should ensure that the location provider is enabled by the user. If the user does not currently have the provider enabled, the location settings activity can be for them and allow them to enable the provider without leaving the app. This occurs in the example app when the Change Location Provider Settings button is pressed. Accomplishing this is actually pretty trivial, as evidenced by Listing 2.6, and it happens in the handler for the button click.

Listing 2.6: Launching the location settings activity

public void onChangeLocationProvidersSettingsClick(View view) { startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); }

The location settings activity screen is displayed in Figure 2.3.

Figure 2.3 The location settings screen

Now that you have an app capable of determining your current location, try loading the app on an actual device and spending some time playing with the different location providers, paying special attention to TTFF and accuracy differences. Try running the app in different environments (indoors and outdoors, sunny and overcast, urban and rural) to see how they affect the various location providers. Spending some time getting a feel for how the providers work will give you an idea of their limitations.

Summary

This chapter provided a tour around some of the basic SDK elements that are needed to work with Android location services. The chapter discussed some of the foundation classes, and examined the implementation of a simple app for determining the current location of a device. This app really is the “sunny day” scenario and does not handle some of the real-world problems an app will face when using location services. Although the information in this chapter is enough to get up and running, the next few chapters describe how to take full advantage of Android location services.

Chapter 3

Tracking Device Movement

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!