Reworking geofencing training to new API and sample.

Change-Id: Ibc9e2561cd93e73eab87a78f4aabe64ae9c8a0b3
diff --git a/docs/html/images/training/geofence.png b/docs/html/images/training/geofence.png
new file mode 100644
index 0000000..2d5d3aa
--- /dev/null
+++ b/docs/html/images/training/geofence.png
Binary files differ
diff --git a/docs/html/images/training/geofence@2x.png b/docs/html/images/training/geofence@2x.png
new file mode 100644
index 0000000..2f83105
--- /dev/null
+++ b/docs/html/images/training/geofence@2x.png
Binary files differ
diff --git a/docs/html/training/location/geofencing.jd b/docs/html/training/location/geofencing.jd
index 748b6ec..59fc4c6 100644
--- a/docs/html/training/location/geofencing.jd
+++ b/docs/html/training/location/geofencing.jd
@@ -9,9 +9,11 @@
 
 <h2>This lesson teaches you to</h2>
 <ol>
-    <li><a href="#RequestGeofences">Request Geofence Monitoring</a></li>
+    <li><a href="#RequestGeofences">Set up for Geofence Monitoring</a></li>
+    <li><a href="#CreateAdd">Create and Add Geofences</a></li>
     <li><a href="#HandleGeofenceTransitions">Handle Geofence Transitions</a></li>
     <li><a href="#StopGeofenceMonitoring">Stop Geofence Monitoring</a></li>
+
 </ol>
 
 <h2>You should also read</h2>
@@ -23,577 +25,148 @@
 
 <h2>Try it out</h2>
 
-<div class="download-box">
-  <a href="http://developer.android.com/shareables/training/GeofenceDetection.zip" class="button">Download the sample</a>
-  <p class="filename">GeofenceDetection.zip</p>
-</div>
+   <ul>
+      <li>
+        <a href="https://github.com/googlesamples/android-play-location/tree/master/Geofencing"
+        class="external-link">Geofencing</a>
+      </li>
+    </ul>
 
 </div>
 </div>
 <p>
-    Geofencing combines awareness of the user's current location with awareness of nearby
-    features, defined as the user's proximity to locations that may be of interest. To mark a
+    Geofencing combines awareness of the user's current location with awareness of the user's
+    proximity to locations that may be of interest. To mark a
     location of interest, you specify its latitude and longitude. To adjust the proximity for the
-    location, you add a radius. The latitude, longitude, and radius define a geofence.
-    You can have multiple active geofences at one time.
+    location, you add a radius. The latitude, longitude, and radius define a geofence, creating a
+    circular area, or fence, around the location of interest.
 </p>
 <p>
-    Location Services treats a geofences as an area rather than as a points and proximity. This
-    allows it to detect when the user enters or exits a geofence. For each geofence, you can ask
-    Location Services to send you entrance events or exit events or both. You can also limit the
-    duration of a geofence by specifying an expiration duration in milliseconds. After the geofence
-    expires, Location Services automatically removes it.
+    You can have multiple active geofences, with a limit of 100 per device user. For each geofence,
+    you can ask Location Services to send you entrance and exit events, or you can specify a
+    duration within the geofence area to wait, or <em>dwell</em>, before triggering an event. You
+    can limit the duration of any geofence by specifying an expiration duration in milliseconds.
+    After the geofence expires, Location Services automatically removes it.
 </p>
-<!--
-    Send geofences to Location Services
- -->
-<h2 id="RequestGeofences">Request Geofence Monitoring</h2>
+
+<img src="{@docRoot}images/training/geofence@2x.png"
+srcset="{@docRoot}images/training/geofence.png 1x, {@docRoot}images/training/geofence@2x.png 2x" alt=""
+  width="400" height="400"/>
+<p>
+    This lesson shows you how to add and remove geofences, and then listen for geofence transitions
+    using an {@link android.app.IntentService}.</p>
+
+<h2 id="RequestGeofences">Set up for Geofence Monitoring</h2>
 <p>
     The first step in requesting geofence monitoring is to request the necessary permission.
     To use geofencing, your app must request
     {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}. To request this
     permission, add the following element as a child element of the
 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
-    element:
+    element in your app manifest:
 </p>
 <pre>
 &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
 </pre>
-<!-- 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:
+    If you want to use an {@link android.app.IntentService} to listen for geofence transitions,
+    add an element specifying the service name. This element must be
+    a child of the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">
+    &lt;application&gt;</a></code> element:
+</p>
+
+<pre>
+&lt;application
+   android:allowBackup=&quot;true&quot;&gt;
+   ...
+   &lt;service android:name=".GeofenceTransitionsIntentService"/&gt;
+&lt;application/&gt;
+</pre>
+
+<p>To access the location APIs, you need to create an instance of the
+  Google Play services API client. To learn how to connect your client, see
+  <a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
+  to Google Play Services</a>.</p>
+
+<h2 id="CreateAdd">Create and Add Geofences</h2>
+
+<p>Your app needs to create and add geofences using the location API's builder class for
+ creating Geofence objects, and the convenience class for adding them. Also, to handle the
+ intents sent from Location Services when geofence transitions occur, you can define a
+ {@link android.app.PendingIntent} as shown in this section.
+</p>
+
+<h3>Create geofence objects</h3>
+
+<p>
+    First, use <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.
+    html">Geofence.Builder</a></code> to create a geofence, setting the desired radius, duration, and
+    transition types for the geofence. For example, to populate a list object named
+    {@code mGeofenceList}:
+    </p>
+
+<pre>
+mGeofenceList.add(new Geofence.Builder()
+    // Set the request ID of the geofence. This is a string to identify this
+    // geofence.
+    .setRequestId(entry.getKey())
+
+    .setCircularRegion(
+            entry.getValue().latitude,
+            entry.getValue().longitude,
+            Constants.GEOFENCE_RADIUS_IN_METERS
+    )
+    .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
+    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
+            Geofence.GEOFENCE_TRANSITION_EXIT)
+    .build());
+</pre>
+
+<p>This example pulls data from a constants file. In actual practice, apps might
+    dynamically create geofences based on the user's location.</p>
+
+<h3>Specify geofences and initial triggers</h3>
+
+<p>
+    The following snippet uses the <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.html">
+    GeofencingRequest</a></code> class
+    and its nested <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.Builder.html">
+    GeofencingRequestBuilder</a></code> class to
+    specify the geofences to monitor and to set how related geofence events are triggered:
 </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.
