Many apps today use the location services of the Android device. One such app is Uber, which people use to find a car to go somewhere for a fee. The app uses the device’s Global Positioning System (GPS) to locate where we are and find registered car drivers who are nearby. It uses satellites to provide location and time information.
In this app, we intend to retrieve the location of the device, ask the user for a destination, and calculate the distance and time to destination. In order for the app to retrieve the location of the device using its GPS, it needs to access Google Play services. We use an Empty Activity template for this app. In Version 0 of this app, we show how we can check if a device can access Google Play services. We need to do the following:
▸ Edit the build.gradle file in order to include Google Play services in the compilation process.
▸ Edit the MainActivity
class in order to access Google Play services.
EXAMPLE 11.1 shows the build.gradle (Module: app) file. We edit it in order to make the Google Play services libraries available to the app (note that there are two build.gradle files). The only addition is at line 26: we include the appropriate version of the Google Play services libraries. At the time of this writing, it is 9.4.0.
After editing the build.gradle file, we should click on the Sync Project with Gradle Files icon on the tool bar, as shown on FIGURE 11.1.
Inside the MainActivity
class, we do the following:
▸ Try to access Google Play services from the device.
▸ If we cannot and the issue can be resolved, we try to resolve it. Otherwise, we exit the app.
▸ Retrieve the current location and display it.
TABLE 11.1 Selected methods of the GoogleApiClient.Builder
class
Method | Description |
---|---|
GoogleApiClient.Builder( Context context ) | Constructs a GoogleApiClient object. |
GoogleApiClient.Builder addConnectionCallbacks( GoogleApiClient. ConnectionCallbacks listener ) | Registers listener to receive connection events. Returns this GoogleApiClient.Builder reference so method calls can be chained. |
GoogleApiClient.Builder addOnConnectionFailedListener( GoogleApiClient.ConnectionFailedListener listener ) | Registers listener to receive failed connection events. Returns this GoogleApiClient.Builder reference so method calls can be chained. |
GoogleApiClient.Builder addApi( API<? extends Api.ApiOptions.NotRequiredOptions> api ) | Specifies api as an API requested by this app. We should use the API constant of LocationServices. Returns this GoogleApiClient.Builder reference so method calls can be chained. |
GoogleApiClient build( ) | Builds and returns a GoogleApiClient object for communicating with the Google APIs. |
The GoogleApiClient abstract
class, from the com.google.android.gms.common.api
package, is the main entry point for Google Play services. It includes the functionality to establish a connection to Google Play services and manage it. Since it is abstract
, we cannot instantiate an object of that class using the new
operator. It includes a static
inner class, Builder
, which includes methods to specify attributes of a GoogleApiClient
and a build
method to create one. TABLE 11.1 lists some of these methods. These methods, except the build
method, return the GoogleApiClient.Builder
reference that calls them, so that method calls can be chained. The build
method returns a GoogleApiClient
reference.
The GoogleApiClient
class includes the ConnectionCallbacks
and OnConnectionFailedListener static
inner interfaces. ConnectionCallbacks
provides callback methods that are automatically called when we connect or are disconnected from the Google service. OnConnectionFailedListener
provides a callback method that is automatically called if the connection attempt failed. TABLE 11.2 lists them. The int
parameter of the onConnectionSuspended
method can be tested against the CAUSE_SERVICE_DISCONNECTED
and CAUSE_NETWORK_LOST
constants of the ConnectionCallbacks
interface in order to determine the cause of the disconnection.
TABLE 11.2 The ConnectionCallbacks
and OnConnectionFailedListener
interfaces and their methods
Interface | Method | Description |
---|---|---|
ConnectionCallbacks | void onConnected( Bundle connectionHint) | Automatically called after successful completion of a connection request made by calling the connect method with a GoogleApiClient reference. |
ConnectionCallbacks | void onConnectionSuspended(int cause) | Automatically called when the connection is lost. The GoogleApiClient object will automatically attempt to restore the connection. |
OnConnectionFailedListener | void onConnectionFailed(ConnectionResult result) | Automatically called when there is an error connecting to the service. |
Thus, assuming we are inside an Activity
class that implements the ConnectionCallbacks
and OnConnectionFailedListener
interfaces, we can instantiate a GoogleApiClient
object using the following sequence:
// Assuming that we are inside an Activity class and that it // implements ConnectionCallbacks and OnConnectionFailedListener GoogleApiClient.Builder builder = new GoogleApiClient.Builder( this ); builder.addConnectionCallbacks( this ); builder.addOnConnectionFailedListener( this ); builder.addApi( LocationServices.API ); GoogleApiClient gac = builder.build( );
Since we are inside an Activity
class, we can use this
as the argument of the GoogleApiClient.Builder
constructor. Since the Activity
class implements both interfaces, we can also use this
as the argument of addConnectionCallbacks
and addOnConnectionFailedListener
. We use the API
constant of the LocationServices
class, shown in TABLE 11.3, as the argument of the addApi
method. Alternatively, since these three methods return the GoogleApiClient.Builder
reference that calls them, we can chain method calls as follows:
GoogleApiClient gac = new GoogleApiClient.Builder( this ) .addConnectionCallbacks( this ) .addOnConnectionFailedListener( this ) .addApi( LocationServices.API ).build( );
TABLE 11.3 Selected fields of the LocationServices
class
Constant | Description |
---|---|
API | A constant that should be used to pass to the addApi method of the GoogleApi.Builder class during the process of building a GoogleApiClient. |
FusedLocationAPI | Static constant of type FusedLocationProviderAPI, an interface that includes methods to retrieve the location of a device and manage location updates. |
TABLE 11.4 Selected methods of the GoogleApiClient
class
Methods | Description |
---|---|
void connect( ) | Establishes a connection with Google Play services. If successful, the onConnected method of ConnectionCallbacks is called. If unsuccessful, onConnectionFailed is called. |
void disconnect( ) | Closes the connection with Google Play services. |
Once we have a GoogleApiClient
reference, and assuming its name is gac
, we can attempt to establish a connection by calling the connect
method of GoogleApiClient
, shown in TABLE 11.4, as in the code that follows:
// Assuming that gac is a GoogleApiClient reference gac.connect( );
If the connection is successful, the onConnected
method of the ConnectionCallbacks
interface is automatically called. Inside that method, we can retrieve the location of the device.
If the device fails to connect to Google Play services, the onConnectionFailed
callback method is called. We want to check if that issue can be resolved (for example, Google Play services may need to be updated on the device). We can do that by calling the hasResolution
method with the ConnectionResult
parameter of onConnectionFailed
. If that method returns false
, the issue cannot be resolved and we can exit the app. If that method returns true
, the issue can be resolved and we want to try to resolve it. We can do so by calling the startResolutionForResult
method of ConnectionResult
. TABLE 11.5 shows both methods. This requires user interaction. After it is over, the onActivityResult
method of the Activity
class will be called. Inside that method, we can check if the issue was resolved. If it was, we can try to connect again to Google Play services.
TABLE 11.5 Selected methods of the ConnectionResult
class
Method | Description |
---|---|
boolean hasResolution( ) | Returns true if there is a resolution that can be started to attempt to solve the connection issue. |
void startResolutionForResult( Activity activity, int requestCode ) | Starts an intent to attempt to resolve a connection issue. This requires user interaction. |
We can implement this with the following pseudo-code:
// inside onConnectionFailed method if( there is a possible resolution to the issue ) call startResolutionForResult to try to resolve it else exit the app // inside onActivityResult if( the problem was resolved ) try to connect again
EXAMPLE 11.2 shows the MainActivity
class. It implements the ConnectionCallbacks
and OnConnectionFailedListener
interfaces (lines 14–15). We declare a GoogleApiClient
instance variable at line 18. We instantiate it at lines 25–28. The onStart
method is automatically called after onCreate
executes. If gac
is not null
(line 66), we try to establish the connection at line 67. If successful, this triggers a call to the onConnected
method (lines 31–34). In this version, we simply output some feedback to Logcat. If the connection attempt fails, we execute inside onConnectionFailed
(lines 41–54). At line 44, we test if there is a possible resolution to that problem. If there is, we try to start an activity to solve it at line 46. If we cannot, we exit the app after showing a Toast
(lines 48–51). If we were successful in starting an activity to try to solve the connection problem, and after interaction with the user, the app will resume execution inside the onActivityResult
method (lines 56–62). If the resolution was successful (line 58), we try to connect to Google Play services again at line 60.
When running the GPS app, Version 0, the output inside Logcat shows that we are connected.
In Version 1, we retrieve the location of the device and display it in a TextView
. Since the app accesses the GPS, it will not work in the emulator, although we could hard code latitude and longitude data using the emulator. To use our current location, we need to run it on a device. Because the app uses location services from Google, we need to specify that in the AndroidManifest.xml file. Thus, we need to do the following:
▸ In the AndroidManifest.xml file, specify that we use location services and add meta data about the Google Play services version this app uses.
▸ Inside the MainActivity
class, capture our current location and display it.
EXAMPLE 11.3 shows the AndroidManifest.xml file. At lines 5–6, we specify that this app accesses the approximate location of the device. The ACCESS_COARSE_LOCATION
and ACCESS_FINE_LOCATION String
constants of the Manifest.permission
class can be used to specify an approximate or a precise location, respectively. At lines 15–17, we specify the version of Google Play services that this app uses. To make it simple, we only allow the app to work in vertical orientation (line 20).
Inside the MainActivity
class, we do the following:
▸ Establish a connection with Google Play services.
▸ Retrieve the location.
▸ Display the location.
The Location
class, part of the android.location
package, encapsulates a geographical location on Earth. A location is typically identified by its latitude and longitude. TABLE 11.6 lists a few methods of the Location
class. Note that the Location
class uses the metric system and distances, when calculated by methods, are returned in meters.
The lastLocation
method of the FusedLocationProviderApi
interface returns the current location of the device as a Location
reference. It accepts a GoogleApiClient
parameter, as shown in TABLE 11.7. We use this method to retrieve the device’s location. Thus, in order to call that method, we need a FusedLocationProviderApi
reference to call it, and a GoogleApiClient
reference to pass as its only argument. As shown in Table 11.3, the LocationServices
class, part of the com.google.android.gms.location
package, includes a FusedLocationProviderApi
constant named FusedLocationApi
. Thus, assuming we have a GoogleApiClient
reference named gac
, we can retrieve the current location using the following sequence:
// Assuming that gac is a GoogleApiClient reference FusedLocationProviderApi flpa = LocationServices.FusedLocationApi; Location location = flpa.getLastLocation( gac );
TABLE 11.6 Selected methods of the Location
class
Method | Description |
---|---|
double getLatitude( ) | Returns the latitude of this Location. |
double getLongitude( ) | Returns the longitude of this Location. |
float getAccuracy( ) | Returns the accuracy of this Location, in meters. |
float distanceTo( Location destination ) | Returns the distance between this Location and destination, in meters. |
TABLE 11.7 The getLastLocation
method of the FusedLocationProviderApi
interface
Method | Description |
---|---|
Location getLastLocation( GoogleApiClient gac) | Returns the most recent location, null if no location is available. |
Once we have a Location
reference for the current location, we can retrieve the latitude and longitude of that location by calling the getLatitude
and getLongitude
methods as follows:
double latitude = location.getLatitude( ); double longitude = location.getLongitude( );
EXAMPLE 11.4 shows the MainActivity
class. We declare two additional instance variables at lines 23–24: location
, a Location
to store the current location; and locationTV
, a TextView
to display the location. Inside onCreate
, we instantiate the TextView
at line 30. This assumes that there is a TextView
whose id
is location_tv
inside activity_main.xml. Inside the onConnected
method, we call the displayLocation
method at line 52. The displayLocation
method (lines 38–48) retrieves the current device location at lines 39–40. If the location is not null
(line 41), we retrieve its latitude and longitude, display them inside the TextView
(line 44), and output them to Logcat (line 45).
EXAMPLE 11.5 shows the activity_main.xml file. The id
of the TextView
is assigned at line 13. EXAMPLE 11.6 shows the styles.xml file, which specifies a font size of 22 at line 5.
FIGURE 11.2 shows the output of the app inside Logcat, showing the latitude and longitude data. Note that we must run this app on a connected device (which has GPS), not the emulator.
In Version 2, we ask the user to input an address for his or her destination, and we provide a button to display the distance and time left to that destination. Before building the GUI and the controller for it, we add the TravelManager
class, the Model for the app, shown in EXAMPLE 11.7. It includes a Location
instance variable to store a destination (line 9) and methods to calculate the distance and time left from the current location to the destination location. In order to keep this app simple, we assume that the user travels at 55
miles per hour (line 6).
In the distanceToDestination
method (lines 15–21), we call the distanceTo
method of the Location
class shown in Table 11.6 in order to calculate the distance between its Location
parameter and destination
. If one of them is null
, it returns –1
. Otherwise, we return the distance between them. The milesToDestination
method (lines 23–31) converts and returns that distance to a String
representing the number of miles.
The timeToDestination
method (lines 33–54) calculates and returns the time that it takes to go from its Location
parameter and destination, assuming a speed of 55
miles per hour. At lines 35–36, we compute the distance to the destination from its Location
parameter in meters. At 37–38, we compute the time in hours, as a float
, that it takes to drive that distance at a speed of 55
miles per hour. We then convert that value to the String result
, which represents the number of hours and the number of minutes at lines 40–52. Note that if the time is either 0
or negative (line 51), we assign less than a minute left
to result
at line 52.
We include the following elements in the GUI, all centered and lined up vertically:
▸ One EditText for the user to enter the destination address.
▸ Two TextViews
to display the distance and time to destination.
▸ One Button
: when the user clicks on it, we update the distance and time to destination in the two TextViews.
EXAMPLE 11.8 shows the updated activity_main.xml file. We give all the elements an id
(lines 13, 18, 23, 28) so we can position them and retrieve them as needed in the MainActivity
class. We want to specify the WRAP_CONTENT
value for both the width and height of all the elements. We also want to have 20
pixels between them and center them horizontally. Thus, we define the WrappedAndCentered
style in styles.xml (lines 11–16 of EXAMPLE 11.9) and use it for all the four elements (lines 15, 20, 25, 32). We specify a hint, Enter destination
, defined in the strings.xml file (line 3 of EXAMPLE 11.10) for the EditText
at line 14. At line 30, we define the text inside the button as the String Update
, defined at line 4 of Example 11.10. At line 31, we specify that the updateTrip
method is called when the user clicks on the Button
.
Inside the MainActivity
class, we need to make the following edits:
▸ Add the appropriate import statements.
▸ Add a TravelManager
instance variable so that we can access the functionality of the Model.
▸ Add instance variables for the EditText
and the two TextViews
of the GUI and a String
to store the destination address.
▸ Delete the displayLocation
method: we are no longer interested in displaying our location.
▸ Add the updateTrip
method.
▸ Delete the body of the onConnected
method: we want to wait for the user to input a destination address before we do anything.
EXAMPLE 11.11 shows the updated MainActivity
class. We declare the additional five instance variables at lines 29–33. The TravelManager
and the three GUI components are instantiated inside onCreate
at lines 39–42. Inside the updateTrip
method (lines 50–79), we retrieve user input, update the Model if necessary, call methods of the Model to calculate the distance and time left to the destination, and update the View accordingly.
We first retrieve the destination address entered by the user at line 51. If the destination address is different from the current destination address (line 53), we update the current destination address (line 54). We then try to geocode it into a Location
object (lines 57–59). Geocoding is the process of converting a street address into a (latitude, longitude) coordinate. TABLE 11.8 shows a constructor and a getFromLocationName
method of the Geocoder
class. If the geocoding is successful (line 60), we assign the Location
to the destination
instance variable of the TravelManager
(line 66). We keep track of whether the geocoding is successful or not with the state variable goodGeocoding
. We initialize it to true
at line 52, and switch it to false
if we end up in the catch
block at line 69. We retrieve the current location at lines 73–74. If we are successful retrieving the current location and if the geocoding was successful (line 75), we update the two TextViews
displaying the distance and time left to the destination at lines 76–77. The manager
instance variable calls the milesToDestination
and timeToDestination
methods, passing the current location.
TABLE 11.8 Selected methods of the Geocoder
class
Methods | Description |
---|---|
Geocoder( Context context ) | Constructs a Geocoder. |
List getFromLocationName( String locationName, int maxResults ) | Returns a list of Address objects that match locationName. Throws an IllegalArgumentException and an IOException. |
FIGURE 11.3 shows the app running inside the tablet after the user enters the address of the White House and clicks on update.
In Version 3, we want to update the distance and time left to destination automatically, without having to click on the Update
button. We keep the Update button in case the user wants an instant update. Thus, the user interface is identical to the one in Version 2.
The LocationListener
interface, part of the com.google.android.gms.location
package, provides a callback method, onLocationChanged
, that is automatically called based on various specified parameters, such as frequency and distance travelled, as shown in TABLE 11.9. This is very similar to event handling; we need to do the following:
▸ Create a private class that implements LocationListener
(and override onLocationChanged
).
▸ Declare and instantiate an object of that class.
▸ Register that object on a fused location provider (a FusedLocationProviderApi
reference).
TABLE 11.9 The onLocationChanged
method of the LocationListener
class
Method | Description |
---|---|
void onLocationChanged( Location location ) | Callback method called automatically as defined by a LocationRequest; location represents the most recent location. |
TABLE 11.10 Selected methods of the FusedLocationProviderApi
interface
Method | Description |
---|---|
PendingResult requestLocationUpdates( GoogleApiClient gap, LocationRequest request, LocationListener listener ) | Requests listener to listen to location updates based on request. |
PendingResult removeLocationUpdates( GoogleApiClient gap, LocationListener listener ) | Discontinues location updates for listener. |
Alternatively, we can do the following:
▸ Have our Activity
class implement LocationListener
(and override onLocationChanged
).
▸ Register this
on a fused location provider (a FusedLocationProviderApi
reference).
We choose to implement the second strategy. TABLE 11.10 shows one of the requestLocationUpdates
methods of the FusedLocationProviderApi
interface. It requests that its LocationListener
parameter provides location updates, via the onLocationChanged
method, as defined by its LocationRequest
parameter. Thus, assuming that we are inside an Activity
class that implements the LocationListener
interface, and that a LocationRequest
named request
has been defined, we can request location updates using the following code sequence:
// we are inside an Activity class that implements LocationListener // thus, this "is a" LocationListener // gac is a GoogleApiClient reference // request is a LocationRequest reference FusedLocationProviderApi flpa = LocationServices.FusedLocationApi; flpa.requestLocationUpdates( gac, request, this );
TABLE 11.11 Selected methods of the LocationRequest
class
Method | Description |
---|---|
LocationRequest setInterval( long ms ) | Sets the interval for location updates in milliseconds. Returns this LocationRequest so method calls can be chained. |
LocationRequest setPriority( int priority ) | Sets priority of this request. The LocationRequest class includes constants (see Table 11.12) that can be used as the argument. Returns this LocationRequest so method calls can be chained. |
LocationRequest setSmallestDisplacement( float meters ) | Sets the minimum distance between consecutive updates. Returns this LocationRequest so method calls can be chained. |
At that point, we will receive updates and the onLocationChanged
method will be called at the frequency specified by the LocationRequest
. Its Location
parameter stores the most recent location, as follows.
public void onLocationChanged( Location location ) { // location is the most recent location }
The LocationRequest
class provides the functionality to define a request for location updates by specifying the frequency of updates, their accuracy, etc.
TABLE 11.11 shows the two most important methods of the LocationRequest
class. We use the setInterval
method to specify the desired frequency, in milliseconds, of location updates. A location update consumes power, and frequent updates can drain the device’s battery. We use the setPriority
method to specify a desired accuracy level, which in turn is a hint at what source to use, GPS or Wi-Fi and cell tower. However, other factors, such as the current location and availability or such sources, as well as the device itself, can impact the accuracy of the location returned. All the set methods of the LocationRequest
class return the LocationRequest
reference that calls them, so that we can chain method calls. If we do not want updates—if we have not moved by a minimum distance—we can use the setSmallestDisplacement
method and specify such minimum distance between two consecutive updates. For example, in a travel app, the user does not need distance updates if he or she is stuck in traffic and is not moving.
The following code sequence shows how to define a LocationRequest
:
LocationRequest request = new LocationRequest( ); request.setInterval( 30000); // 30 seconds interval request.setPriority( LocationRequest.PRIORITY_HIGH_ACCURACY ); request.setSmallestDisplacement(100); // 100 meters minimum
TABLE 11.12 shows the constants of the LocationRequest
class that we can use as the argument of the setPriority
method. The higher the accuracy requested, the higher the battery usage. Without specifically setting the priority by calling setPriority
, the default priority, defined by PRIORITY_BALANCED_POWER_ACCURACY
, is used. If we build a golf app that measures the distance to the pin, we want accuracy to the nearest yard or meter, so we specify the highest possible accuracy. For this travel app, the default accuracy is adequate.
TABLE 11.12 Priority constants of the LocationRequest
class
Constant | Value | Description |
---|---|---|
PRIORITY_HIGH_ACCURACY | 100 | The highest available accuracy. |
PRIORITY_BALANCED_POWER_ACCURACY | 102 | The default value—block level accuracy, around 100 meters. |
PRIORITY_LOW_POWER | 104 | City level accuracy, around 10 kilometers. |
PRIORITY_NO_POWER | 105 | The worst accuracy, requesting no power consumption. |
EXAMPLE 11.12 shows the changes in the MainActivity
class. We only want to set up location updates if we are successfully connected. Thus, we do that inside the onConnected
method (lines 98–108). We create and define a LocationRequest
at lines 100–103. We added the calls to setPriority
and setSmallestDisplacement
in order to illustrate them, but commented them out. Indeed, if we test the app without moving, we do not want to set a minimum distance for location updates. It is actually possible that we get disconnected in the middle of the onConnected
method, in which case the app will crash when we try to set up location updates. Thus, we test that we are connected (line 104) before we set up location updates (line 105). If we lost the connection, we try to establish another connection (line 107).
Inside the onLocationChanged
method (lines 54–59), we call updateTrip
at line 58 in order to update the two TextViews
showing the distance and time left to the destination. For feedback, we output to Logcat information about the accuracy and the timeline of the automatic calls to onLocationChanged
. TABLE 11.13 shows the getAccuracy
and getElapsedRealtimeNanos
methods. The getElapsedRealtimeNanos
method requires API level 17. Thus, we update the build.gradle file accordingly.
If the app is running and goes in the background, we want to stop requesting location updates. When that happens, the onPause
method (lines 92–96) is called automatically. We disable location updates at line 95 by calling the removeLocationUpdates
method (shown in Table 11.10). When the app comes back to the foreground, onStart
is called, reconnects to Google Play services if necessary, and we request location updates again when onConnected
executes.
FIGURE 11.4 shows the Logcat output of the app when running on the author’s tablet. The output shows that the accuracy of the location returned by the GPS can vary from measurement to measurement. In this instance, it varies from 30 meters to 64.5 meters. One nanosecond is equal to 10–9 second. The interval frequency of the measurements is always very close to the 30 seconds specified. It varies between 30.016 seconds (time elapsed between the last and next to last measurements) and 30.034 seconds (time elapsed between the third and fourth measurements). When the app starts, the two TextViews
show 0 mile
and seconds left
. If we enter an address and wait, the distance and time to that location is automatically updated after fewer than 30 seconds without clicking on the Update
button, illustrating that the onLocationChanged
method has been called.
TABLE 11.13 Selected methods of the Location
class
Method | Description |
---|---|
float getAccuracy( ) | Returns the accuracy for this Location in meters. |
long getElapsedRealtimeNanos( ) | Returns the time since the last boot in nanoseconds. |
Accuracy can be device and location dependent too. Further testing on the author’s tablet from his home shows an accuracy varying from 12 meters to 36 meters when setting the priority using PRIORITY_HIGH_ACCURACY
(by un-commenting line 102 in Example 11.12).
The GoogleApiClient
class is the entry point to Google Play services.
If Google Play services are not available, it is possible that they can be made available via user interaction.
The Builder static
inner class of GoogleApiClient
enables us to build a GoogleApiClient
.
We can obtain the current location of the device by calling the lastLocation
method of the FusedLocationProviderApi
interface.
The LocationServices
has a FusedLocationProviderApi static
constant field named FusedLocationApi
.
The getLatitude
and getLongitude
methods of the Location
class return the latitude and longitude of a location.
The distanceTo
method of the Location
class returns the distance, in meters, between the Location
reference calling it and a parameter Location
reference.
If the app accesses Google Play services to retrieve the device’s location, we should add a uses-permission
element in the AndroidManifest.xml file and specify ACCESS_COARSE_LOCATION
or ACCESS_FINE_LOCATION
, two constants of the Manifest.permission
class.
The Geocoder
class provides methods to convert an address into a Location
object (i.e., latitude and longitude) and vice versa.
We can get location updates at a regular interval by implementing the LocationListener
interface. LocationListener
contains one callback method, onLocationChanged
. It takes a Location
parameter that represents the current location of the device.
We use the requestLocationUpdates
method to register a LocationListener
on a FusedLocationProviderApi
, defining various parameters of the updates using a LocationRequest
parameter. Such registration triggers automatic calls to the onLocationChanged
method of LocationListener
.
The most important attributes of a LocationRequest
are the frequency of the updates and the priority, which translates into the accuracy of the locations retrieved.
How can we obtain a GoogleApiClient reference?
Use a constructor of GoogleApiClient
Use the getInstance method of GoogleApiClient
Create a GoogleApiClient.Builder and call the build method
We cannot
What is the name of the FusedLocationProviderApi constant of LocationServices?
Api
FusedLocationApi
FusedApi
Fused
The Location class encapsulates a location on Earth. What method can we use to retrieve its latitude?
latitude
getLat
getLatitude
locationLatitude
The distanceTo method of the Location class returns a distance in
yards
meters
miles
kilometers
What class contains methods to convert an address to a Location and vice versa?
Geocoder
LocationCoder
Mapping
Geography
If we want to get location updates at regular intervals, what interface should we implement?
Listener
UpdateListener
GeoListener
LocationListener
What is the meaning of the Location parameter of the onLocationChanged method of the interface of question 6?
It stores a random location
It stores the most recent location
It stores the next location
It is null
We call the requestLocationUpdates of the FusedLocationProviderApi interface to request regular location updates. Two of its parameters are a GoogleApiClient and a LocationListener. What is the type of the third one?
double
Request
Time
LocationRequest
Declare and instantiate a GoogleApiClient that listens to connection success and failures.
The Location reference myLocation stores a location. Output to Logcat its accuracy.
The String address stores an address. Output its latitude and longitude to Logcat. Use the first Address geocoded for this.
The MyActivity class wants to get location updates. Write its class header.
Code the onLocationChanged method so that we display the latitude and longitude of the current location in a TextView name MyTV.
Build a LocationRequest that can be used to trigger updates every 100 seconds with the highest possible accuracy.
We are coding inside an Activity class that implements LocationListener. We have already instantiated a FusedLocationProviderApi named providerApi, a GoogleClientApi named clientApi, and a LocationRequest named request. Write one statement so that we get location updates as defined by request inside this Activity class.
Expand the app in the chapter by calculating the time left using the speed between the last two location updates rather than 55 miles per hour.
Expand the app in the chapter by calculating the time left using the average speed between the last five location updates rather than 55 miles per hour. If there have not been five location updates yet, use 55 miles per hour.
Write an app that identifies the closest location from where the user is among five locations. The five locations can be hard coded inside the Model of the app.
Write an app that identifies how far the user is from five locations. The five locations can be hard coded inside the Model of the app. As the user moves, the five distances should be updated at regular intervals. The app should let the user decide the frequency of the updates and the accuracy of the locations (priority).
Write an app that enables the user to select a friend in a list, retrieve his or her address, and calculate how far that friend is. The list should be stored either in a file or can be hard coded. Include a Model.
Same as 20 but the list is not hard coded, is persistent and is expandable. The user can add to the list.
Same as 21 but the user can also delete and update a friend’s data from the list.
Write a 1-hole golf app. The app allows the user to enter the location of the middle of the green by simply clicking on a button. That data should be stored on the device. The app allows the user to compute the distance from where the user is to the middle of the green location (previously stored).
Same as 23 but the app is an 18-hole golf app, not a 1-hole golf app.
Write an app that stores a list of locations and descriptions on the device. The user can enter a description for a location (where the user is) and can click on a button to retrieve the current location and write to the device’s storage the description and the location. The app also allows the user to retrieve the list of descriptions and locations and display them.
Write an app that sends an email and includes the latitude and longitude of the user’s location in the body of the email.
Same as 26 but convert the current location to an address and include the current address in the body of the email.
Write an app that helps the user retrieve the parking location of his or her car. When the user parks his or her car, the user clicks on a button to store the car’s location. If the user wants to know where his or her car is, the app displays a map with two circles showing both the car and the user location.
3.142.40.56