Merge "Deleting pages so redirects work on DevSite. b/28670825" into mnc-mr-docs
am: 965f4bf1ef
* commit '965f4bf1ef2e8958ec9a53bab00be919a49bc8c2':
Deleting pages so redirects work on DevSite. b/28670825
Change-Id: If2a4f83aadd1994c86c34a9443cf50af96b633d6
This commit is contained in:
@@ -1,786 +0,0 @@
|
||||
page.title=Recognizing the User's Current Activity
|
||||
|
||||
trainingnavtop=true
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>This lesson teaches you to</h2>
|
||||
<ol>
|
||||
<li><a href="#RequestUpdates">Request Activity Recognition Updates</a></li>
|
||||
<li><a href="#HandleUpdates">Handle Activity Updates</a>
|
||||
<li><a href="#RemoveUpdates">Stop Activity Recognition Updates</a>
|
||||
</ol>
|
||||
<h2>You should also read</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="receive-location-updates.html">Receiving Location Updates</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Try it out</h2>
|
||||
|
||||
<div class="download-box">
|
||||
<a href="http://developer.android.com/shareables/training/ActivityRecognition.zip" class="button">Download the sample</a>
|
||||
<p class="filename">ActivityRecognition.zip</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h2 id="RequestUpdates">Request Activity Recognition Updates</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h3>Request permission to receive updates</h3>
|
||||
<p>
|
||||
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
|
||||
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code>
|
||||
element:
|
||||
</p>
|
||||
<pre>
|
||||
<uses-permission
|
||||
android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
|
||||
</pre>
|
||||
<p>
|
||||
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}.
|
||||
</p>
|
||||
<!-- Check for Google Play services -->
|
||||
<h3>Check for Google Play Services</h3>
|
||||
<p>
|
||||
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
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#isGooglePlayServicesAvailable(android.content.Context)">GooglePlayServicesUtil.isGooglePlayServicesAvailable()</a></code>,
|
||||
which returns one of the
|
||||
integer result codes listed in the API reference documentation. If you encounter an error,
|
||||
call
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesUtil.html#getErrorDialog(int, android.app.Activity, int)">GooglePlayServicesUtil.getErrorDialog()</a></code>
|
||||
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()}
|
||||
|
||||
</p>
|
||||
<p class="note">
|
||||
<strong>Note:</strong> 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}.
|
||||
</p>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Snippets in the following sections call this method to verify that Google Play services is
|
||||
available.
|
||||
</p>
|
||||
<h3>Send the activity update request</h3>
|
||||
<p>
|
||||
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
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">onConnected()</a></code>.
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
This process is described in the following snippets.
|
||||
</p>
|
||||
<h4 id="DefineActivity">Define the Activity or Fragment</h4>
|
||||
<p>
|
||||
Define an {@link android.support.v4.app.FragmentActivity} or
|
||||
{@link android.support.v4.app.Fragment} that implements the following interfaces:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html">ConnectionCallbacks</a></code>
|
||||
</dt>
|
||||
<dd>
|
||||
Specifies methods that Location Services calls when the client is connected or
|
||||
disconnected.
|
||||
</dd>
|
||||
<dt>
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html">OnConnectionFailedListener</a></code>
|
||||
</dt>
|
||||
<dd>
|
||||
Specifies a method that Location Services calls if an error occurs while attempting to
|
||||
connect the client.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
For example:
|
||||
</p>
|
||||
<pre>
|
||||
public class MainActivity extends FragmentActivity implements
|
||||
ConnectionCallbacks, OnConnectionFailedListener {
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<pre>
|
||||
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;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
In {@link android.app.Activity#onCreate onCreate()}, instantiate the activity recognition
|
||||
client and the {@link android.app.PendingIntent}:
|
||||
</p>
|
||||
<pre>
|
||||
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);
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<h4>Start the request process</h4>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
The following snippet shows how to start a request for updates:
|
||||
</p>
|
||||
<pre>
|
||||
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.
|
||||
*/
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Implement
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">onConnected()</a></code>.
|
||||
In this method, request activity recognition updates from Location Services. When Location
|
||||
Services finishes connecting to the client and calls
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">onConnected()</a></code>,
|
||||
the update request is called immediately:
|
||||
</p>
|
||||
<pre>
|
||||
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();
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<h3>Handle disconnections</h3>
|
||||
<p>
|
||||
In some cases, Location Services may disconnect from the activity recognition client before
|
||||
you call
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/ActivityRecognitionClient.html#disconnect()">disconnect()</a></code>.
|
||||
To handle this situation, implement <code>
|
||||
<a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onDisconnected()">onDisconnected()</a></code>.
|
||||
In this method, set the request flag to indicate that a request is not in progress, and
|
||||
delete the client:
|
||||
</p>
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<!-- Handle connection errors -->
|
||||
<h3>Handle connection errors</h3>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<pre>
|
||||
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");
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<!-- Create Intent Service -->
|
||||
<h2 id="HandleUpdates">Handle Activity Updates</h2>
|
||||
<p>
|
||||
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
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/ActivityRecognitionClient.html#requestActivityUpdates(long, android.app.PendingIntent)">requestActivityUpdates()</a></code>.
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
The following snippets demonstrate how to examine the data in an activity recognition
|
||||
update.
|
||||
</p>
|
||||
<h3>Define an IntentService</h3>
|
||||
<p>
|
||||
Start by defining the class and the required method
|
||||
{@link android.app.IntentService#onHandleIntent onHandleIntent()}:
|
||||
</p>
|
||||
<pre>
|
||||
/**
|
||||
* 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) {
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<pre>
|
||||
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.
|
||||
*/
|
||||
}
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<pre>
|
||||
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";
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<!-- Define IntentService -->
|
||||
<h3>Specify the IntentService in the manifest</h3>
|
||||
<p>
|
||||
To identify the {@link android.app.IntentService} to the system, add a
|
||||
<code><a href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code>
|
||||
element to the app manifest. For example:
|
||||
</p>
|
||||
<pre>
|
||||
<service
|
||||
android:name="com.example.android.location.ActivityRecognitionIntentService"
|
||||
android:label="@string/app_name"
|
||||
android:exported="false">
|
||||
</service>
|
||||
</pre>
|
||||
<p>
|
||||
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 <a id="DefineActivity">Define the Activity or Fragment</a>.
|
||||
</p>
|
||||
<h2 id="RemoveUpdates">Stop Activity Recognition Updates</h2>
|
||||
<p>
|
||||
To stop activity recognition updates, use the same pattern you used to request updates,
|
||||
but call <code>
|
||||
<a href="{@docRoot}reference/com/google/android/gms/location/ActivityRecognitionClient.html#removeActivityUpdates(android.app.PendingIntent)">removeActivityUpdates()</a></code>
|
||||
instead of <code><a href="{@docRoot}reference/com/google/android/gms/location/ActivityRecognitionClient.html#requestActivityUpdates(long, android.app.PendingIntent)">requestActivityUpdates()</a></code>.
|
||||
</p>
|
||||
<p>
|
||||
<p>
|
||||
Since removing updates uses some of the methods you use to add updates, start by defining
|
||||
request types for the two operations:
|
||||
</p>
|
||||
<pre>
|
||||
public class MainActivity extends FragmentActivity implements
|
||||
ConnectionCallbacks, OnConnectionFailedListener {
|
||||
...
|
||||
public enum REQUEST_TYPE {START, STOP}
|
||||
private REQUEST_TYPE mRequestType;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Modify the code that starts activity recognition so that it uses the {@code START}
|
||||
request type:
|
||||
</p>
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<h3>Start the process</h3>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<pre>
|
||||
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.
|
||||
*/
|
||||
}
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
In
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">onConnected()</a></code>,
|
||||
if the request type is STOP, call
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/ActivityRecognitionClient.html#removeActivityUpdates(android.app.PendingIntent)">removeActivityUpdates()</a></code>.
|
||||
Pass the {@link android.app.PendingIntent} you used to start updates as the parameter to
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/ActivityRecognitionClient.html#removeActivityUpdates(android.app.PendingIntent)">removeActivityUpdates()</a></code>:
|
||||
</p>
|
||||
<pre>
|
||||
public class MainActivity extends FragmentActivity implements
|
||||
ConnectionCallbacks, OnConnectionFailedListener {
|
||||
...
|
||||
public void onConnected(Bundle dataBundle) {
|
||||
switch (mRequestType) {
|
||||
...
|
||||
case STOP :
|
||||
mActivityRecognitionClient.removeActivityUpdates(
|
||||
mActivityRecognitionPendingIntent);
|
||||
break;
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
You do not have to modify your implementation of
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onDisconnected()">onDisconnected()</a></code>
|
||||
or
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html#onConnectionFailed(com.google.android.gms.common.ConnectionResult)">onConnectionFailed()</a></code>,
|
||||
because these methods do not depend on the request type.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
@@ -1,371 +0,0 @@
|
||||
page.title=Testing Using Mock Locations
|
||||
|
||||
trainingnavtop=true
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
|
||||
<!-- table of contents -->
|
||||
<h2>This lesson teaches you to</h2>
|
||||
<ol>
|
||||
<li><a href="#TurnOnMockMode">Turn On Mock Mode</a></li>
|
||||
<li><a href="#SendMockLocations">Send Mock Locations</a></li>
|
||||
<li><a href="#RunProvider">Run the Mock Location Provider App</a></li>
|
||||
<li><a href="#TestingTips">Testing Tips</a>
|
||||
</ol>
|
||||
|
||||
<h2>You should also read</h2>
|
||||
<ul>
|
||||
<li><a href="receive-location-updates.html">Receiving Location Updates</a></li>
|
||||
<li><a href="geofencing.html">Creating and Monitoring Geofences</a></li>
|
||||
<li><a href="{@docRoot}guide/components/services.html">Services</a></li>
|
||||
<li><a href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threads</a>
|
||||
</ul>
|
||||
|
||||
<h2>Example Test App</h2>
|
||||
|
||||
<div class="download-box">
|
||||
<a href="http://developer.android.com/shareables/training/LocationProvider.zip" class="button"
|
||||
>Download the sample</a>
|
||||
<p class="filename">LocationProvider.zip</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
Using mock locations has several advantages:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Mock locations allow you to create specific mock data, instead of trying to approximate
|
||||
data by moving an actual device.
|
||||
</li>
|
||||
<li>
|
||||
Since mock locations come from Location Services, they test every part of your
|
||||
location-handling code. In addition, since you can send the mock data from outside your
|
||||
production app, you don't have to disable or remove test code before you publish.
|
||||
</li>
|
||||
<li>
|
||||
Since you don't have to generate test locations by moving a device, you can test an app
|
||||
using the emulator.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
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 <a href="#TestData">Managing test data</a>.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p class="note">
|
||||
<strong>Note:</strong> Mock locations have no effect on the activity recognition algorithm used
|
||||
by Location Services. To learn more about activity recognition, see the lesson
|
||||
<a href="activity-recognition.html">Recognizing the User's Current Activity</a>.
|
||||
</p>
|
||||
<!--
|
||||
Create a Test App
|
||||
-->
|
||||
<h2 id="TurnOnMockMode">Turn On Mock Mode</h2>
|
||||
<p>
|
||||
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 <b>Enable mock locations</b>. To learn how to
|
||||
enable mock locations on the device, see
|
||||
<a href="{@docRoot}tools/device.html#setting-up">Setting up a Device for Development</a>.
|
||||
</p>
|
||||
<p>
|
||||
To turn on mock mode in Location Services, start by connecting a location client to Location
|
||||
Services, as described in the lesson
|
||||
<a href="retrieve-current.html">Retrieving the Current Location</a>.
|
||||
Next, call the method
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#setMockMode(boolean)">LocationClient.setMockMode(true)</a></code>.
|
||||
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
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#setMockMode(boolean)">LocationClient.setMockMode(true)</a></code>:
|
||||
</p>
|
||||
<pre>
|
||||
// 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);
|
||||
</pre>
|
||||
<p>
|
||||
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
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#disconnect()">LocationClient.disconnect()</a></code>,
|
||||
Location Services returns to using its internal location providers. To turn off mock mode while
|
||||
the location client is connected, call
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#setMockMode(boolean)">LocationClient.setMockMode(false)</a></code>.
|
||||
</p>
|
||||
<h2 id="SendMockLocations">Send Mock Locations</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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}:
|
||||
</p>
|
||||
<pre>
|
||||
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);
|
||||
</pre>
|
||||
<p>
|
||||
In mock mode, to send a mock location to Location Services call the method
|
||||
<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#setMockLocation(android.location.Location)">LocationClient.setMockLocation()</a></code>.
|
||||
For example:
|
||||
</p>
|
||||
<pre>
|
||||
mLocationClient.setMockLocation(testLocation);
|
||||
</pre>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<!--
|
||||
Run the Mock Location Provider
|
||||
-->
|
||||
<h2 id="RunProvider">Run the Mock Location Provider App</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h3>Overview</h3>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
Pause before test
|
||||
</dt>
|
||||
<dd>
|
||||
The number of seconds to wait before the provider app starts sending test data to Location
|
||||
Services. This interval allows you to switch from the provider app to the app under test
|
||||
before the testing actually starts.
|
||||
</dd>
|
||||
<dt>
|
||||
Send interval
|
||||
</dt>
|
||||
<dd>
|
||||
The number of seconds that the provider app waits before it sends another mock location to
|
||||
Location Services. See the section <a href="#TestingTips">Testing Tips</a> to learn more
|
||||
about setting the send interval.
|
||||
</dd>
|
||||
<dt>
|
||||
Run once
|
||||
</dt>
|
||||
<dd>
|
||||
Switch from normal mode to mock mode, run through the test data once, switch back to
|
||||
normal mode, and then kill the {@link android.app.Service}.
|
||||
</dd>
|
||||
<dt>
|
||||
Run continuously
|
||||
</dt>
|
||||
<dd>
|
||||
Switch from normal mode to mock mode, then run through the test data indefinitely. The
|
||||
background thread and the started {@link android.app.Service} continue to run, even if the
|
||||
main {@link android.app.Activity} is destroyed.
|
||||
</dd>
|
||||
<dt>
|
||||
Stop test
|
||||
</dt>
|
||||
<dd>
|
||||
If a continuous test is in progress, stop it; otherwise, return a warning message. The
|
||||
started {@link android.app.Service} switches from mock mode to normal mode and then
|
||||
stops itself. This also stops the background thread.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
Besides the options, the provider app has two status displays:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
App status
|
||||
</dt>
|
||||
<dd>
|
||||
Displays messages related to the lifecycle of the provider app.
|
||||
</dd>
|
||||
<dt>
|
||||
Connection status
|
||||
</dt>
|
||||
<dd>
|
||||
Displays messages related to the state of the location client connection.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h3>Test using the mock location provider app</h3>
|
||||
<p>
|
||||
To test mock location data coming from the mock location provider app:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Install the mock location provider app on a device that has Google Play services installed.
|
||||
Location Services is part of Google Play services.
|
||||
</li>
|
||||
<li>
|
||||
On the device, enable mock locations. To learn how to do this, see the topic
|
||||
<a href="{@docRoot}tools/device.html#setting-up">Setting up a Device for Development</a>.
|
||||
</li>
|
||||
<li>
|
||||
Start the provider app from the Launcher, then choose the options you want from the main
|
||||
screen.
|
||||
</li>
|
||||
<li>
|
||||
Unless you've removed the pause interval feature, the mock location provider app
|
||||
pauses for a few seconds, and then starts sending mock location data to Location
|
||||
Services.
|
||||
</li>
|
||||
<li>
|
||||
Run the app you want to test. While the mock location provider app is running, the app
|
||||
you're testing receives mock locations instead of real locations.
|
||||
</li>
|
||||
<li>
|
||||
If the provider app is in the midst of a continuous test, you can switch back to real
|
||||
locations by clicking <b>Stop test</b>. This forces the started {@link android.app.Service}
|
||||
to turn off mock mode and then stop itself. When the service stops itself, the background
|
||||
thread is also destroyed.
|
||||
</li>
|
||||
|
||||
</ol>
|
||||
<h2 id="TestingTips">Testing Tips</h2>
|
||||
<p>
|
||||
The following sections contain tips for creating mock location data and using the data with a
|
||||
mock location provider app.
|
||||
</p>
|
||||
<h3>Choosing a send interval</h3>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h3>Simulating speed</h3>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h3>Calculating location data</h3>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
{@link android.location.Location#distanceBetween distanceBetween()}
|
||||
</dt>
|
||||
<dd>
|
||||
A static method that calculates the distance between two points specified by latitude and
|
||||
longitude.
|
||||
</dd>
|
||||
<dt>
|
||||
{@link android.location.Location#distanceTo distanceTo()}
|
||||
</dt>
|
||||
<dd>
|
||||
For a given {@link android.location.Location}, returns the distance to another
|
||||
{@link android.location.Location}.
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Geofence testing</h3>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<h3 id="TestData">Managing test data</h3>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
XML
|
||||
</dt>
|
||||
<dd>
|
||||
Store location data in XML files that are including in the provider app. By separating the
|
||||
data from the code, you facilitate changes to the data.
|
||||
</dd>
|
||||
<dt>
|
||||
Server download
|
||||
</dt>
|
||||
<dd>
|
||||
Store location data on a server and then have the provider app download it. Since the data
|
||||
is completely separate from the app, you can change the data without having to rebuild the
|
||||
app. You can also change the data on the server and have the changes reflected immediately
|
||||
in the mock locations you're testing.
|
||||
</dd>
|
||||
<dt>
|
||||
Recorded data
|
||||
</dt>
|
||||
<dd>
|
||||
Instead of making up test data, write a utility app that records location data as you move
|
||||
the device. Use the recorded data as your test data, or use the data to guide you in
|
||||
developing test data. For example, record locations as you walk with a device, and then
|
||||
create mock locations that have an appropriate change in latitude and longitude over
|
||||
time.
|
||||
</dd>
|
||||
</dl>
|
||||
Reference in New Issue
Block a user