-        &#64;Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            return mDialog;
-        }
-        ...
-    }
-    ...
-    /*
-     * Handle results returned to the FragmentActivity
-     * by Google Play services
-     */
-     &#64;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("Geofence Detection",
-                    "Google Play services is available.");
-            // Continue
-            return true;
-        // Google Play services was not available for some reason
-        } 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(),
-                        "Geofence Detection");
-            }
-        }
-    }
-    ...
+private GeofencingRequest getGeofencingRequest() {
+    GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
+    builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
+    builder.addGeofences(mGeofenceList);
+    return builder.build();
 }
 </pre>
-<p>
-    Snippets in the following sections call this method to verify that Google Play services is
-    available.
-</p>
-<p>
-    To use geofencing, start by defining the geofences you want to monitor. Although you usually
-    store geofence data in a local database or download it from the network, you need to send
-    a geofence to Location Services as an instance of
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html">Geofence</a></code>,
-    which you create with
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.html">Geofence.Builder</a></code>.
-    Each
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html">Geofence</a></code>
-    object contains the following information:
-</p>
-<dl>
-    <dt>Latitude, longitude, and radius</dt>
-    <dd>
-        Define a circular area for the geofence. Use the latitude and longitude to mark a location
-        of interest, and then use the radius to adjust how close the user needs to approach the
-        location before the geofence is detected. The larger the radius, the more likely the
-        user will trigger a geofence transition alert by approaching the geofence. For example,
-        providing a large radius for a geofencing app that turns on lights in the user's house as
-        the user returns home might cause the lights to go on even if the user is simply passing by.
-    </dd>
-    <dt>Expiration time</dt>
-    <dd>
-        How long the geofence should remain active. Once the expiration time is reached, Location
-        Services deletes the geofence. Most of the time, you should specify an expiration time, but
-        you may want to keep permanent geofences for the user's home or place of work.
-    </dd>
-    <dt>Transition type</dt>
-    <dd>
-        Location Services can detect when the user steps within the radius of the geofence ("entry")
-        and when the user steps outside the radius of the geofence ("exit"), or both.
-    </dd>
-    <dt>Geofence ID</dt>
-    <dd>
-        A string that is stored with the geofence. You should make this unique, so that you can
-        use it to remove a geofence from Location Services tracking.
-    </dd>
-</dl>
-<h3>Define geofence storage</h3>
-<p>
-    A geofencing app needs to read and write geofence data to persistent storage. You shouldn't use
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html">Geofence</a></code>
-    objects to do this; instead, use storage techniques such as databases that can store groups of
-    related data.
-</p>
-<p>
-    As an example of storing geofence data, the following snippet defines two classes that use
-    the app's {@link android.content.SharedPreferences} instance for persistent storage. The class
-    {@code SimpleGeofence}, analogous to a database record, stores the
-    data for a single
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html">Geofence</a></code>
-    object in a "flattened" form. The class {@code SimpleGeofenceStore}, analogous to a database,
-    reads and writes {@code SimpleGeofence} data to the
-    {@link android.content.SharedPreferences} instance.
-</p>
-<pre>
-public class MainActivity extends FragmentActivity {
-    ...
-    /**
-     * A single Geofence object, defined by its center and radius.
-     */
-    public class SimpleGeofence {
-            // Instance variables
-            private final String mId;
-            private final double mLatitude;
-            private final double mLongitude;
-            private final float mRadius;
-            private long mExpirationDuration;
-            private int mTransitionType;
 
-        /**
-         * @param geofenceId The Geofence's request ID
-         * @param latitude Latitude of the Geofence's center.
-         * @param longitude Longitude of the Geofence's center.
-         * @param radius Radius of the geofence circle.
-         * @param expiration Geofence expiration duration
-         * @param transition Type of Geofence transition.
-         */
-        public SimpleGeofence(
-                String geofenceId,
-                double latitude,
-                double longitude,
-                float radius,
-                long expiration,
-                int transition) {
-            // Set the instance fields from the constructor
-            this.mId = geofenceId;
-            this.mLatitude = latitude;
-            this.mLongitude = longitude;
-            this.mRadius = radius;
-            this.mExpirationDuration = expiration;
-            this.mTransitionType = transition;
-        }
-        // Instance field getters
-        public String getId() {
-            return mId;
-        }
-        public double getLatitude() {
-            return mLatitude;
-        }
-        public double getLongitude() {
-            return mLongitude;
-        }
-        public float getRadius() {
-            return mRadius;
-        }
-        public long getExpirationDuration() {
-            return mExpirationDuration;
-        }
-        public int getTransitionType() {
-            return mTransitionType;
-        }
-        /**
-         * Creates a Location Services Geofence object from a
-         * SimpleGeofence.
-         *
-         * @return A Geofence object
-         */
-        public Geofence toGeofence() {
-            // Build a new Geofence object
-            return new Geofence.Builder()
-                    .setRequestId(getId())
-                    .setTransitionTypes(mTransitionType)
-                    .setCircularRegion(
-                            getLatitude(), getLongitude(), getRadius())
-                    .setExpirationDuration(mExpirationDuration)
-                    .build();
-        }
-    }
-    ...
-    /**
-     * Storage for geofence values, implemented in SharedPreferences.
-     */
-    public class SimpleGeofenceStore {
-        // Keys for flattened geofences stored in SharedPreferences
-        public static final String KEY_LATITUDE =
-                "com.example.android.geofence.KEY_LATITUDE";
-        public static final String KEY_LONGITUDE =
-                "com.example.android.geofence.KEY_LONGITUDE";
-        public static final String KEY_RADIUS =
-                "com.example.android.geofence.KEY_RADIUS";
-        public static final String KEY_EXPIRATION_DURATION =
-                "com.example.android.geofence.KEY_EXPIRATION_DURATION";
-        public static final String KEY_TRANSITION_TYPE =
-                "com.example.android.geofence.KEY_TRANSITION_TYPE";
-        // The prefix for flattened geofence keys
-        public static final String KEY_PREFIX =
-                "com.example.android.geofence.KEY";
-        /*
-         * Invalid values, used to test geofence storage when
-         * retrieving geofences
-         */
-        public static final long INVALID_LONG_VALUE = -999l;
-        public static final float INVALID_FLOAT_VALUE = -999.0f;
-        public static final int INVALID_INT_VALUE = -999;
-        // The SharedPreferences object in which geofences are stored
-        private final SharedPreferences mPrefs;
-        // The name of the SharedPreferences
-        private static final String SHARED_PREFERENCES =
-                "SharedPreferences";
-        // Create the SharedPreferences storage with private access only
-        public SimpleGeofenceStore(Context context) {
-            mPrefs =
-                    context.getSharedPreferences(
-                            SHARED_PREFERENCES,
-                            Context.MODE_PRIVATE);
-        }
-        /**
-         * Returns a stored geofence by its id, or returns {@code null}
-         * if it's not found.
-         *
-         * @param id The ID of a stored geofence
-         * @return A geofence defined by its center and radius. See
-         */
-        public SimpleGeofence getGeofence(String id) {
-            /*
-             * Get the latitude for the geofence identified by id, or
-             * INVALID_FLOAT_VALUE if it doesn't exist
-             */
-            double lat = mPrefs.getFloat(
-                    getGeofenceFieldKey(id, KEY_LATITUDE),
-                    INVALID_FLOAT_VALUE);
-            /*
-             * Get the longitude for the geofence identified by id, or
-             * INVALID_FLOAT_VALUE if it doesn't exist
-             */
-            double lng = mPrefs.getFloat(
-                    getGeofenceFieldKey(id, KEY_LONGITUDE),
-                    INVALID_FLOAT_VALUE);
-            /*
-             * Get the radius for the geofence identified by id, or
-             * INVALID_FLOAT_VALUE if it doesn't exist
-             */
-            float radius = mPrefs.getFloat(
-                    getGeofenceFieldKey(id, KEY_RADIUS),
-                    INVALID_FLOAT_VALUE);
-            /*
-             * Get the expiration duration for the geofence identified
-             * by id, or INVALID_LONG_VALUE if it doesn't exist
-             */
-            long expirationDuration = mPrefs.getLong(
-                    getGeofenceFieldKey(id, KEY_EXPIRATION_DURATION),
-                    INVALID_LONG_VALUE);
-            /*
-             * Get the transition type for the geofence identified by
-             * id, or INVALID_INT_VALUE if it doesn't exist
-             */
-            int transitionType = mPrefs.getInt(
-                    getGeofenceFieldKey(id, KEY_TRANSITION_TYPE),
-                    INVALID_INT_VALUE);
-            // If none of the values is incorrect, return the object
-            if (
-                lat != GeofenceUtils.INVALID_FLOAT_VALUE &amp;&amp;
-                lng != GeofenceUtils.INVALID_FLOAT_VALUE &amp;&amp;
-                radius != GeofenceUtils.INVALID_FLOAT_VALUE &amp;&amp;
-                expirationDuration !=
-                        GeofenceUtils.INVALID_LONG_VALUE &amp;&amp;
-                transitionType != GeofenceUtils.INVALID_INT_VALUE) {
-
-                // Return a true Geofence object
-                return new SimpleGeofence(
-                        id, lat, lng, radius, expirationDuration,
-                        transitionType);
-            // Otherwise, return null.
-            } else {
-                return null;
-            }
-        }
-        /**
-         * Save a geofence.
-         * @param geofence The SimpleGeofence containing the
-         * values you want to save in SharedPreferences
-         */
-        public void setGeofence(String id, SimpleGeofence geofence) {
-            /*
-             * Get a SharedPreferences editor instance. Among other
-             * things, SharedPreferences ensures that updates are atomic
-             * and non-concurrent
-             */
-            Editor editor = mPrefs.edit();
-            // Write the Geofence values to SharedPreferences
-            editor.putFloat(
-                    getGeofenceFieldKey(id, KEY_LATITUDE),
-                    (float) geofence.getLatitude());
-            editor.putFloat(
-                    getGeofenceFieldKey(id, KEY_LONGITUDE),
-                    (float) geofence.getLongitude());
-            editor.putFloat(
-                    getGeofenceFieldKey(id, KEY_RADIUS),
-                    geofence.getRadius());
-            editor.putLong(
-                    getGeofenceFieldKey(id, KEY_EXPIRATION_DURATION),
-                    geofence.getExpirationDuration());
-            editor.putInt(
-                    getGeofenceFieldKey(id, KEY_TRANSITION_TYPE),
-                    geofence.getTransitionType());
-            // Commit the changes
-            editor.commit();
-        }
-        public void clearGeofence(String id) {
-            /*
-             * Remove a flattened geofence object from storage by
-             * removing all of its keys
-             */
-            Editor editor = mPrefs.edit();
-            editor.remove(getGeofenceFieldKey(id, KEY_LATITUDE));
-            editor.remove(getGeofenceFieldKey(id, KEY_LONGITUDE));
-            editor.remove(getGeofenceFieldKey(id, KEY_RADIUS));
-            editor.remove(getGeofenceFieldKey(id,
-                    KEY_EXPIRATION_DURATION));
-            editor.remove(getGeofenceFieldKey(id, KEY_TRANSITION_TYPE));
-            editor.commit();
-        }
-        /**
-         * Given a Geofence object's ID and the name of a field
-         * (for example, KEY_LATITUDE), return the key name of the
-         * object's values in SharedPreferences.
-         *
-         * @param id The ID of a Geofence object
-         * @param fieldName The field represented by the key
-         * @return The full key name of a value in SharedPreferences
-         */
-        private String getGeofenceFieldKey(String id,
-                String fieldName) {
-            return KEY_PREFIX + "_" + id + "_" + fieldName;
-        }
-    }
-    ...
-}
-</pre>
-<h3>Create Geofence objects</h3>
 <p>
