diff --git a/docs/html/training/location/activity-recognition.jd b/docs/html/training/location/activity-recognition.jd deleted file mode 100644 index d50064b00d6eb..0000000000000 --- a/docs/html/training/location/activity-recognition.jd +++ /dev/null @@ -1,786 +0,0 @@ -page.title=Recognizing the User's Current Activity - -trainingnavtop=true -@jd:body - -
ActivityRecognition.zip
-- Activity recognition tries to detect the user's current physical activity, such as walking, - driving, or standing still. Requests for updates go through an activity recognition client, - which, while different from the location client used by location or geofencing, follows a - similar pattern. Based on the update interval you choose, Location Services sends out - activity information containing one or more possible activities and the confidence level for - each one. This lesson shows you how to request activity recognition updates from Location - Services. -
-- Requesting activity recognition updates from Location Services is similar to requesting - periodic location updates. You send the request through a client, and Location Services sends - updates back to your app by means of a {@link android.app.PendingIntent}. However, you need to - request a special permission before you request activity updates, and you use a different type - of client to make requests. The following sections show how to request the permission, - connect the client, and request updates. -
-
- An app that wants to get activity recognition updates must have the permission
- {@code com.google.android.gms.permission.ACTIVITY_RECOGNITION}. To request this permission for
- your app, add the following XML element to your manifest as a child element of the
-<manifest>
- element:
-
-<uses-permission - android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/> --
- Activity recognition does not require the permissions - {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or - {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}. -
- -
- Location Services is part of the Google Play services APK. Since it's hard to anticipate the
- state of the user's device, you should always check that the APK is installed before you attempt
- to connect to Location Services. To check that the APK is installed, call
-GooglePlayServicesUtil.isGooglePlayServicesAvailable(),
- which returns one of the
- integer result codes listed in the API reference documentation. If you encounter an error,
- call
-GooglePlayServicesUtil.getErrorDialog()
- to retrieve localized dialog that prompts users to take the correct action, then display
- the dialog in a {@link android.support.v4.app.DialogFragment}. The dialog may allow the
- user to correct the problem, in which case Google Play services may send a result back to your
- activity. To handle this result, override the method
- {@link android.support.v4.app.FragmentActivity#onActivityResult onActivityResult()}
-
-
- Note: To make your app compatible with - platform version 1.6 and later, the activity that displays the - {@link android.support.v4.app.DialogFragment} must subclass - {@link android.support.v4.app.FragmentActivity} instead of {@link android.app.Activity}. Using - {@link android.support.v4.app.FragmentActivity} also allows you to call - {@link android.support.v4.app.FragmentActivity#getSupportFragmentManager - getSupportFragmentManager()} to display the {@link android.support.v4.app.DialogFragment}. -
-- Since you usually need to check for Google Play services in more than one place in your code, - define a method that encapsulates the check, then call the method before each connection - attempt. The following snippet contains all of the code required to check for Google - Play services: -
-
-public class MainActivity extends FragmentActivity {
- ...
- // Global constants
- /*
- * Define a request code to send to Google Play services
- * This code is returned in Activity.onActivityResult
- */
- private final static int
- CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
- ...
- // Define a DialogFragment that displays the error dialog
- public static class ErrorDialogFragment extends DialogFragment {
- // Global field to contain the error dialog
- private Dialog mDialog;
- // Default constructor. Sets the dialog field to null
- public ErrorDialogFragment() {
- super();
- mDialog = null;
- }
- // Set the dialog to display
- public void setDialog(Dialog dialog) {
- mDialog = dialog;
- }
- // Return a Dialog to the DialogFragment.
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return mDialog;
- }
- }
- ...
- /*
- * Handle results returned to the FragmentActivity
- * by Google Play services
- */
- @Override
- protected void onActivityResult(
- int requestCode, int resultCode, Intent data) {
- // Decide what to do based on the original request code
- switch (requestCode) {
- ...
- case CONNECTION_FAILURE_RESOLUTION_REQUEST :
- /*
- * If the result code is Activity.RESULT_OK, try
- * to connect again
- */
- switch (resultCode) {
- case Activity.RESULT_OK :
- /*
- * Try the request again
- */
- ...
- break;
- }
- ...
- }
- ...
- }
- ...
- private boolean servicesConnected() {
- // Check that Google Play services is available
- int resultCode =
- GooglePlayServicesUtil.
- isGooglePlayServicesAvailable(this);
- // If Google Play services is available
- if (ConnectionResult.SUCCESS == resultCode) {
- // In debug mode, log the status
- Log.d("Activity Recognition",
- "Google Play services is available.");
- // Continue
- return true;
- // Google Play services was not available for some reason
- } else {
- // Get the error dialog from Google Play services
- Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
- resultCode,
- this,
- CONNECTION_FAILURE_RESOLUTION_REQUEST);
-
- // If Google Play services can provide an error dialog
- if (errorDialog != null) {
- // Create a new DialogFragment for the error dialog
- ErrorDialogFragment errorFragment =
- new ErrorDialogFragment();
- // Set the dialog in the DialogFragment
- errorFragment.setDialog(errorDialog);
- // Show the error dialog in the DialogFragment
- errorFragment.show(
- getSupportFragmentManager(),
- "Activity Recognition");
- }
- return false;
- }
- }
- ...
-}
-
-- Snippets in the following sections call this method to verify that Google Play services is - available. -
-
- Send the update request from an {@link android.app.Activity} or
- {@link android.support.v4.app.Fragment} that implements the callback methods required by
- Location Services. Making the request is an asynchronous process that starts when you request
- a connection to an activity recognition client. When the client is connected, Location Services
- invokes your implementation of
-onConnected().
- In this method, you can send the update request to Location Services; this request is
- synchronous. Once you've made the request, you can disconnect the client.
-
- This process is described in the following snippets. -
-- Define an {@link android.support.v4.app.FragmentActivity} or - {@link android.support.v4.app.Fragment} that implements the following interfaces: -
-ConnectionCallbacks
- OnConnectionFailedListener
- - For example: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
-}
-
-- Next, define global variables and constants. Define constants for the update interval, - add a variable for the activity recognition client, and another for the - {@link android.app.PendingIntent} that Location Services uses to send updates to your app: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- // Constants that define the activity detection interval
- public static final int MILLISECONDS_PER_SECOND = 1000;
- public static final int DETECTION_INTERVAL_SECONDS = 20;
- public static final int DETECTION_INTERVAL_MILLISECONDS =
- MILLISECONDS_PER_SECOND * DETECTION_INTERVAL_SECONDS;
- ...
- /*
- * Store the PendingIntent used to send activity recognition events
- * back to the app
- */
- private PendingIntent mActivityRecognitionPendingIntent;
- // Store the current activity recognition client
- private ActivityRecognitionClient mActivityRecognitionClient;
- ...
-}
-
-- In {@link android.app.Activity#onCreate onCreate()}, instantiate the activity recognition - client and the {@link android.app.PendingIntent}: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- @Override
- onCreate(Bundle savedInstanceState) {
- ...
- /*
- * Instantiate a new activity recognition client. Since the
- * parent Activity implements the connection listener and
- * connection failure listener, the constructor uses "this"
- * to specify the values of those parameters.
- */
- mActivityRecognitionClient =
- new ActivityRecognitionClient(mContext, this, this);
- /*
- * Create the PendingIntent that Location Services uses
- * to send activity recognition updates back to this app.
- */
- Intent intent = new Intent(
- mContext, ActivityRecognitionIntentService.class);
- /*
- * Return a PendingIntent that starts the IntentService.
- */
- mActivityRecognitionPendingIntent =
- PendingIntent.getService(mContext, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- ...
- }
- ...
-}
-
-- Define a method that requests activity recognition updates. In the method, request a - connection to Location Services. You can call this method from anywhere in your activity; its - purpose is to start the chain of method calls for requesting updates. -
-- To guard against race conditions that might arise if your app tries to start another request - before the first one finishes, define a boolean flag that tracks the state of the current - request. Set the flag to {@code true} when you start a request, and then set it to - {@code false} when the request completes. -
-- The following snippet shows how to start a request for updates: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- // Global constants
- ...
- // Flag that indicates if a request is underway.
- private boolean mInProgress;
- ...
- @Override
- onCreate(Bundle savedInstanceState) {
- ...
- // Start with the request flag set to false
- mInProgress = false;
- ...
- }
- ...
- /**
- * Request activity recognition updates based on the current
- * detection interval.
- *
- */
- public void startUpdates() {
- // Check for Google Play services
-
- if (!servicesConnected()) {
- return;
- }
- // If a request is not already underway
- if (!mInProgress) {
- // Indicate that a request is in progress
- mInProgress = true;
- // Request a connection to Location Services
- mActivityRecognitionClient.connect();
- //
- } else {
- /*
- * A request is already underway. You can handle
- * this situation by disconnecting the client,
- * re-setting the flag, and then re-trying the
- * request.
- */
- }
- }
- ...
-}
-
-
- Implement
-onConnected().
- In this method, request activity recognition updates from Location Services. When Location
- Services finishes connecting to the client and calls
-onConnected(),
- the update request is called immediately:
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- /*
- * Called by Location Services once the location client is connected.
- *
- * Continue by requesting activity updates.
- */
- @Override
- public void onConnected(Bundle dataBundle) {
- /*
- * Request activity recognition updates using the preset
- * detection interval and PendingIntent. This call is
- * synchronous.
- */
- mActivityRecognitionClient.requestActivityUpdates(
- DETECTION_INTERVAL_MILLISECONDS,
- mActivityRecognitionPendingIntent);
- /*
- * Since the preceding call is synchronous, turn off the
- * in progress flag and disconnect the client
- */
- mInProgress = false;
- mActivityRecognitionClient.disconnect();
- }
- ...
-}
-
-
- In some cases, Location Services may disconnect from the activity recognition client before
- you call
-disconnect().
- To handle this situation, implement
-onDisconnected().
- In this method, set the request flag to indicate that a request is not in progress, and
- delete the client:
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- /*
- * Called by Location Services once the activity recognition
- * client is disconnected.
- */
- @Override
- public void onDisconnected() {
- // Turn off the request flag
- mInProgress = false;
- // Delete the client
- mActivityRecognitionClient = null;
- }
- ...
-}
-
-
-- Besides handling the normal callbacks from Location Services, you have to provide a callback - method that Location Services calls if a connection error occurs. This callback method - can re-use the {@link android.support.v4.app.DialogFragment} class that you defined to - handle the check for Google Play services. It can also re-use the override you defined - for {@link android.support.v4.app.FragmentActivity#onActivityResult onActivityResult()} that - receives any Google Play services results that occur when the user interacts with the - error dialog. The following snippet shows you a sample implementation of the callback method: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- // Implementation of OnConnectionFailedListener.onConnectionFailed
- @Override
- public void onConnectionFailed(ConnectionResult connectionResult) {
- // Turn off the request flag
- mInProgress = false;
- /*
- * If the error has a resolution, start a Google Play services
- * activity to resolve it.
- */
- if (connectionResult.hasResolution()) {
- try {
- connectionResult.startResolutionForResult(
- this,
- CONNECTION_FAILURE_RESOLUTION_REQUEST);
- } catch (SendIntentException e) {
- // Log the error
- e.printStackTrace();
- }
- // If no resolution is available, display an error dialog
- } else {
- // Get the error code
- int errorCode = connectionResult.getErrorCode();
- // Get the error dialog from Google Play services
- Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
- errorCode,
- this,
- CONNECTION_FAILURE_RESOLUTION_REQUEST);
- // If Google Play services can provide an error dialog
- if (errorDialog != null) {
- // Create a new DialogFragment for the error dialog
- ErrorDialogFragment errorFragment =
- new ErrorDialogFragment();
- // Set the dialog in the DialogFragment
- errorFragment.setDialog(errorDialog);
- // Show the error dialog in the DialogFragment
- errorFragment.show(
- getSupportFragmentManager(),
- "Activity Recognition");
- }
- }
- ...
- }
- ...
-}
-
-
-
- To handle the {@link android.content.Intent} that Location Services sends for each update
- interval, define an {@link android.app.IntentService} and its required method
- {@link android.app.IntentService#onHandleIntent onHandleIntent()}. Location Services
- sends out activity recognition updates as {@link android.content.Intent} objects, using the
- the {@link android.app.PendingIntent} you provided when you called
-requestActivityUpdates().
- Since you provided an explicit intent for the {@link android.app.PendingIntent}, the only
- component that receives the intent is the {@link android.app.IntentService} you're defining.
-
- The following snippets demonstrate how to examine the data in an activity recognition - update. -
-- Start by defining the class and the required method - {@link android.app.IntentService#onHandleIntent onHandleIntent()}: -
-
-/**
- * Service that receives ActivityRecognition updates. It receives
- * updates in the background, even if the main Activity is not visible.
- */
-public class ActivityRecognitionIntentService extends IntentService {
- ...
- /**
- * Called when a new activity detection update is available.
- */
- @Override
- protected void onHandleIntent(Intent intent) {
- ...
- }
- ...
-}
-
-- Next, examine the data in the intent. From the update, you can get a list of possible activities - and the probability of each one. The following snippet shows how to get the most probable - activity, the confidence level for the activity (the probability that this is the actual - activity), and its type: -
-
-public class ActivityRecognitionIntentService extends IntentService {
- ...
- @Override
- protected void onHandleIntent(Intent intent) {
- ...
- // If the incoming intent contains an update
- if (ActivityRecognitionResult.hasResult(intent)) {
- // Get the update
- ActivityRecognitionResult result =
- ActivityRecognitionResult.extractResult(intent);
- // Get the most probable activity
- DetectedActivity mostProbableActivity =
- result.getMostProbableActivity();
- /*
- * Get the probability that this activity is the
- * the user's actual activity
- */
- int confidence = mostProbableActivity.getConfidence();
- /*
- * Get an integer describing the type of activity
- */
- int activityType = mostProbableActivity.getType();
- String activityName = getNameFromType(activityType);
- /*
- * At this point, you have retrieved all the information
- * for the current update. You can display this
- * information to the user in a notification, or
- * send it to an Activity or Service in a broadcast
- * Intent.
- */
- ...
- } else {
- /*
- * This implementation ignores intents that don't contain
- * an activity update. If you wish, you can report them as
- * errors.
- */
- }
- ...
- }
- ...
-}
-
-- The method {@code getNameFromType()} converts activity types into descriptive - strings. In a production app, you should retrieve the strings from resources instead of - using fixed values: -
-
-public class ActivityRecognitionIntentService extends IntentService {
- ...
- /**
- * Map detected activity types to strings
- *@param activityType The detected activity type
- *@return A user-readable name for the type
- */
- private String getNameFromType(int activityType) {
- switch(activityType) {
- case DetectedActivity.IN_VEHICLE:
- return "in_vehicle";
- case DetectedActivity.ON_BICYCLE:
- return "on_bicycle";
- case DetectedActivity.ON_FOOT:
- return "on_foot";
- case DetectedActivity.STILL:
- return "still";
- case DetectedActivity.UNKNOWN:
- return "unknown";
- case DetectedActivity.TILTING:
- return "tilting";
- }
- return "unknown";
- }
- ...
-}
-
-
-
- To identify the {@link android.app.IntentService} to the system, add a
- <service>
- element to the app manifest. For example:
-
-<service - android:name="com.example.android.location.ActivityRecognitionIntentService" - android:label="@string/app_name" - android:exported="false"> -</service> --
- Notice that you don't have to specify intent filters for the service, because it only receives - explicit intents. How the incoming activity update intents are created is described in the - section Define the Activity or Fragment. -
-
- To stop activity recognition updates, use the same pattern you used to request updates,
- but call
-removeActivityUpdates()
- instead of requestActivityUpdates().
-
-
- Since removing updates uses some of the methods you use to add updates, start by defining - request types for the two operations: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- public enum REQUEST_TYPE {START, STOP}
- private REQUEST_TYPE mRequestType;
- ...
-}
-
-- Modify the code that starts activity recognition so that it uses the {@code START} - request type: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- public void startUpdates() {
- // Set the request type to START
- mRequestType = REQUEST_TYPE.START;
- /*
- * Test for Google Play services after setting the request type.
- * If Google Play services isn't present, the proper request type
- * can be restarted.
- */
- if (!servicesConnected()) {
- return;
- }
- ...
- }
- ...
- public void onConnected(Bundle dataBundle) {
- switch (mRequestType) {
- case START :
- /*
- * Request activity recognition updates using the
- * preset detection interval and PendingIntent.
- * This call is synchronous.
- */
- mActivityRecognitionClient.requestActivityUpdates(
- DETECTION_INTERVAL_MILLISECONDS,
- mActivityRecognitionPendingIntent);
- break;
- ...
- /*
- * An enum was added to the definition of REQUEST_TYPE,
- * but it doesn't match a known case. Throw an exception.
- */
- default :
- throw new Exception("Unknown request type in onConnected().");
- break;
- }
- ...
- }
- ...
-}
-
-- Define a method that requests a stop to activity recognition updates. In the method, - set the request type and then request a connection to Location Services. You can call this - method from anywhere in your activity; its purpose is to start the chain of method calls that - stop activity updates: -
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- /**
- * Turn off activity recognition updates
- *
- */
- public void stopUpdates() {
- // Set the request type to STOP
- mRequestType = REQUEST_TYPE.STOP;
- /*
- * Test for Google Play services after setting the request type.
- * If Google Play services isn't present, the request can be
- * restarted.
- */
- if (!servicesConnected()) {
- return;
- }
- // If a request is not already underway
- if (!mInProgress) {
- // Indicate that a request is in progress
- mInProgress = true;
- // Request a connection to Location Services
- mActivityRecognitionClient.connect();
- //
- } else {
- /*
- * A request is already underway. You can handle
- * this situation by disconnecting the client,
- * re-setting the flag, and then re-trying the
- * request.
- */
- }
- ...
- }
- ...
-}
-
-
- In
-onConnected(),
- if the request type is STOP, call
-removeActivityUpdates().
- Pass the {@link android.app.PendingIntent} you used to start updates as the parameter to
-removeActivityUpdates():
-
-public class MainActivity extends FragmentActivity implements
- ConnectionCallbacks, OnConnectionFailedListener {
- ...
- public void onConnected(Bundle dataBundle) {
- switch (mRequestType) {
- ...
- case STOP :
- mActivityRecognitionClient.removeActivityUpdates(
- mActivityRecognitionPendingIntent);
- break;
- ...
- }
- ...
- }
- ...
-}
-
-
- You do not have to modify your implementation of
-onDisconnected()
- or
-onConnectionFailed(),
- because these methods do not depend on the request type.
-
- You now have the basic structure of an app that implements activity recognition. You can combine - activity recognition with other location-aware features, such as periodic location updates or - geofencing, which are described in other lessons in this class. -
diff --git a/docs/html/training/location/location-testing.jd b/docs/html/training/location/location-testing.jd deleted file mode 100644 index 8f73d515db878..0000000000000 --- a/docs/html/training/location/location-testing.jd +++ /dev/null @@ -1,371 +0,0 @@ -page.title=Testing Using Mock Locations - -trainingnavtop=true -@jd:body - -LocationProvider.zip
-- To test a location-aware app that uses Location Services, you don't need to move your device - from place to place to generate location data. Instead, you can put Location Services into mock - mode. In this mode, you can send mock {@link android.location.Location} objects to - Location Services, which then sends them to location clients. In mock mode, Location Services - also uses mock {@link android.location.Location} objects to trigger geofences. -
-- Using mock locations has several advantages: -
-- The best way to use mock locations is to send them from a separate mock location provider app. - This lesson includes a provider app that you can download and use to test your own software. - Modify the provider app as necessary to suit your own needs. Some ideas for providing test data - to the app are listed in the section Managing test data. -
-- The remainder of this lesson shows you how to turn on mock mode and use a location client to - send mock locations to Location Services. -
-- Note: Mock locations have no effect on the activity recognition algorithm used - by Location Services. To learn more about activity recognition, see the lesson - Recognizing the User's Current Activity. -
- -- To send mock locations to Location Services in mock mode, a test app must request the permission - android.Manifest.permission#ACCESS_MOCK_LOCATION. In addition, you must enable mock - locations on the test device using the option Enable mock locations. To learn how to - enable mock locations on the device, see - Setting up a Device for Development. -
-
- To turn on mock mode in Location Services, start by connecting a location client to Location
- Services, as described in the lesson
- Retrieving the Current Location.
- Next, call the method
-LocationClient.setMockMode(true).
- Once you call this method, Location Services turns off its internal location providers and only
- sends out the mock locations you provide it. The following snippet shows you how to call
-LocationClient.setMockMode(true):
-
- // Define a LocationClient object - public LocationClient mLocationClient; - ... - // Connect to Location Services - mLocationClient.connect(); - ... - // When the location client is connected, set mock mode - mLocationClinet.setMockMode(true); --
- Once you have connected the location client to Location Services, you must keep it connected
- until you finish sending out mock locations. Once you call
-LocationClient.disconnect(),
- Location Services returns to using its internal location providers. To turn off mock mode while
- the location client is connected, call
-LocationClient.setMockMode(false).
-
- Once you have set mock mode, you can create mock {@link android.location.Location} objects and - send them to Location Services. In turn, Location Services sends these mock - {@link android.location.Location} objects to connected location clients. Location Services also - uses the mock {@link android.location.Location} objects to control geofence triggering. -
-- To create a new mock {@link android.location.Location}, create a new - {@link android.location.Location} object using your test data. Always set the provider - value to {@code flp}, which is the code that Location Services puts into the - {@link android.location.Location} objects it sends out. The following snippet shows you how - to create a new mock {@link android.location.Location}: -
-
- private static final String PROVIDER = "flp";
- private static final double LAT = 37.377166;
- private static final double LNG = -122.086966;
- private static final float ACCURACY = 3.0f;
- ...
- /*
- * From input arguments, create a single Location with provider set to
- * "flp"
- */
- public Location createLocation(double lat, double lng, float accuracy) {
- // Create a new Location
- Location newLocation = new Location(PROVIDER);
- newLocation.setLatitude(lat);
- newLocation.setLongitude(lng);
- newLocation.setAccuracy(accuracy);
- return newLocation;
- }
- ...
- // Example of creating a new Location from test data
- Location testLocation = createLocation(LAT, LNG, ACCURACY);
-
-
- In mock mode, to send a mock location to Location Services call the method
-LocationClient.setMockLocation().
- For example:
-
- mLocationClient.setMockLocation(testLocation); --
- Location Services sets this mock location as the current location, and this location is sent - out as the next location update. If this new mock location moves across a geofence boundary, - Location Services triggers the geofence. -
- -- This section contains a brief overview of the mock location provider sample app - (available for download above) and gives you directions for testing an app using the sample app. -
-- The mock location provider app included with this lesson sends mock - {@link android.location.Location} objects to Location Services from a background thread running - in a started {@link android.app.Service}. By using a started service, the provider app is able - to keep running even if the app's main {@link android.app.Activity} is destroyed because of - a configuration change or other system event. By using a background thread, the service is able - to perform a long-running test without blocking the UI thread. -
-- The {@link android.app.Activity} that starts when you run the provider app allows you to - send test parameters to the {@link android.app.Service} and control the type of test you want. - You have the following options: -
-- Besides the options, the provider app has two status displays: -
-- While the started {@link android.app.Service} is running, it also posts notifications with the - testing status. These notifications allow you to see status updates even if the app is not in - the foreground. When you click on a notification, the main {@link android.app.Activity} of the - provider app returns to the foreground. -
-- To test mock location data coming from the mock location provider app: -
-- The following sections contain tips for creating mock location data and using the data with a - mock location provider app. -
-- Each location provider that contributes to the fused location sent out by Location Services has - its own minimum update cycle. For example, the GPS provider can't send a new location more often - than once per second, and the Wi-Fi provider can't send a new location more often than once - every five seconds. These cycle times are handled automatically for real locations, but you - should account for them when you send mock locations. For example, you shouldn't send a new mock - location more than once per second. If you're testing indoor locations, which rely heavily on - the Wi-Fi provider, then you should consider using a send interval of five seconds. -
-- To simulate the speed of an actual device, shorten or lengthen the distance between two - successive locations. For example, changing the location by 88 feet every second simulates - car travel, because this change works out to 60 miles an hour. In comparison, changing the - location by 1.5 feet every second simulates brisk walking, because this change works out to - 3 miles per hour. -
-- By searching the web, you can find a variety of small programs that calculate a new set of - latitude and longitude coordinates from a starting location and a distance, as well as - references to formulas for calculating the distance between two points based on their latitude - and longitude. In addition, the {@link android.location.Location} class offers two methods for - calculating the distance between points: -
-- When you test an app that uses geofence detection, use test data that reflects different modes - of travel, including walking, cycling, driving, and traveling by train. For a slow mode of - travel, make small changes in position between points. Conversely, for a fast mode of travel, - make a large change in position between points. -
-- The mock location provider app included with this lesson contains test latitude, longitude, - and accuracy values in the form of constants. You may want to consider other ways of organizing - data as well: -
-