-    The following snippet uses the {@code SimpleGeofence} and {@code SimpleGeofenceStore} classes
-    gets geofence data from the UI, stores it in {@code SimpleGeofence} objects, stores these
-    objects in a {@code SimpleGeofenceStore} object, and then creates
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html">Geofence</a></code>
-    objects:
+    This example shows the use of two geofence triggers. The <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">
+    GEOFENCE_TRANSITION_ENTER</a></code>
+    transition triggers when a device enters a geofence, and the <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_EXIT">
+    GEOFENCE_TRANSITION_EXIT</a></code>
+    transition triggers when a device exits a geofence. Specifying
+    <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.html#INITIAL_TRIGGER_ENTER">
+        INITIAL_TRIGGER_ENTER</a></code> tells Location services that
+    <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">
+        GEOFENCE_TRANSITION_ENTER</a></code>
+    should be triggered if the the device is already inside the geofence.</p>
 </p>
-<pre>
-public class MainActivity extends FragmentActivity {
-    ...
-    /*
-     * Use to set an expiration time for a geofence. After this amount
-     * of time Location Services will stop tracking the geofence.
-     */
-    private static final long SECONDS_PER_HOUR = 60;
-    private static final long MILLISECONDS_PER_SECOND = 1000;
-    private static final long GEOFENCE_EXPIRATION_IN_HOURS = 12;
-    private static final long GEOFENCE_EXPIRATION_TIME =
-            GEOFENCE_EXPIRATION_IN_HOURS *
-            SECONDS_PER_HOUR *
-            MILLISECONDS_PER_SECOND;
-    ...
-    /*
-     * Handles to UI views containing geofence data
-     */
-    // Handle to geofence 1 latitude in the UI
-    private EditText mLatitude1;
-    // Handle to geofence 1 longitude in the UI
-    private EditText mLongitude1;
-    // Handle to geofence 1 radius in the UI
-    private EditText mRadius1;
-    // Handle to geofence 2 latitude in the UI
-    private EditText mLatitude2;
-    // Handle to geofence 2 longitude in the UI
-    private EditText mLongitude2;
-    // Handle to geofence 2 radius in the UI
-    private EditText mRadius2;
-    /*
-     * Internal geofence objects for geofence 1 and 2
-     */
-    private SimpleGeofence mUIGeofence1;
-    private SimpleGeofence mUIGeofence2;
-    ...
-    // Internal List of Geofence objects
-    List&lt;Geofence&gt; mGeofenceList;
-    // Persistent storage for geofences
-    private SimpleGeofenceStore mGeofenceStorage;
-    ...
-    &#64;Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        ...
-        // Instantiate a new geofence storage area
-        mGeofenceStorage = new SimpleGeofenceStore(this);
 
-        // Instantiate the current List of geofences
-        mCurrentGeofences = new ArrayList&lt;Geofence&gt;();
-    }
-    ...
-    /**
-     * Get the geofence parameters for each geofence from the UI
-     * and add them to a List.
-     */
-    public void createGeofences() {
-        /*
-         * Create an internal object to store the data. Set its
-         * ID to "1". This is a "flattened" object that contains
-         * a set of strings
-         */
-        mUIGeofence1 = new SimpleGeofence(
-                "1",
-                Double.valueOf(mLatitude1.getText().toString()),
-                Double.valueOf(mLongitude1.getText().toString()),
-                Float.valueOf(mRadius1.getText().toString()),
-                GEOFENCE_EXPIRATION_TIME,
-                // This geofence records only entry transitions
-                Geofence.GEOFENCE_TRANSITION_ENTER);
-        // Store this flat version
-        mGeofenceStorage.setGeofence("1", mUIGeofence1);
-        // Create another internal object. Set its ID to "2"
-        mUIGeofence2 = new SimpleGeofence(
-                "2",
-                Double.valueOf(mLatitude2.getText().toString()),
-                Double.valueOf(mLongitude2.getText().toString()),
-                Float.valueOf(mRadius2.getText().toString()),
-                GEOFENCE_EXPIRATION_TIME,
-                // This geofence records both entry and exit transitions
-                Geofence.GEOFENCE_TRANSITION_ENTER |
-                Geofence.GEOFENCE_TRANSITION_EXIT);
-        // Store this flat version
-        mGeofenceStorage.setGeofence(2, mUIGeofence2);
-        mGeofenceList.add(mUIGeofence1.toGeofence());
-        mGeofenceList.add(mUIGeofence2.toGeofence());
-    }
-    ...
-}
-</pre>
-<p>
-    In addition to the {@link java.util.List} of
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html">Geofence</a></code>
-    objects you want to monitor, you need to provide Location Services with the
-    {@link android.content.Intent} that it sends to your app when it detects geofence
-    transitions.
-<h4>Define a Intent for geofence transitions</h4>
+<p>In many cases, it may be preferable to use instead <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest.html#INITIAL_TRIGGER_DWELL">
+    INITIAL_TRIGGER_DWELL</a></code>,
+    which triggers events only when the user stops for a defined duration within a geofence.
+    This approach can help reduce "alert spam" resulting from large numbers notifications when a
+    device briefly enters and exits geofences. Another strategy for getting best results from your
+    geofences is to set a minimum radius of 100 meters. This helps account for the location accuracy
+    of typical WiFi networks, and also helps reduce device power consumption.
+</p>
+
+<h3>Define an Intent for geofence transitions</h3>
 <p>
     The {@link android.content.Intent} sent from Location Services can trigger various actions in
     your app, but you should <i>not</i> have it start an activity or fragment, because components
@@ -601,807 +174,133 @@
     {@link android.app.IntentService} is a good way to handle the intent. An
     {@link android.app.IntentService} can post a notification, do long-running background work,
     send intents to other services, or send a broadcast intent. The following snippet shows how
-    how to define a {@link android.app.PendingIntent} that starts an
-    {@link android.app.IntentService}:
+    to define a {@link android.app.PendingIntent} that starts an {@link android.app.IntentService}:
 </p>
 <pre>
 public class MainActivity extends FragmentActivity {
     ...
-    /*
-     * Create a PendingIntent that triggers an IntentService in your
-     * app when a geofence transition occurs.
-     */
-    private PendingIntent getTransitionPendingIntent() {
-        // Create an explicit Intent
-        Intent intent = new Intent(this,
-                ReceiveTransitionsIntentService.class);
-        /*
-         * Return the PendingIntent
-         */
-        return PendingIntent.getService(
-                this,
-                0,
-                intent,
-                PendingIntent.FLAG_UPDATE_CURRENT);
-    }
-    ...
-}
-</pre>
-<p>
-    Now you have all the code you need to send a request to monitor geofences to Location
-    Services.
-</p>
-<!-- Send the monitoring request -->
-<h3 id="requestmonitoring">Send the monitoring request</h3>
-<p>
-    Sending the monitoring request requires two asynchronous operations. The first operation gets a
-    location client for the request, and the second makes the request using the client. In both
-    cases, Location Services invokes a callback method when it finishes the operation. The best way
-    to handle these operations is to chain together the method calls. The following snippets
-    demonstrate how to set up an activity, define the methods, and call them in the proper order.
-</p>
-<p>
-     First, modify the activity's class definition to implement the necessary callback interfaces.
-     Add 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 a location 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 location client.
-    </dd>
-    <dt>
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnAddGeofencesResultListener.html">OnAddGeofencesResultListener</a></code>
-    </dt>
-    <dd>
-        Specifies a method that Location Services calls once it has added the geofences.
-    </dd>
-</dl>
-<p>
-    For example:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-}
-</pre>
-<h4>Start the request process</h4>
-<p>
-    Next, define a method that starts the request process by connecting to Location Services.
-    Mark this as a request to add a geofence by setting a global variable. This allows you to
-    use the callback
-<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">ConnectionCallbacks.onConnected()</a></code>
-    to add geofences and to remove them, as described in succeeding sections.
-</p>
-<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:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    // Holds the location client
-    private LocationClient mLocationClient;
-    // Stores the PendingIntent used to request geofence monitoring
-    private PendingIntent mGeofenceRequestIntent;
-    // Defines the allowable request types.
-    public enum REQUEST_TYPE = {ADD}
-    private REQUEST_TYPE mRequestType;
-    // Flag that indicates if a request is underway.
-    private boolean mInProgress;
-    ...
-    &#64;Override
-    protected void onCreate(Bundle savedInstanceState) {
-        ...
-        // Start with the request flag set to false
-        mInProgress = false;
-        ...
-    }
-    ...
-    /**
-     * Start a request for geofence monitoring by calling
-     * LocationClient.connect().
-     */
-    public void addGeofences() {
-        // Start a request to add geofences
-        mRequestType = ADD;
-        /*
-         * Test for Google Play services after setting the request type.
-         * If Google Play services isn't present, the proper request
-         * can be restarted.
-         */
-        if (!servicesConnected()) {
-            return;
+    private PendingIntent getGeofencePendingIntent() {
+        // Reuse the PendingIntent if we already have it.
+        if (mGeofencePendingIntent != null) {
+            return mGeofencePendingIntent;
         }
-        /*
-         * Create a new location client object. Since the current
-         * activity class implements ConnectionCallbacks and
-         * OnConnectionFailedListener, pass the current activity object
-         * as the listener for both parameters
-         */
-        mLocationClient = new LocationClient(this, this, this)
-        // If a request is not already underway
-        if (!mInProgress) {
-            // Indicate that a request is underway
-            mInProgress = true;
-            // Request a connection from the client to Location Services
-            mLocationClient.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.
-             */
-        }
+        Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
+        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
+        // calling addGeofences() and removeGeofences().
+        return PendingIntent.getService(this, 0, intent, PendingIntent.
+                FLAG_UPDATE_CURRENT);
     }
-    ...
-}
 </pre>
-<h4>Send a request to add the geofences</h4>
+
+<h3>Add geofences</h3>
+
 <p>
-    In your implementation of
-<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">ConnectionCallbacks.onConnected()</a></code>,
-    call
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#addGeofences(java.util.List<com.google.android.gms.location.Geofence>, android.app.PendingIntent, com.google.android.gms.location.LocationClient.OnAddGeofencesResultListener)">LocationClient.addGeofences()</a></code>.
-    Notice that if the connection fails,
-<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">onConnected()</a></code>
-    isn't called, and the request stops.
+    To add geofences, use the <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingApi.html#addGeofences(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.GeofencingRequest, android.app.PendingIntent)">{@code GeoencingApi.addGeofences()}</a></code> method.
+    Provide the Google API client, the <code><a href="{@docRoot}reference/com/google/android/gms/location/GeofencingRequest">
+    GeofencingRequest</a></code> object, and the {@link android.app.PendingIntent}.
+    The following snippet, which processes the results in <code><a href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html#onResult(R)">
+    onResult()</a></code>, assumes that the main activity implements <code><a href="{@docRoot}reference/com/google/android/gms/common/api/ResultCallback.html">
+    ResultCallback</a></code>:
 </p>
 <pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
+public class MainActivity extends FragmentActivity {
     ...
-    /*
-     * Provide the implementation of ConnectionCallbacks.onConnected()
-     * Once the connection is available, send a request to add the
-     * Geofences
-     */
-    &#64;Override
-    private void onConnected(Bundle dataBundle) {
-        ...
-        switch (mRequestType) {
-            case ADD :
-                // Get the PendingIntent for the request
-                mTransitionPendingIntent =
-                        getTransitionPendingIntent();
-                // Send a request to add the current geofences
-                mLocationClient.addGeofences(
-                        mCurrentGeofences, pendingIntent, this);
-            ...
-        }
-    }
-    ...
-}
+    LocationServices.GeofencingApi.addGeofences(
+                mGoogleApiClient,
+                getGeofencingRequest(),
+                getGeofencePendingIntent()
+        ).setResultCallback(this);
 </pre>
-<p>
-    Notice that
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#addGeofences(java.util.List<com.google.android.gms.location.Geofence>, android.app.PendingIntent, com.google.android.gms.location.LocationClient.OnAddGeofencesResultListener)">addGeofences()</a></code>
-    returns immediately, but the status of the request is indeterminate until Location Services
-    calls
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnAddGeofencesResultListener.html#onAddGeofencesResult(int, java.lang.String[])">onAddGeofencesResult()</a></code>
-    Once this method is called, you can determine if the request was successful or not.
-</p>
-<h4>Check the result returned by Location Services</h4>
-<p>
-    When Location Services invokes your implementation of the callback method
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnAddGeofencesResultListener.html#onAddGeofencesResult(int, java.lang.String[])">onAddGeofencesResult()</a></code>,
-    indicating that the request is complete, examine the incoming status code. If the request
-    was successful, the geofences you requested are active. If the request was unsuccessful,
-    the geofences aren't active, and you need to re-try the request or report an error. For example:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-        ...
-    /*
-     * Provide the implementation of
-     * OnAddGeofencesResultListener.onAddGeofencesResult.
-     * Handle the result of adding the geofences
-     *
-     */
-    &#64;Override
-    public void onAddGeofencesResult(
-            int statusCode, String[] geofenceRequestIds) {
-        // If adding the geofences was successful
-        if (LocationStatusCodes.SUCCESS == statusCode) {
-            /*
-             * Handle successful addition of geofences here.
-             * You can send out a broadcast intent or update the UI.
-             * geofences into the Intent's extended data.
-             */
-        } else {
-        // If adding the geofences failed
-            /*
-             * Report errors here.
-             * You can log the error using Log.e() or update
-             * the UI.
-             */
-        }
-        // Turn off the in progress flag and disconnect the client
-        mInProgress = false;
-        mLocationClient.disconnect();
-    }
-    ...
-}
-</pre>
-<!-- Handle disconnections -->
-<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/LocationClient.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,
-        OnAddGeofencesResultListener {
-    ...
-    /*
-     * Implement ConnectionCallbacks.onDisconnected()
-     * Called by Location Services once the location client is
-     * disconnected.
-     */
-    &#64;Override
-    public void onDisconnected() {
-        // Turn off the request flag
-        mInProgress = false;
-        // Destroy the current location client
-        mLocationClient = 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,
-        OnAddGeofencesResultListener {
-    ...
-    // Implementation of OnConnectionFailedListener.onConnectionFailed
-    &#64;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(),
-                        "Geofence Detection");
-            }
-        }
-    }
-    ...
-}
-</pre>
-<!--
-    Handle Geofence Transitions
- -->
+
+
 <h2 id="HandleGeofenceTransitions">Handle Geofence Transitions</h2>
 <p>
     When Location Services detects that the user has entered or exited a geofence, it
     sends out the {@link android.content.Intent} contained in the {@link android.app.PendingIntent}
-    you included in the request to add geofences. This {@link android.content.Intent} is
+    you included in the request to add geofences. This {@link android.content.Intent} is received
+    by a service like <code>GeofenceTransitionsIntentService</code>,
+    which obtains the geofencing event from the intent, determines the type of Geofence transition(s),
+    and determines which of the defined geofences was triggered. It then sends a notification as
+    the output.
 </p>
-<h3>Define an IntentService</h3>
 <p>
     The following snippet shows how to define an {@link android.app.IntentService} that posts a
     notification when a geofence transition occurs. When the user clicks the notification, the
     app's main activity appears:
 </p>
 <pre>
-public class ReceiveTransitionsIntentService extends IntentService {
-    ...
-    /**
-     * Sets an identifier for the service
-     */
-    public ReceiveTransitionsIntentService() {
-        super("ReceiveTransitionsIntentService");
-    }
-    /**
-     * Handles incoming intents
-     *&#64;param intent The Intent sent by Location Services. This
-     * Intent is provided
-     * to Location Services (inside a PendingIntent) when you call
-     * addGeofences()
-     */
-    &#64;Override
+public class GeofenceTransitionsIntentService extends IntentService {
+   ...
     protected void onHandleIntent(Intent intent) {
-        // First check for errors
-        if (LocationClient.hasError(intent)) {
-            // Get the error code with a static method
-            int errorCode = LocationClient.getErrorCode(intent);
-            // Log the error
-            Log.e("ReceiveTransitionsIntentService",
-                    "Location Services error: " +
-                    Integer.toString(errorCode));
-            /*
-             * You can also send the error code to an Activity or
-             * Fragment with a broadcast Intent
-             */
-        /*
-         * If there's no error, get the transition type and the IDs
-         * of the geofence or geofences that triggered the transition
-         */
-        } else {
-            // Get the type of transition (entry or exit)
-            int transitionType =
-                    LocationClient.getGeofenceTransition(intent);
-            // Test that a valid transition was reported
-            if (
-                (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER)
-                 ||
-                (transitionType == Geofence.GEOFENCE_TRANSITION_EXIT)
-               ) {
-                List &lt;Geofence&gt; triggerList =
-                        getTriggeringGeofences(intent);
+        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
+        if (geofencingEvent.hasError()) {
+            String errorMessage = GeofenceErrorMessages.getErrorString(this,
+                    geofencingEvent.getErrorCode());
+            Log.e(TAG, errorMessage);
+            return;
+        }
 
-                String[] triggerIds = new String[geofenceList.size()];
+        // Get the transition type.
+        int geofenceTransition = geofencingEvent.getGeofenceTransition();
 
-                for (int i = 0; i &lt; triggerIds.length; i++) {
-                    // Store the Id of each geofence
-                    triggerIds[i] = triggerList.get(i).getRequestId();
-                }
-                /*
-                 * At this point, you can store the IDs for further use
-                 * display them, or display the details associated with
-                 * them.
-                 */
-            }
-        // An invalid transition was reported
+        // Test that the reported transition was of interest.
+        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
+                geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
+
+            // Get the geofences that were triggered. A single event can trigger
+            // multiple geofences.
+            List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
+
+            // Get the transition details as a String.
+            String geofenceTransitionDetails = getGeofenceTransitionDetails(
+                    this,
+                    geofenceTransition,
+                    triggeringGeofences
+            );
+
+            // Send notification and log the transition details.
+            sendNotification(geofenceTransitionDetails);
+            Log.i(TAG, geofenceTransitionDetails);
         } else {
-            Log.e("ReceiveTransitionsIntentService",
-                    "Geofence transition error: " +
-                    Integer.toString()transitionType));
+            // Log the error.
+            Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
+                    geofenceTransition));
         }
     }
-    ...
-}
 </pre>
-<!-- Specify the IntentService in the manifest -->
-<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">&lt;service&gt;</a></code>
-    element to the app manifest. For example:
-</p>
-<pre>
-&lt;service
-    android:name="com.example.android.location.ReceiveTransitionsIntentService"
-    android:label="&#64;string/app_name"
-    android:exported="false"&gt;
-&lt;/service&gt;
-</pre>
-<p>
-    Notice that you don't have to specify intent filters for the service, because it only receives
-    explicit intents. How the incoming geofence transition intents are created is described in the
-    section <a href="#requestmonitoring">Send the monitoring request</a>.
-</p>
+
+<p>After detecting the transition event via the {@link android.app.PendingIntent},
+    this {@link android.app.IntentService} gets the geofence transition type and tests whether
+    it is one of the events the app uses to trigger notifications -- either
+    <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_ENTER">GEOFENCE_TRANSITION_ENTER</a></code>
+     or <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html#GEOFENCE_TRANSITION_EXIT">GEOFENCE_TRANSITION_EXIT</a></code>
+    in this case. The service then sends a notification and logs the transition details.</p>
 <!--
     Remove Geofences
  -->
 <h2 id="StopGeofenceMonitoring">Stop Geofence Monitoring</h2>
-<p>
-    To stop geofence monitoring, you remove the geofences themselves. You can remove a specific
-    set of geofences or all the geofences associated with a {@link android.app.PendingIntent}. The
-    procedure is similar to adding geofences. The first operation gets a location
-    client for the removal request, and the second makes the request using the client.
+
+<p>Stopping geofence monitoring when it is no longer needed or desired can help save battery
+    power and CPU cycles on the device. You can stop geofence monitoring
+    in the main activity used to add and remove geofences; removing a geofence stops it
+    immediately. The API provides methods to
+    remove geofences either by request IDs, or by removing geofences associated with a given
+    {@link android.app.PendingIntent}.
 </p>
 <p>
-    The callback methods that Location Services invokes when it has finished removing geofences
-    are defined in the interface
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnRemoveGeofencesResultListener.html">LocationClient.OnRemoveGeofencesResultListener</a></code>. Declare
-    this interface as part of your class definition, and then add definitions for its two methods:
-</p>
-<dl>
-    <dt>
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnRemoveGeofencesResultListener.html#onRemoveGeofencesByPendingIntentResult(int, android.app.PendingIntent)">onRemoveGeofencesByPendingIntentResult()</a></code>
-    </dt>
-    <dd>
-        Callback invoked when Location Services finishes a request to remove all geofences made
-        by the method
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#removeGeofences(android.app.PendingIntent, com.google.android.gms.location.LocationClient.OnRemoveGeofencesResultListener)">removeGeofences(PendingIntent, LocationClient.OnRemoveGeofencesResultListener)</a></code>.
-    </dd>
-    <dt>
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnRemoveGeofencesResultListener.html#onRemoveGeofencesByRequestIdsResult(int, java.lang.String[])">onRemoveGeofencesByRequestIdsResult(List&lt;String&gt;, LocationClient.OnRemoveGeofencesResultListener)</a></code>
-    </dt>
-    <dd>
-        Callback invoked when Location Services finished a request to remove a set of geofences,
-        specified by their geofence IDs, by the method
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#removeGeofences(java.util.List<java.lang.String>, com.google.android.gms.location.LocationClient.OnRemoveGeofencesResultListener)">removeGeofences(List&lt;String&gt;, LocationClient.OnRemoveGeofencesResultListener)</a></code>.
-    </dd>
-</dl>
-<p>
-    Examples of implementing these methods are shown in the next snippets.
-</p>
-<h3>Remove all geofences</h3>
-<p>
-    Since removing geofences uses some of the methods you use to add geofences, start by defining
-    another request type:
+    The following snippet removes geofences by {@link android.app.PendingIntent}, stopping all
+    further notification when the device enters or exits previously added geofences:
 </p>
 <pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    // Enum type for controlling the type of removal requested
-    public enum REQUEST_TYPE = {ADD, REMOVE_INTENT}
-    ...
+LocationServices.GeofencingApi.removeGeofences(
+            mGoogleApiClient,
+            // This is the same pending intent that was used in addGeofences().
+            getGeofencePendingIntent()
+    ).setResultCallback(this); // Result processed in onResult().
 }
 </pre>
+
 <p>
-    Start the removal request by getting a connection to Location Services. If the connection fails,
-<code><a href="{@docRoot}reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">onConnected()</a></code> isn't called,
-    and the request stops. The following snippet shows how to start the request:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    /**
-     * Start a request to remove geofences by calling
-     * LocationClient.connect()
-     */
-    public void removeGeofences(PendingIntent requestIntent) {
-        // Record the type of removal request
-        mRequestType = REMOVE_INTENT;
-        /*
-         * 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;
-        }
-        // Store the PendingIntent
-        mGeofenceRequestIntent = requestIntent;
-        /*
-         * Create a new location client object. Since the current
-         * activity class implements ConnectionCallbacks and
-         * OnConnectionFailedListener, pass the current activity object
-         * as the listener for both parameters
-         */
-        mLocationClient = new LocationClient(this, this, this);
-        // If a request is not already underway
-        if (!mInProgress) {
-            // Indicate that a request is underway
-            mInProgress = true;
-            // Request a connection from the client to Location Services
-            mLocationClient.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>
-   When Location Services invokes the callback method indicating that the connection is open,
-   make the request to remove all geofences. Disconnect the client after making the request.
-   For example:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    /**
-     * Once the connection is available, send a request to remove the
-     * Geofences. The method signature used depends on which type of
-     * remove request was originally received.
-     */
-    private void onConnected(Bundle dataBundle) {
-        /*
-         * Choose what to do based on the request type set in
-         * removeGeofences
-         */
-        switch (mRequestType) {
-            ...
-            case REMOVE_INTENT :
-                mLocationClient.removeGeofences(
-                        mGeofenceRequestIntent, this);
-                break;
-            ...
-        }
-    }
-    ...
-}
-</pre>
-<p>
-    Although the call to
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.html#removeGeofences(android.app.PendingIntent, com.google.android.gms.location.LocationClient.OnRemoveGeofencesResultListener)">removeGeofences(PendingIntent, LocationClient.OnRemoveGeofencesResultListener)</a></code>    Services calls
-    returns immediately, the result of the removal request is indeterminate until Location Services
-    calls
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnRemoveGeofencesResultListener.html#onRemoveGeofencesByPendingIntentResult(int, android.app.PendingIntent)">onRemoveGeofencesByPendingIntentResult()</a></code>.
-    The following snippet shows how to define this method:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    /**
-     * When the request to remove geofences by PendingIntent returns,
-     * handle the result.
-     *
-     *&#64;param statusCode the code returned by Location Services
-     *&#64;param requestIntent The Intent used to request the removal.
-     */
-    &#64;Override
-    public void onRemoveGeofencesByPendingIntentResult(int statusCode,
-            PendingIntent requestIntent) {
-        // If removing the geofences was successful
-        if (statusCode == LocationStatusCodes.SUCCESS) {
-            /*
-             * Handle successful removal of geofences here.
-             * You can send out a broadcast intent or update the UI.
-             * geofences into the Intent's extended data.
-             */
-        } else {
-        // If adding the geocodes failed
-            /*
-             * Report errors here.
-             * You can log the error using Log.e() or update
-             * the UI.
-             */
-        }
-        /*
-         * Disconnect the location client regardless of the
-         * request status, and indicate that a request is no
-         * longer in progress
-         */
-        mInProgress = false;
-        mLocationClient.disconnect();
-    }
-    ...
-}
-</pre>
-<h3>Remove individual geofences</h3>
-<p>
-    The procedure for removing an individual geofence or set of geofences is similar to the
-    removal of all geofences. To specify the geofences you want remove, add their geofence ID
-    values to a {@link java.util.List} of String objects. Pass this {@link java.util.List} to a
-    different definition of {@code removeGeofences} with the appropriate signature. This method
-    then starts the removal process.
-</p>
-<p>
-    Start by adding a request type for removing geofences by a list, and also add a global variable
-    for storing the list of geofences:
-</p>
-<pre>
-    ...
-    // Enum type for controlling the type of removal requested
-    public enum REQUEST_TYPE = {ADD, REMOVE_INTENT, REMOVE_LIST}
-    // Store the list of geofence Ids to remove
-    String&lt;List&gt; mGeofencesToRemove;
-</pre>
-<p>
-    Next, define a list of geofences you want to remove. For example, this snippet removes the
-<code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.html">Geofence</a></code>
-    defined by the geofence ID "1":
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-        List&lt;String&gt; listOfGeofences =
-                Collections.singletonList("1");
-        removeGeofences(listOfGeofences);
-    ...
-}
-</pre>
-<p>
-    The following snippet defines the {@code removeGeofences()} method:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    /**
-     * Start a request to remove monitoring by
-     * calling LocationClient.connect()
-     *
-     */
-    public void removeGeofences(List&lt;String&gt; geofenceIds) {
-        // If Google Play services is unavailable, exit
-        // Record the type of removal request
-        mRequestType = REMOVE_LIST;
-        /*
-         * 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;
-        }
-        // Store the list of geofences to remove
-        mGeofencesToRemove = geofenceIds;
-        /*
-         * Create a new location client object. Since the current
-         * activity class implements ConnectionCallbacks and
-         * OnConnectionFailedListener, pass the current activity object
-         * as the listener for both parameters
-         */
-        mLocationClient = new LocationClient(this, this, this);
-        // If a request is not already underway
-        if (!mInProgress) {
-            // Indicate that a request is underway
-            mInProgress = true;
-            // Request a connection from the client to Location Services
-            mLocationClient.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>
-   When Location Services invokes the callback method indicating that the connection is open,
-   make the request to remove the list of geofences. Disconnect the client after making the request.
-   For example:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    private void onConnected(Bundle dataBundle) {
-        ...
-        switch (mRequestType) {
-        ...
-        // If removeGeofencesById was called
-            case REMOVE_LIST :
-                mLocationClient.removeGeofences(
-                        mGeofencesToRemove, this);
-                break;
-        ...
-        }
-        ...
-    }
-    ...
-}
-</pre>
-<p>
-    Define an implementation of
-<code><a href="{@docRoot}reference/com/google/android/gms/location/LocationClient.OnRemoveGeofencesResultListener.html#onRemoveGeofencesByRequestIdsResult(int, java.lang.String[])">onRemoveGeofencesByRequestIdsResult()</a></code>.
-    Location Services invokes this callback method to indicate that the request to remove a list of
-    geofences is complete. In this method, examine the incoming status code and take the
-    appropriate action:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity implements
-        ConnectionCallbacks,
-        OnConnectionFailedListener,
-        OnAddGeofencesResultListener {
-    ...
-    /**
-     * When the request to remove geofences by IDs returns, handle the
-     * result.
-     *
-     * &#64;param statusCode The code returned by Location Services
-     * &#64;param geofenceRequestIds The IDs removed
-     */
-    &#64;Override
-    public void onRemoveGeofencesByRequestIdsResult(
-            int statusCode, String[] geofenceRequestIds) {
-        // If removing the geocodes was successful
-        if (LocationStatusCodes.SUCCESS == statusCode) {
-            /*
-             * Handle successful removal of geofences here.
-             * You can send out a broadcast intent or update the UI.
-             * geofences into the Intent's extended data.
-             */
-        } else {
-        // If removing the geofences failed
-            /*
-             * Report errors here.
-             * You can log the error using Log.e() or update
-             * the UI.
-             */
-        }
-        // Indicate that a request is no longer in progress
-        mInProgress = false;
-        // Disconnect the location client
-        mLocationClient.disconnect();
-    }
-    ...
-}
-</pre>
-<p>
-    You can combine geofencing with other location-aware features, such as periodic location updates
-    or activity recognition, which are described in other lessons in this class.
-</p>
-<p>
-    The next lesson,
-    <a href="activity-recognition.html">Recognizing the User's Current Activity</a>, shows you how
-    to request and receive activity updates. At regular intervals, Location Services can send you
-    information about the user's current physical activity. Based on this information, you can
-    change your app's behavior; for example, you can switch to a longer update interval if you
-    detect that the user is walking instead of driving.
+    You can combine geofencing with other location-aware features, such as periodic location updates.
+    For more information, see the other lessons in this class.
 </p>
diff --git a/docs/html/training/location/index.jd b/docs/html/training/location/index.jd
index 35e177f..c4dec99 100644
--- a/docs/html/training/location/index.jd
+++ b/docs/html/training/location/index.jd
@@ -81,4 +81,10 @@
     Learn how to convert a location's latitude and longitude into an address
     (reverse geocoding).
   </dd>
+  <dt>
+    <b><a href="geofencing.html">Creating and Monitoring Geofences</a></b>
+  </dt> <dd>
+    Learn how to define one or more geographic areas as locations of interest,
+    called geofences, and detect when the user is close to or inside a geofence.
+  </dd>
 </dl>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index c59d8ff..c7a779c 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -736,6 +736,10 @@
             Displaying a Location Address
           </a>
           </li>
+          <li><a href="<?cs var:toroot ?>training/location/geofencing.html">
+            Creating and Monitoring Geofences
+          </a>
+          </li>
         </ul>
       </li>
     </ul>