summaryrefslogtreecommitdiffstats
path: root/docs/html/training
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/training')
-rw-r--r--docs/html/training/location/display-address.jd680
-rw-r--r--docs/html/training/training_toc.cs29
-rw-r--r--docs/html/training/transitions/custom-transitions.jd189
-rw-r--r--docs/html/training/transitions/index.jd80
-rw-r--r--docs/html/training/transitions/overview.jd165
-rw-r--r--docs/html/training/transitions/scenes.jd211
-rw-r--r--docs/html/training/transitions/transitions.jd315
-rw-r--r--docs/html/training/wearables/data-layer/data-items.jd128
-rw-r--r--docs/html/training/wearables/data-layer/events.jd3
-rw-r--r--docs/html/training/wearables/data-layer/messages.jd22
-rw-r--r--docs/html/training/wearables/watch-faces/configuration.jd19
11 files changed, 1562 insertions, 279 deletions
diff --git a/docs/html/training/location/display-address.jd b/docs/html/training/location/display-address.jd
index 621b082..516f14f 100644
--- a/docs/html/training/location/display-address.jd
+++ b/docs/html/training/location/display-address.jd
@@ -1,280 +1,468 @@
page.title=Displaying a Location Address
-
trainingnavtop=true
-
@jd:body
-
-
<div id="tb-wrapper">
-<div id="tb">
+ <div id="tb">
-<h2>This lesson teaches you to</h2>
-<ol>
- <li><a href="#DefineTask">Define the Address Lookup Task</a></li>
- <li><a href="#DisplayResults">Define a Method to Display the Results</a></li>
- <li><a href="#RunTask">Run the Lookup Task</a></li>
-</ol>
+ <h2>This lesson teaches you how to</h2>
+ <ol>
+ <li><a href="#connect">Get a Geographic Location</a></li>
+ <li><a href="#fetch-address">Define an Intent Service to Fetch the
+ Address</a></li>
+ <li><a href="#start-intent">Start the Intent Service</a></li>
+ <li><a href="#result-receiver">Receive the Geocoding Results</a></li>
+ </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="retrieve-current.html">Retrieving the Current Location</a>
- </li>
- <li>
- <a href="receive-location-updates.html">Receiving Location Updates</a>
- </li>
-</ul>
-<h2>Try it out</h2>
+ <h2>You should also read</h2>
+ <ul>
+ <li>
+ <a href="{@docRoot}google/play-services/setup.html">Setting up Google
+ Play Services</a>
+ </li>
+ <li>
+ <a href="retrieve-current.html">Getting the Last Known Location</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/LocationUpdates.zip" class="button">Download
- the sample app</a>
-<p class="filename">LocationUpdates.zip</p>
+ <ul>
+ <li>
+ <a href="https://github.com/googlesamples/android-play-location/tree/master/LocationAddress" class="external-link">LocationAddress</a>
+ </li>
+ </ul>
+ </div>
</div>
-</div>
-</div>
+<p>The lessons <a href="retrieve-current.html">Getting the Last Known
+ Location</a> and <a href="receive-location-updates.html">Receiving Location
+ Updates</a> describe how to get the user's location in the form of a
+ {@link android.location.Location} object that contains latitude and longitude
+ coordinates. Although latitude and longitude are useful for calculating
+ distance or displaying a map position, in many cases the address of the
+ location is more useful. For example, if you want to let your users know where
+ they are or what is close by, a street address is more meaningful than the
+ geographic coordinates (latitude/longitude) of the location.</p>
+
+<p>Using the {@link android.location.Geocoder} class in the Android framework
+ location APIs, you can convert an address to the corresponding geographic
+ coordinates. This process is called <em>geocoding</em>. Alternatively, you can
+ convert a geographic location to an address. The address lookup feature is
+ also known as <em>reverse geocoding</em>.</p>
+
+<p>This lesson shows you how to use the
+ {@link android.location.Geocoder#getFromLocation getFromLocation()} method to
+ convert a geographic location to an address. The method returns an estimated
+ street address corresponding to a given latitude and longitude.</p>
+
+<h2 id="connect">Get a Geographic Location</h2>
+
+<p>The last known location of the device is a useful starting point for the
+ address lookup feature. The lesson on
+ <a href="retrieve-current.html">Getting the Last Known Location</a> shows you
+ how to use the
+ <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>
+ method provided by the
+ <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
+ location provider</a> to find the latest location of the device.</p>
+
+<p>To access the fused location provider, 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>
+
+<p>In order for the fused location provider to retrieve a precise street
+ address, set the location permission in your app manifest to
+ {@code ACCESS_FINE_LOCATION}, as shown in the following example:</p>
-<p>
- The lessons <a href="retrieve-current.html">Retrieving the Current Location</a> and
- <a href="receive-location-updates.html">Receiving Location Updates</a> describe how to get the
- user's current location in the form of a {@link android.location.Location} object that
- contains latitude and longitude coordinates. Although latitude and longitude are useful for
- calculating distance or displaying a map position, in many cases the address of the location is
- more useful.
-</p>
-<p>
- The Android platform API provides a feature that returns an estimated street addresses for
- latitude and longitude values. This lesson shows you how to use this address lookup feature.
-</p>
-<p class="note">
- <strong>Note:</strong> Address lookup requires a backend service that is not included in the
- core Android framework. If this backend service is not available,
- {@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()} returns an empty
- list. The helper method {@link android.location.Geocoder#isPresent isPresent()}, available
- in API level 9 and later, checks to see if the backend service is available.
-</p>
-<p>
- The snippets in the following sections assume that your app has already retrieved the
- current location and stored it as a {@link android.location.Location} object in the global
- variable {@code mLocation}.
-</p>
-<!--
- Define the address lookup task
--->
-<h2 id="DefineTask">Define the Address Lookup Task</h2>
-<p>
-To get an address for a given latitude and longitude, call
-{@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()}, which returns a
-list of addresses. The method is synchronous, and may take a long time to do its work, so you
-should call the method from the {@link android.os.AsyncTask#doInBackground
-doInBackground()} method of an {@link android.os.AsyncTask}.
-</p>
-<p>
-While your app is getting the address, display an indeterminate activity
-indicator to show that your app is working in the background. Set the indicator's initial state
-to {@code android:visibility="gone"}, to make it invisible and remove it from the layout
-hierarchy. When you start the address lookup, you set its visibility to "visible".
-</p>
-<p>
-The following snippet shows how to add an indeterminate {@link android.widget.ProgressBar} to
-your layout file:
-</p>
<pre>
-&lt;ProgressBar
-android:id="&#64;+id/address_progress"
-android:layout_width="wrap_content"
-android:layout_height="wrap_content"
-android:layout_centerHorizontal="true"
-android:indeterminate="true"
-android:visibility="gone" /&gt;
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.gms.location.sample.locationupdates" &gt;
+
+ &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
+&lt;/manifest&gt;
</pre>
-<p>
-To create the background task, define a subclass of {@link android.os.AsyncTask} that calls
-{@link android.location.Geocoder#getFromLocation getFromLocation()} and returns an address.
-Define a {@link android.widget.TextView} object {@code mAddress} to contain the returned
-address, and a {@link android.widget.ProgressBar} object that allows you to control the
-indeterminate activity indicator. For example:
-</p>
+
+<h2 id="fetch-address">Define an Intent Service to Fetch the Address</h2>
+
+<p>The {@link android.location.Geocoder#getFromLocation getFromLocation()}
+ method provided by the {@link android.location.Geocoder} class accepts a
+ latitude and longitude, and returns a list of addresses. The method is
+ synchronous, and may take a long time to do its work, so you should not call
+ it from the main, user interface (UI) thread of your app.</p>
+
+<p>The {@link android.app.IntentService IntentService} class provides a
+ structure for running a task on a background thread. Using this class, you can
+ handle a long-running operation without affecting your UI's responsiveness.
+ Note that the {@link android.os.AsyncTask AsyncTask} class also allows you to
+ perform background operations, but it's designed for short operations. An
+ {@link android.os.AsyncTask AsyncTask} shouldn't keep a reference to the UI if
+ the activity is recreated, for example when the device is rotated. In
+ contrast, an {@link android.app.IntentService IntentService} doesn't need to
+ be cancelled when the activity is rebuilt.</p>
+
+<p>Define a {@code FetchAddressIntentService} class that extends
+ {@link android.app.IntentService}. This class is your address lookup service.
+ The intent service handles an intent asynchronously on a worker thread, and
+ stops itself when it runs out of work. The intent extras provide the data
+ needed by the service, including a {@link android.location.Location} object
+ for conversion to an address, and a {@link android.os.ResultReceiver} object
+ to handle the results of the address lookup. The service uses a {@link
+ android.location.Geocoder} to fetch the address for the location, and sends
+ the results to the {@link android.os.ResultReceiver}.</p>
+
+<h3>Define the Intent Service in your App Manifest</h3>
+
+<p>Add an entry to your app manifest defining the intent service:</p>
+
<pre>
-public class MainActivity extends FragmentActivity {
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.gms.location.sample.locationaddress" &gt;
+ &lt;application
+ ...
+ &lt;service
+ android:name=".FetchAddressIntentService"
+ android:exported="false"/&gt;
+ &lt;/application&gt;
...
- private TextView mAddress;
- private ProgressBar mActivityIndicator;
+&lt;/manifest&gt;
+</pre>
+
+<p class="note"><strong>Note:</strong> The {@code &lt;service&gt;} element in
+ the manifest doesn't need to include an intent filter, because your main
+ activity creates an explicit intent by specifying the name of the class to use
+ for the intent.</p>
+
+<h3>Create a Geocoder</h3>
+
+<p>The process of converting a geographic location to an address is called
+ <em>reverse geocoding</em>. To perform the main work of the intent service,
+ that is, your reverse geocoding request, implement
+ {@link android.app.IntentService#onHandleIntent onHandleIntent()} within the
+ {@code FetchAddressIntentService} class. Create a
+ {@link android.location.Geocoder} object to handle the reverse geocoding.</p>
+
+<p>A locale represents a specific geographical or linguistic region. Locale
+ objects are used to adjust the presentation of information, such as numbers or
+ dates, to suit the conventions in the region represented by the locale. Pass a
+ <a href="{@docRoot}reference/java/util/Locale.html">{@code Locale}</a> object
+ to the {@link android.location.Geocoder} object, to ensure that the resulting
+ address is localized to the user's geographic region.</p>
+
+<pre>
+&#64;Override
+protected void onHandleIntent(Intent intent) {
+ Geocoder geocoder = new Geocoder(this, Locale.getDefault());
...
- &#64;Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+}
+</pre>
+
+<h3 id="retrieve-street-address">Retrieve the street address data</h3>
+
+<p>The next step is to retrieve the street address from the geocoder, handle
+ any errors that may occur, and send the results back to the activity that
+ requested the address. To report the results of the geocoding
+ process, you need two numeric constants that indicate success or failure.
+ Define a {@code Constants} class to contain the values, as shown in this code
+ snippet:</p>
+
+<pre>
+public final class Constants {
+ public static final int SUCCESS_RESULT = 0;
+ public static final int FAILURE_RESULT = 1;
+ public static final String PACKAGE_NAME =
+ "com.google.android.gms.location.sample.locationaddress";
+ public static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";
+ public static final String RESULT_DATA_KEY = PACKAGE_NAME +
+ ".RESULT_DATA_KEY";
+ public static final String LOCATION_DATA_EXTRA = PACKAGE_NAME +
+ ".LOCATION_DATA_EXTRA";
+}
+</pre>
+
+<p>To get a street address corresponding to a geographical location, call
+ {@link android.location.Geocoder#getFromLocation getFromLocation()},
+ passing it the latitude and longitude from the location object, and the
+ maximum number of addresses you want returned. In this case, you want just one
+ address. The geocoder returns an array of addresses. If no addresses were
+ found to match the given location, it returns an empty list. If there is no
+ backend geocoding service available, the geocoder returns null.</p>
+
+<p>Check for the following errors as shown in the code sample below. If an error
+ occurs, place the corresponding error message in the {@code errorMessage}
+ variable, so you can send it back to the requesting activity:</p>
+
+<ul>
+ <li><strong>No location data provided</strong> - The intent extras do not
+ include the {@link android.location.Location} object required for reverse
+ geocoding.</li>
+ <li><strong>Invalid latitude or longitude used</strong> - The latitude
+ and/or longitude values provided in the {@link android.location.Location}
+ object are invalid.</li>
+ <li><strong>No geocoder available</strong> - The background geocoding service
+ is not available, due to a network error or IO exception.</li>
+ <li><strong>Sorry, no address found</strong> - The geocoder could not find an
+ address for the given latitude/longitude.</li>
+</ul>
+
+<p>To get the individual lines of an address object, use the
+ {@link android.location.Address#getAddressLine getAddressLine()}
+ method provided by the {@link android.location.Address} class. Then join the
+ lines into a list of address fragments ready to return to the activity that
+ requested the address.</p>
+
+<p>To send the results back to the requesting activity, call the
+ {@code deliverResultToReceiver()} method (defined in
+ <a href="#return-address">Return the address to the requestor</a>). The
+ results consist of the previously-mentioned numeric success/failure code and
+ a string. In the case of a successful reverse geocoding, the string contains
+ the address. In the case of a failure, the string contains the error message,
+ as shown in the code sample below:</p>
+
+<pre>
+&#64;Override
+protected void onHandleIntent(Intent intent) {
+ String errorMessage = "";
+
+ // Get the location passed to this service through an extra.
+ Location location = intent.getParcelableExtra(
+ Constants.LOCATION_DATA_EXTRA);
+
...
- mAddress = (TextView) findViewById(R.id.address);
- mActivityIndicator =
- (ProgressBar) findViewById(R.id.address_progress);
+
+ List&lt;Address&gt; addresses = null;
+
+ try {
+ addresses = geocoder.getFromLocation(
+ location.getLatitude(),
+ location.getLongitude(),
+ // In this sample, get just a single address.
+ 1);
+ } catch (IOException ioException) {
+ // Catch network or other I/O problems.
+ errorMessage = getString(R.string.service_not_available);
+ Log.e(TAG, errorMessage, ioException);
+ } catch (IllegalArgumentException illegalArgumentException) {
+ // Catch invalid latitude or longitude values.
+ errorMessage = getString(R.string.invalid_lat_long_used);
+ Log.e(TAG, errorMessage + ". " +
+ "Latitude = " + location.getLatitude() +
+ ", Longitude = " +
+ location.getLongitude(), illegalArgumentException);
}
- ...
- /**
- * A subclass of AsyncTask that calls getFromLocation() in the
- * background. The class definition has these generic types:
- * Location - A {@link android.location.Location} object containing
- * the current location.
- * Void - indicates that progress units are not used
- * String - An address passed to onPostExecute()
- */
- private class GetAddressTask extends
- AsyncTask&lt;Location, Void, String&gt; {
- Context mContext;
- public GetAddressTask(Context context) {
- super();
- mContext = context;
+
+ // Handle case where no address was found.
+ if (addresses == null || addresses.size() == 0) {
+ if (errorMessage.isEmpty()) {
+ errorMessage = getString(R.string.no_address_found);
+ Log.e(TAG, errorMessage);
}
- ...
- /**
- * Get a Geocoder instance, get the latitude and longitude
- * look up the address, and return it
- *
- * &#64;params params One or more Location objects
- * &#64;return A string containing the address of the current
- * location, or an empty string if no address can be found,
- * or an error message
- */
- &#64;Override
- protected String doInBackground(Location... params) {
- Geocoder geocoder =
- new Geocoder(mContext, Locale.getDefault());
- // Get the current location from the input parameter list
- Location loc = params[0];
- // Create a list to contain the result address
- List&lt;Address&gt; addresses = null;
- try {
- /*
- * Return 1 address.
- */
- addresses = geocoder.getFromLocation(loc.getLatitude(),
- loc.getLongitude(), 1);
- } catch (IOException e1) {
- Log.e("LocationSampleActivity",
- "IO Exception in getFromLocation()");
- e1.printStackTrace();
- return ("IO Exception trying to get address");
- } catch (IllegalArgumentException e2) {
- // Error message to post in the log
- String errorString = "Illegal arguments " +
- Double.toString(loc.getLatitude()) +
- " , " +
- Double.toString(loc.getLongitude()) +
- " passed to address service";
- Log.e("LocationSampleActivity", errorString);
- e2.printStackTrace();
- return errorString;
- }
- // If the reverse geocode returned an address
- if (addresses != null &amp;&amp; addresses.size() &gt; 0) {
- // Get the first address
- Address address = addresses.get(0);
- /*
- * Format the first line of address (if available),
- * city, and country name.
- */
- String addressText = String.format(
- "&#037;s, &#037;s, &#037;s",
- // If there's a street address, add it
- address.getMaxAddressLineIndex() &gt; 0 ?
- address.getAddressLine(0) : "",
- // Locality is usually a city
- address.getLocality(),
- // The country of the address
- address.getCountryName());
- // Return the text
- return addressText;
- } else {
- return "No address found";
- }
+ deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
+ } else {
+ Address address = addresses.get(0);
+ ArrayList&lt;String&gt; addressFragments = new ArrayList&lt;String&gt;();
+
+ // Fetch the address lines using {@code getAddressLine},
+ // join them, and send them to the thread.
+ for(int i = 0; i < address.getMaxAddressLineIndex(); i++) {
+ addressFragments.add(address.getAddressLine(i));
}
- ...
+ Log.i(TAG, getString(R.string.address_found));
+ deliverResultToReceiver(Constants.SUCCESS_RESULT,
+ TextUtils.join(System.getProperty("line.separator"),
+ addressFragments));
}
- ...
}
</pre>
-<p>
-The next section shows you how to display the address in the user interface.
-</p>
-<!-- Define a method to display the address -->
-<h2 id="DisplayResults">Define a Method to Display the Results</h2>
-<p>
- {@link android.os.AsyncTask#doInBackground doInBackground()} returns the result of the address
- lookup as a {@link java.lang.String}. This value is passed to
- {@link android.os.AsyncTask#onPostExecute onPostExecute()}, where you do further processing
- on the results. Since {@link android.os.AsyncTask#onPostExecute onPostExecute()}
- runs on the UI thread, it can update the user interface; for example, it can turn off the
- activity indicator and display the results to the user:
+
+<h3 id="return-address">Return the address to the requestor</h3>
+
+<p>The final thing the intent service must do is send the address back to a
+ {@link android.os.ResultReceiver} in the activity that started the service.
+ The {@link android.os.ResultReceiver} class allows you to send a
+ numeric result code as well as a message containing the result data. The
+ numeric code is useful for reporting the success or failure of the geocoding
+ request. In the case of a successful reverse geocoding, the message contains
+ the address. In the case of a failure, the message contains some text
+ describing the reason for failure.</p>
+
+<p>You have already retrieved the address from the geocoder, trapped any errors
+ that may occur, and called the {@code deliverResultToReceiver()} method. Now
+ you need to define the {@code deliverResultToReceiver()} method that sends
+ a result code and message bundle to the result receiver.</p>
+
+<p>For the result code, use the value that you've passed to the
+ {@code deliverResultToReceiver()} method in the {@code resultCode} parameter.
+ To construct the message bundle, concatenate the {@code RESULT_DATA_KEY}
+ constant from your {@code Constants} class (defined in
+ <a href="#retrieve-street-address">Retrieve the street address data</a>) and
+ the value in the {@code message} parameter passed to the
+ {@code deliverResultToReceiver()} method, as shown in the following sample:
</p>
+
<pre>
- private class GetAddressTask extends
- AsyncTask&lt;Location, Void, String&gt; {
- ...
- /**
- * A method that's called once doInBackground() completes. Turn
- * off the indeterminate activity indicator and set
- * the text of the UI element that shows the address. If the
- * lookup failed, display the error message.
- */
- &#64;Override
- protected void onPostExecute(String address) {
- // Set activity indicator visibility to "gone"
- mActivityIndicator.setVisibility(View.GONE);
- // Display the results of the lookup.
- mAddress.setText(address);
- }
- ...
+public class FetchAddressIntentService extends IntentService {
+ protected ResultReceiver mReceiver;
+ ...
+ private void deliverResultToReceiver(int resultCode, String message) {
+ Bundle bundle = new Bundle();
+ bundle.putString(Constants.RESULT_DATA_KEY, message);
+ mReceiver.send(resultCode, bundle);
}
+}
</pre>
-<p>
- The final step is to run the address lookup.
-</p>
-<!-- Get and display the address -->
-<h2 id="RunTask">Run the Lookup Task</h2>
-<p>
- To get the address, call {@link android.os.AsyncTask#execute execute()}. For example, the
- following snippet starts the address lookup when the user clicks the "Get Address" button:
-</p>
+
+<h2 id="start-intent">Start the Intent Service</h2>
+
+<p>The intent service, as defined in the previous section, runs in the
+ background and is responsible for fetching the address corresponding to a
+ given geographic location. When you start the service, the Android framework
+ instantiates and starts the service if it isn't already running, and creates a
+ process if needed. If the service is already running then it remains running.
+ Because the service extends {@link android.app.IntentService IntentService},
+ it shuts down automatically when all intents have been processed.</p>
+
+<p>Start the service from your app's main activity,
+ and create an {@link android.content.Intent} to pass data to the service. You
+ need an <em>explicit</em> intent, because you want only your service
+ to respond to the intent. For more information, see
+ <a href="{@docRoot}guide/components/intents-filters.html#Types">Intent
+ Types</a>.</p>
+
+<p>To create an explicit intent, specify the name of the
+ class to use for the service: {@code FetchAddressIntentService.class}.
+ Pass two pieces of information in the intent extras:</p>
+
+<ul>
+ <li>A {@link android.os.ResultReceiver} to handle the results of the address
+ lookup.</li>
+ <li>A {@link android.location.Location} object containing the latitude and
+ longitude that you want to convert to an address.</li>
+</ul>
+
+<p>The following code sample shows you how to start the intent service:</p>
+
<pre>
-public class MainActivity extends FragmentActivity {
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
+
+ protected Location mLastLocation;
+ private AddressResultReceiver mResultReceiver;
...
- /**
- * The "Get Address" button in the UI is defined with
- * android:onClick="getAddress". The method is invoked whenever the
- * user clicks the button.
- *
- * &#64;param v The view object associated with this method,
- * in this case a Button.
- */
- public void getAddress(View v) {
- // Ensure that a Geocoder services is available
- if (Build.VERSION.SDK_INT &gt;=
- Build.VERSION_CODES.GINGERBREAD
- &amp;&amp;
- Geocoder.isPresent()) {
- // Show the activity indicator
- mActivityIndicator.setVisibility(View.VISIBLE);
- /*
- * Reverse geocoding is long-running and synchronous.
- * Run it on a background thread.
- * Pass the current location to the background task.
- * When the task finishes,
- * onPostExecute() displays the address.
- */
- (new GetAddressTask(this)).execute(mLocation);
+
+ protected void startIntentService() {
+ Intent intent = new Intent(this, FetchAddressIntentService.class);
+ intent.putExtra(Constants.RECEIVER, mResultReceiver);
+ intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
+ startService(intent);
+ }
+}
+</pre>
+
+<p>Call the above {@code startIntentService()} method when the
+ user takes an action that requires a geocoding address lookup. For example,
+ the user may press a <em>Fetch address</em> button on your app's UI. Before
+ starting the intent service, you need to check that the connection to Google
+ Play services is present. The following code snippet shows the call to the
+ {@code startIntentService()} method in the button handler:</p>
+
+<pre>
+public void fetchAddressButtonHandler(View view) {
+ // Only start the service to fetch the address if GoogleApiClient is
+ // connected.
+ if (mGoogleApiClient.isConnected() && mLastLocation != null) {
+ startIntentService();
+ }
+ // If GoogleApiClient isn't connected, process the user's request by
+ // setting mAddressRequested to true. Later, when GoogleApiClient connects,
+ // launch the service to fetch the address. As far as the user is
+ // concerned, pressing the Fetch Address button
+ // immediately kicks off the process of getting the address.
+ mAddressRequested = true;
+ updateUIWidgets();
+}
+</pre>
+
+<p>You must also start the intent service when the connection to Google Play
+ services is established, if the user has already clicked the button on your
+ app's UI. The following code snippet shows the call to the
+ {@code startIntentService()} method in the
+ <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
+ callback provided by the Google API Client:</p>
+
+<pre>
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
+ ...
+ &#64;Override
+ public void onConnected(Bundle connectionHint) {
+ // Gets the best and most recent location currently available,
+ // which may be null in rare cases when a location is not available.
+ mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
+ mGoogleApiClient);
+
+ if (mLastLocation != null) {
+ // Determine whether a Geocoder is available.
+ if (!Geocoder.isPresent()) {
+ Toast.makeText(this, R.string.no_geocoder_available,
+ Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ if (mAddressRequested) {
+ startIntentService();
+ }
}
- ...
}
+}
+</pre>
+
+<h2 id="result-receiver">Receive the Geocoding Results</h2>
+
+<p>The intent service has handled the geocoding request, and uses a
+ {@link android.os.ResultReceiver} to return the results to the activity that
+ made the request. In the activity that makes the request, define an
+ {@code AddressResultReceiver} that extends {@link android.os.ResultReceiver}
+ to handle the response from {@code FetchAddressIntentService}.</p>
+
+<p>The result includes a numeric result code (<code>resultCode</code>) as well
+ as a message containing the result data (<code>resultData</code>). If the
+ reverse geocoding process was successful, the <code>resultData</code> contains
+ the address. In the case of a failure, the <code>resultData</code> contains
+ text describing the reason for failure. For details of the possible errors,
+ see <a href="#return-address">Return the address to the requestor</a>.</p>
+
+<p>Override the
+ {@link android.os.ResultReceiver#onReceiveResult onReceiveResult()} method
+ to handle the results delivered to the result receiver, as shown in the
+ following code sample:</p>
+
+<pre>
+public class MainActivity extends ActionBarActivity implements
+ ConnectionCallbacks, OnConnectionFailedListener {
...
+ class AddressResultReceiver extends ResultReceiver {
+ public AddressResultReceiver(Handler handler) {
+ super(handler);
+ }
+
+ &#64;Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+
+ // Display the address string
+ // or an error message sent from the intent service.
+ mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
+ displayAddressOutput();
+
+ // Show a toast message if an address was found.
+ if (resultCode == Constants.SUCCESS_RESULT) {
+ showToast(getString(R.string.address_found));
+ }
+
+ }
+ }
}
</pre>
-<p>
- The next lesson, <a href="geofencing.html">Creating and Monitoring Geofences</a>, demonstrates
- how to define locations of interest called <b>geofences</b> and how to use geofence monitoring
- to detect the user's proximity to a location of interest.
-</p>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0fcfb9c..f5999a5 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -437,6 +437,35 @@ include the action bar on devices running Android 2.1 or higher."
</li>
</ul>
</li>
+
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot?>training/transitions/index.html"
+ description=
+ "How to animate state changes in a view hierarchy using transitions."
+ >Animating Views Using Scenes and Transitions</a>
+ </div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>training/transitions/overview.html">
+ The Transitions Framework
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/transitions/scenes.html">
+ Creating a Scene
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/transitions/transitions.html">
+ Applying a Transition
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/transitions/custom-transitions.html">
+ Creating Custom Transitions
+ </a>
+ </li>
+
+ </ul>
+ </li>
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/animation/index.html"
description=
diff --git a/docs/html/training/transitions/custom-transitions.jd b/docs/html/training/transitions/custom-transitions.jd
new file mode 100644
index 0000000..b64daae
--- /dev/null
+++ b/docs/html/training/transitions/custom-transitions.jd
@@ -0,0 +1,189 @@
+page.title=Creating Custom Transitions
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#Extend">Extend the Transition Class</a></li>
+ <li><a href="#CaptureProperties">Capture View Property Values</a></li>
+ <li><a href="#CreateAnimator">Create a Custom Animator</a></li>
+ <li><a href="#Apply">Apply a Custom Transition</a></li>
+</ol>
+</div>
+</div>
+
+<p>A custom transition enables you to create an animation that is not available from any of
+the built-in transition classes. For example, you can define a custom transition that turns
+the foreground color of text and input fields to gray to indicate that the fields are disabled
+in the new screen. This type of change helps users see the fields you disabled.</p>
+
+<p>A custom transition, like one of the built-in transition types, applies animations to
+child views of both the starting and ending scenes. Unlike built-in transition types,
+however, you have to provide the code that captures property values and generates animations.
+You may also want to define a subset of target views for your animation.</p>
+
+<p>This lesson teaches you to capture property values and generate animations to create
+custom transitions.</p>
+
+
+
+<h2 id="Extend">Extend the Transition Class</h2>
+
+<p>To create a custom transition, add a class to your project that extends the {@link
+android.transition.Transition} class and override the methods shown in the following snippet:</p>
+
+<pre>
+public class CustomTransition extends Transition {
+
+ &#64;Override
+ public void captureStartValues(TransitionValues values) {}
+
+ &#64;Override
+ public void captureEndValues(TransitionValues values) {}
+
+ &#64;Override
+ public Animator createAnimator(ViewGroup sceneRoot,
+ TransitionValues startValues,
+ TransitionValues endValues) {}
+}
+</pre>
+
+<p>The following sections explain how to override these methods.</p>
+
+
+
+<h2 id="CaptureProperties">Capture View Property Values</h2>
+
+<p>Transition animations use the property animation system described in
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>. Property
+animations change a view property between a starting and ending value over a specified
+period of time, so the framework needs to have both the starting and ending value of
+the property to construct the animation.</p>
+
+<p>However, a property animation usually needs only a small subset of all the view's property
+values. For example, a color animation needs color property values, while a movement
+animation needs position property values. Since the property values needed for an animation
+are specific to a transition, the transitions framework does not provide every property value
+to a transition. Instead, the framework invokes callback methods that allow a transition to
+capture only the property values it needs and store them in the framework.</p>
+
+
+<h3 id="StartingValues">Capturing Starting Values</h3>
+
+<p>To pass the starting view values to the framework, implement the
+{@link android.transition.Transition#captureStartValues captureStartValues(transitionValues)}
+method. The framework calls this method for every view in the starting scene. The method
+argument is a {@link android.transition.TransitionValues} object that contains a reference
+to the view and a {@link java.util.Map} instance in which you can store the view values you
+want. In your implementation, retrieve these property values and pass them back to the
+framework by storing them in the map.</p>
+
+<p>To ensure that the key for a property value does not conflict with other {@link
+android.transition.TransitionValues} keys, use the following naming scheme:</p>
+
+<pre>
+package_name:transition_name:property_name
+</pre>
+
+<p>The following snippet shows an implementation of the {@link
+android.transition.Transition#captureStartValues captureStartValues()} method:</p>
+
+<pre>
+public class CustomTransition extends Transition {
+
+ // Define a key for storing a property value in
+ // TransitionValues.values with the syntax
+ // package_name:transition_class:property_name to avoid collisions
+ private static final String PROPNAME_BACKGROUND =
+ "com.example.android.customtransition:CustomTransition:background";
+
+ &#64;Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ // Call the convenience method captureValues
+ captureValues(transitionValues);
+ }
+
+
+ // For the view in transitionValues.view, get the values you
+ // want and put them in transitionValues.values
+ private void captureValues(TransitionValues transitionValues) {
+ // Get a reference to the view
+ View view = transitionValues.view;
+ // Store its background property in the values map
+ transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground());
+ }
+ ...
+}
+</pre>
+
+
+<h3 id="EndingValues">Capture Ending Values</h3>
+
+<p>The framework calls the {@link android.transition.Transition#captureEndValues} method
+once for every target view in the ending scene. In all other respects, {@link
+android.transition.Transition#captureEndValues captureEndValues()} works the same as {@link
+android.transition.Transition#captureStartValues captureStartValues()}.</p>
+
+<p>The following code snippet shows an implementation of the {@link
+android.transition.Transition#captureEndValues captureEndValues()} method:</p>
+
+<pre>
+&#64;Override
+public void captureEndValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+}
+</pre>
+
+<p>In this example, both the {@link android.transition.Transition#captureStartValues
+captureStartValues()} and {@link android.transition.Transition#captureEndValues captureEndValues()}
+methods invoke <code>captureValues()</code> to retrieve and store values. The view property
+that <code>captureValues()</code> retrieves is the same, but it has different values in the
+starting and ending scenes. The framework maintains separate maps for the starting and ending
+states of a view.</p>
+
+
+
+<h2 id="CreateAnimator">Create a Custom Animator</h2>
+
+<p>To animate the changes to a view between its state in the starting scene and its state in
+the ending scene, you provide an animator by overriding the {@link
+android.transition.Transition#createAnimator createAnimator()} method. When the
+framework calls this method, it passes in the scene root view and the {@link
+android.transition.TransitionValues} objects that contain the starting and ending values
+you captured.</p>
+
+<p>The number of times the framework calls the {@link
+android.transition.Transition#createAnimator createAnimator()} method depends on the changes that
+occur between the starting and ending scenes. For example, consider a fade out/fade in animation
+implemented as a custom transition. If the starting scene has five targets of which two are
+removed from the ending scene, and the ending scene has the three targets from the starting
+scene plus a new target, then the framework calls {@link
+android.transition.Transition#createAnimator createAnimator()} six times: three of the calls
+animate the fading out and fading in of the targets that stay in both scene objects; two more calls
+animate the fading out of the targets removed from the ending scene; and one call
+animates the fading in of the new target in the ending scene.</p>
+
+<p>For target views that exist on both the starting and ending scenes, the framework provides
+a {@link android.transition.TransitionValues} object for both the <code>startValues</code> and
+<code>endValues</code> arguments. For target views that only exist in the starting or the
+ending scene, the framework provides a {@link android.transition.TransitionValues} object
+for the corresponding argument and <code>null</code> for the other.</p>
+
+<p>To implement the {@link android.transition.Transition#createAnimator} method when you create
+a custom transition, use the view property values you captured to create an {@link
+android.animation.Animator} object and return it to the framework. For an example implementation,
+see the <a
+href="{@docRoot}samples/CustomTransition/src/com.example.android.customtransition/ChangeColor.html">
+<code>ChangeColor</code></a> class in the <a href="{@docRoot}samples/CustomTransition/index.html">
+CustomTransition</a> sample. For more information about property animators, see
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>.</p>
+
+
+
+<h2 id="Apply">Apply a Custom Transition</h2>
+
+<p>Custom transitions work the same as built-in transitions. You can apply a custom transition
+using a transition manager, as described in <a
+href="{@docRoot}training/transitions/transitions.html#Apply">Applying a Transition</a>.</p>
diff --git a/docs/html/training/transitions/index.jd b/docs/html/training/transitions/index.jd
new file mode 100644
index 0000000..53faa01
--- /dev/null
+++ b/docs/html/training/transitions/index.jd
@@ -0,0 +1,80 @@
+page.title=Animating Views Using Scenes and Transitions
+
+@jd:body
+
+<!-- Sidebox -->
+<div id="tb-wrapper">
+<div id="tb">
+ <h2>Dependencies and Prerequisites</h2>
+ <ul>
+ <li>Android 4.4.2 (API level 19) or higher</li>
+ </ul>
+ <h2>You should also read</h2>
+ <ul>
+ <li><a href="{@docRoot}guide/topics/ui/how-android-draws.html">
+ How Android Draws Views</a></li>
+ </ul>
+ <h2>Try it out</h2>
+ <ul>
+ <li><a href="{@docRoot}samples/BasicTransition/index.html">BasicTransition</a> sample</li>
+ <li><a href="{@docRoot}samples/CustomTransition/index.html">CustomTransition</a> sample</li>
+ </ul>
+</div>
+</div>
+
+<!-- Video box -->
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=S3H7nJ4QaD8">
+<div>
+ <h3>Video</h3>
+ <p>DevBytes: Android 4.4 Transitions</p>
+</div>
+</a>
+
+<p>The user interface of an activity often changes in response to user input and other events.
+For example, an activity that contains a form where users can type search queries can hide
+the form when the user submits it and show a list of search results in its place.</p>
+
+<p>To provide visual continuity in these situations, you can animate changes between
+different view hierarchies in your user interface. These animations give users feedback on
+their actions and help them learn how your app works.</p>
+
+<p>Android includes the <em>transitions framework</em>, which enables you to easily
+animate changes between two view hierarchies. The framework animates the views at runtime by
+changing some of their property values over time. The framework includes built-in animations
+for common effects and lets you create custom animations and transition lifecycle callbacks.</p>
+
+<p>This class teaches you to use the built-in animations in the transitions framework to
+animate changes between view hierarchies. This class also covers how to create custom
+animations.</p>
+
+<p class="note"><strong>Note:</strong> For Android versions earlier than 4.4.2 (API level 19)
+but greater than or equal to Android 4.0 (API level 14), use the <code>animateLayoutChanges</code>
+attribute to animate layouts. To learn more, see
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a> and
+<a href="{@docRoot}training/animation/layout.html">Animating Layout Changes</a>.</p>
+
+
+<h2>Lessons</h2>
+
+<dl>
+<dt><a href="{@docRoot}training/transitions/overview.html">
+The Transitions Framework</a></dt>
+<dd>
+ Learn the main features and components of the transitions framework.
+</dd>
+<dt><a href="{@docRoot}training/transitions/scenes.html">
+Creating a Scene</a></dt>
+<dd>
+ Learn how to create a scene to store the state of a view hierarchy.
+</dd>
+<dt><a href="{@docRoot}training/transitions/transitions.html">
+Applying a Transition</a></dt>
+<dd>
+ Learn how to apply a transition between two scenes of a view hierarchy.
+</dd>
+<dt><a href="{@docRoot}training/transitions/custom-transitions.html">
+Creating Custom Transitions</a></dt>
+<dd>
+ Learn how to create other animation effects not included in the transitions framework.
+</dd>
+</dl>
diff --git a/docs/html/training/transitions/overview.jd b/docs/html/training/transitions/overview.jd
new file mode 100644
index 0000000..044cf16
--- /dev/null
+++ b/docs/html/training/transitions/overview.jd
@@ -0,0 +1,165 @@
+page.title=The Transitions Framework
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson covers</h2>
+<ol>
+ <li><a href="#Overview">Overview</a></li>
+ <li><a href="#Scenes">Scenes</a></li>
+ <li><a href="#Transitions">Transitions</a></li>
+ <li><a href="#Limitations">Limitations</a></li>
+</ol>
+</div>
+</div>
+
+<p>Animating your app's user interface provides more than just visual appeal. Animations
+highlight changes and provide visual cues that help users learn how your app works.</p>
+
+<p>To help you animate a change between one view hierarchy and another, Android provides the
+transitions framework. This framework applies one or more animations to all the views in the
+hierarchies as it changes between them.</p>
+
+<p>The framework has the following features:</p>
+
+<dl>
+<dt><em>Group-level animations</em></dt>
+<dd>Applies one or more animation effects to all of the views in a view hierarchy.</dd>
+<dt><em>Transition-based animation</em></dt>
+<dd>Runs animations based on the changes between starting and ending view property values.</dd>
+<dt><em>Built-in animations</em></dt>
+<dd>Includes predefined animations for common effects such as fade out or movement.</dd>
+
+<!-- Figure 1 - Transitions video -->
+<div style="float:right;margin-left:30px;margin-top:10px">
+<div class="framed-nexus5-port-span-5" style="clear:left;">
+<video class="play-on-hover" height="442" autoplay="" poster="">
+<source src="{@docRoot}images/transitions/transition_sample_video.mp4" type="video/mp4">
+<source src="{@docRoot}images/transitions/transition_sample_video.ogv" type="video/ogg">
+<source src="{@docRoot}images/transitions/transition_sample_video.webm" type="video/webm">
+</video>
+</div>
+<p class="img-caption" style="margin-top:7px;margin-bottom:0px">
+<strong>Figure 1.</strong> Visual cues using user interface animation.</p>
+<div style="margin-top:5px;margin-bottom:20px;font-size:10pt" class="video-instructions">&nbsp;</div>
+</div>
+
+<dt><em>Resource file support</em></dt>
+<dd>Loads view hierarchies and built-in animations from layout resource files.</dd>
+<dt><em>Lifecycle callbacks</em></dt>
+<dd>Defines callbacks that provide finer control over the animation and hierarchy change
+process.</dd>
+</dl>
+
+
+
+<h2 id="Overview">Overview</h2>
+
+<p>The example in Figure 1 shows how an animation provides visual cues to help the user. As the
+app changes from its search entry screen to its search results screen, it fades out views that
+are no longer in use and fades in new views.</p>
+
+<p>This animation is an example of using the transitions framework. The framework
+animates changes to all the views in two view hierarchies. A view hierarchy can be as simple
+as a single view or as complex as a {@link android.view.ViewGroup} containing an elaborate
+tree of views. The framework animates each view by changing one or more of its property values
+over time between the initial or <em>starting</em> view hierarchy and the final or <em>ending</em>
+view hierarchy.</p>
+
+<p>The transitions framework works in parallel with view hierarchies and animations. The
+purpose of the framework is to store the state of view hierarchies, change between these
+hierarchies in order to modify the appearance of the device screen, and animate the change by
+storing and applying animation definitions.</p>
+
+<p>The diagram in Figure 2 illustrates the relationship between view hierarchies, framework
+objects, and animations:</p>
+
+<!-- Figure 2 - diagram -->
+<img src="{@docRoot}images/transitions/transitions_diagram.png"
+ width="506" height="234" alt="" style="margin-top:7px" />
+<p class="img-caption"><strong>Figure 2.</strong> Relationships in the transitions framework.</p>
+
+<p>The transitions framework provides abstractions for scenes, transitions, and transition
+managers. These are described in detail in the following sections. To use the framework, you
+create scenes for the view hierarchies in your app that you plan to change between. Next, you
+create a transition for each animation you want to use. To start the animation between two
+view hierarchies, you use a transition manager specifying the transition to use and the ending
+scene. This procedure is described in detail in the remaining lessons in this class.</p>
+
+
+
+<h2 id="Scenes">Scenes</h2>
+
+<p>A scene stores the state of a view hierarchy, including all its views and their property
+values. A view hierarchy can be a simple view or a complex tree of views and child layouts.
+Storing the view hierarchy state in a scene enables you to transition into that state from
+another scene. The framework provides the {@link android.transition.Scene} class to represent
+a scene.</p>
+
+<p>The transitions framework lets you create scenes from layout resource files or from
+{@link android.view.ViewGroup} objects in your code. Creating a scene in your code is useful
+if you generated a view hierarchy dynamically or if you are modifying it at runtime.</p>
+
+<p>In most cases, you do not create a starting scene explicitly. If you have applied a
+transition, the framework uses the previous ending scene as the starting scene for any
+subsequent transitions. If you have not applied a transition, the framework collects information
+about the views from the current state of the screen.</p>
+
+<p>A scene can also define its own actions that run when you make a scene change. For example,
+this feature is useful for cleaning up view settings after you transition to a scene.</p>
+
+<p>In addition to the view hierarchy and its property values, a scene also stores a reference
+to the parent of the view hierarchy. This root view is called a <strong>scene root</strong>.
+Changes to the scene and animations that affect the scene occur within the scene root.</p>
+
+<p>To learn how to create scenes, see
+<a href="{@docRoot}training/transitions/scenes.html">Creating a Scene</a>.</p>
+
+
+
+<h2 id="Transitions">Transitions</h2>
+
+<p>In the transitions framework, animations create a series of frames that depict a change
+between the view hierarchies in the starting and ending scenes. Information about the animation
+is stored in a {@link android.transition.Transition} object. To run the animation, you apply the
+transition using a {@link android.transition.TransitionManager} instance. The framework can
+transition between two different scenes or transition to a different state for the current
+scene.</p>
+
+<p>The framework includes a set of built-in transitions for commonly-used animation effects,
+such as fading and resizing views. You can also define your own custom transitions to create
+an animation effect using the APIs in the animations framework. The transitions framework also
+enables you to combine different animation effects in a transition set that contains a group
+of individual built-in or custom transitions.</p>
+
+<p>The transition lifecycle is similar to the activity lifecycle, and it represents the
+transition states that the framework monitors between the start and the completion of an
+animation. At important lifecycle states, the framework invokes callback methods that you can
+implement to make adjustments to your user interface at different phases of the transition.</p>
+
+<p>To learn more about transitions, see
+<a href="{@docRoot}training/transitions/transitions.html">Applying a Transition</a> and
+<a href="{@docRoot}training/transitions/custom-transitions.html">Creating Custom
+Transitions</a>.</p>
+
+
+
+<h2 id="Limitations">Limitations</h2>
+
+<p>This section lists some known limitations of the transitions framework:</p>
+
+<ul>
+<li>Animations applied to a {@link android.view.SurfaceView} may not appear correctly.
+{@link android.view.SurfaceView} instances are updated from a non-UI thread, so the updates
+may be out of sync with the animations of other views.</li>
+<li>Some specific transition types may not produce the desired animation effect when applied
+to a {@link android.view.TextureView}.</li>
+<li>Classes that extend {@link android.widget.AdapterView}, such as
+{@link android.widget.ListView}, manage their child views in ways that are incompatible with
+the transitions framework. If you try to animate a view based on
+{@link android.widget.AdapterView}, the device display may hang.</li>
+<li>If you try to resize a {@link android.widget.TextView} with an animation, the text will
+pop to a new location before the object has completely resized. To avoid this problem, do not
+animate the resizing of views that contain text.</li>
+</ul>
diff --git a/docs/html/training/transitions/scenes.jd b/docs/html/training/transitions/scenes.jd
new file mode 100644
index 0000000..4bf7d0e
--- /dev/null
+++ b/docs/html/training/transitions/scenes.jd
@@ -0,0 +1,211 @@
+page.title=Creating a Scene
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#FromLayout">Create a Scene From a Layout Resource</a></li>
+ <li><a href="#FromCode">Create a Scene in Your Code</a></li>
+ <li><a href="#Actions">Create Scene Actions</a></li>
+</ol>
+</div>
+</div>
+
+<p>Scenes store the state of a view hierarchy, including all its views and their property
+values. The transitions framework can run animations between a starting and an ending scene.
+The starting scene is often determined automatically from the current state of the user
+interface. For the ending scene, the framework enables you to create a scene from a layout
+resource file or from a group of views in your code.</p>
+
+<p>This lesson shows you how to create scenes in your app and how to define scene actions.
+The next lesson shows you how to transition between two scenes.</p>
+
+<p class="note"><strong>Note:</strong> The framework can animate changes in a single view
+hierarchy without using scenes, as described in
+<a href="{@docRoot}training/transitions/transitions.html#NoScenes">Apply a Transition Without
+Scenes</a>. However, understanding this lesson is essential to work with transitions.</p>
+
+
+
+<h2 id="FromLayout">Create a Scene From a Layout Resource</h2>
+
+<p>You can create a {@link android.transition.Scene} instance directly from a layout resource
+file. Use this technique when the view hierarchy in the file is mostly static. The resulting
+scene represents the state of the view hierarchy at the time you created the
+{@link android.transition.Scene} instance. If you change the view hierarchy, you have to
+recreate the scene. The framework creates the scene from the entire view hierarchy in the
+file; you can not create a scene from part of a layout file.</p>
+
+<p>To create a {@link android.transition.Scene} instance from a layout resource file, retrieve
+the scene root from your layout as a {@link android.view.ViewGroup} instance and then call the
+{@link android.transition.Scene#getSceneForLayout Scene.getSceneForLayout()} method with the
+scene root and the resource ID of the layout file that contains the view hierarchy for the
+scene.</p>
+
+<h3>Define Layouts for Scenes</h3>
+
+<p>The code snippets in the rest of this section show you how to create two different scenes
+with the same scene root element. The snippets also demonstrate that you can load multiple
+unrelated {@link android.transition.Scene} objects without implying that they are related to
+each other.</p>
+
+<p>The example consists of the following layout definitions:</p>
+
+<ul>
+<li>The main layout of an activity with a text label and a child layout.</li>
+<li>A relative layout for the first scene with two text fields.</li>
+<li>A relative layout for the second scene with the same two text fields in different order.</li>
+</ul>
+
+<p>The example is designed so that all of the animation occurs within the child layout of the
+main layout for the activity. The text label in the main layout remains static.</p>
+
+<p>The main layout for the activity is defined as follows:</p>
+
+<p class="code-caption">res/layout/activity_main.xml</p>
+
+<pre>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/master_layout">
+ &lt;TextView
+ android:id="@+id/title"
+ ...
+ android:text="Title"/>
+ &lt;FrameLayout
+ android:id="@+id/scene_root">
+ &lt;include layout="@layout/a_scene" />
+ &lt;/FrameLayout>
+&lt;/LinearLayout>
+</pre>
+
+<p>This layout definition contains a text field and a child layout for the scene root. The
+layout for the first scene is included in the main layout file. This allows the app to display
+it as part of the initial user interface and also to load it into a scene, since the framework
+can load only a whole layout file into a scene.</p>
+
+<p>The layout for the first scene is defined as follows:</p>
+
+<p class="code-caption">res/layout/a_scene.xml</p>
+
+<pre>
+&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/scene_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ &lt;TextView
+ android:id="@+id/text_view1
+ android:text="Text Line 1" />
+ &lt;TextView
+ android:id="@+id/text_view2
+ android:text="Text Line 2" />
+&lt;/RelativeLayout>
+</pre>
+
+<p>The layout for the second scene contains the same two text fields (with the same IDs)
+placed in a different order and is defined as follows:</p>
+
+<p class="code-caption">res/layout/another_scene.xml</p>
+
+<pre>
+&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/scene_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ &lt;TextView
+ android:id="@+id/text_view2
+ android:text="Text Line 2" />
+ &lt;TextView
+ android:id="@+id/text_view1
+ android:text="Text Line 1" />
+&lt;/RelativeLayout>
+</pre>
+
+<h3>Generate Scenes from Layouts</h3>
+
+<p>After you create definitions for the two relative layouts, you can obtain an scene for
+each of them. This enables you to later transition between the two UI configurations.
+To obtain a scene, you need a reference to the scene root and the layout resource ID.</p>
+
+<p>The following code snippet shows you how to get a reference to the scene root and create
+two {@link android.transition.Scene} objects from the layout files:</p>
+
+<pre>
+Scene mAScene;
+Scene mAnotherScene;
+
+// Create the scene root for the scenes in this app
+mSceneRoot = (ViewGroup) findViewById(R.id.scene_root);
+
+// Create the scenes
+mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this);
+mAnotherScene =
+ Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this);
+</pre>
+
+<p>In the app, there are now two {@link android.transition.Scene} objects based on view
+hierarchies. Both scenes use the scene root defined by the
+{@link android.widget.FrameLayout} element in <code>res/layout/activity_main.xml</code>.</p>
+
+
+
+<h2 id="FromCode">Create a Scene in Your Code</h2>
+
+<p>You can also create a {@link android.transition.Scene} instance in your code from a
+{@link android.view.ViewGroup} object. Use this technique when you modify the view hierarchies
+directly in your code or when you generate them dynamically.</p>
+
+<p>To create a scene from a view hierarchy in your code, use the
+{@link android.transition.Scene#Scene(android.view.ViewGroup, android.view.View) Scene(sceneRoot, viewHierarchy)}
+constructor. Calling this constructor is equivalent to calling the
+{@link android.transition.Scene#getSceneForLayout Scene.getSceneForLayout()} method when you
+have already inflated a layout file.</p>
+
+<p>The following code snippet demonstrates how to create a {@link android.transition.Scene}
+instance from the scene root element and the view hierarchy for the scene in your code:</p>
+
+<pre>
+Scene mScene;
+
+// Obtain the scene root element
+mSceneRoot = (ViewGroup) mSomeLayoutElement;
+
+// Obtain the view hierarchy to add as a child of
+// the scene root when this scene is entered
+mViewHierarchy = (ViewGroup) someOtherLayoutElement;
+
+// Create a scene
+mScene = new Scene(mSceneRoot, mViewHierarchy);
+</pre>
+
+
+
+<h2 id="Actions">Create Scene Actions</h2>
+
+<p>The framework enables you to define custom scene actions that the system runs when entering
+or exiting a scene. In many cases, defining custom scene actions is not necessary, since the
+framework animates the change between scenes automatically.</p>
+
+<p>Scene actions are useful for handling these cases:</p>
+
+<ul>
+<li>Animate views that are not in the same hierarchy. You can animate views for both the
+starting and ending scenes using exit and entry scene actions.</li>
+<li>Animate views that the transitions framework cannot animate automatically, such as
+{@link android.widget.ListView} objects. For more information, see
+<a href="{@docRoot}training/transitions/overview.html#Limitations">Limitations</a>.</li>
+</ul>
+
+<p>To provide custom scene actions, define your actions as {@link java.lang.Runnable} objects
+and pass them to the {@link android.transition.Scene#setExitAction Scene.setExitAction()} or
+{@link android.transition.Scene#setEnterAction Scene.setEnterAction()} methods. The framework
+calls the {@link android.transition.Scene#setExitAction setExitAction()} method on the starting
+scene before running the transition animation and the {@link
+android.transition.Scene#setEnterAction setEnterAction()} method on the ending scene after
+running the transition animation.</p>
+
+<p class="note"><strong>Note:</strong> Do not use scene actions to pass data between views in
+the starting and ending scenes. For more information, see
+<a href="{@docRoot}training/transitions/transitions.html#Callbacks">Defining Transition
+Lifecycle Callbacks</a>.</p>
diff --git a/docs/html/training/transitions/transitions.jd b/docs/html/training/transitions/transitions.jd
new file mode 100644
index 0000000..489e291
--- /dev/null
+++ b/docs/html/training/transitions/transitions.jd
@@ -0,0 +1,315 @@
+page.title=Applying a Transition
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#Create">Create a Transition</a></li>
+ <li><a href="#Apply">Apply a Transition</a></li>
+ <li><a href="#Targets">Choose Specific Target Views</a></li>
+ <li><a href="#Multiple">Specify Multiple Transitions</a></li>
+ <li><a href="#NoScenes">Apply a Transition Without Scenes</a></li>
+ <li><a href="#Callbacks">Define Transition Lifecycle Callbacks</a></li>
+</ol>
+</div>
+</div>
+
+<p>In the transitions framework, animations create a series of frames that depict a change
+between the view hierarchies in the starting and ending scenes. The framework represents
+these animations as transition objects, which contain information about an animation. To
+run an animation, you provide the transition to use and the ending scene to a transition
+manager.</p>
+
+<p>This lesson teaches you run an animation between two scenes using built-in transitions
+to move, resize, and fade views. The next lesson shows you how to define custom transitions.</p>
+
+
+
+<h2 id="Create">Create a Transition</h2>
+
+<p>In the previous lesson, you learned how to create scenes that represent the state of
+different view hierarchies. Once you have defined the starting scene and the ending scene you
+want to change between, you need to create a {@link android.transition.Transition} object
+that defines an animation. The framework enables you to specify a built-in transition in a
+resource file and inflate it in your code or to create an instance of a built-in transition
+directly in your code.</p>
+
+<!-- Built in transition table -->
+<p class="table-caption" id="table1"><strong>Table 1.</strong> Built-in transition types.</p>
+<table>
+<tr>
+ <th scope="col">Class</th>
+ <th scope="col">Tag</th>
+ <th scope="col">Attributes</th>
+ <th scope="col">Effect</th>
+</tr>
+<tr>
+ <td><code><a href="/reference/android/transition/AutoTransition.html">AutoTransition</a></code></td>
+ <td>&lt;autoTransition/&gt;</td>
+ <td style="text-align=center;"> - </td>
+ <td>Default transition. Fade out, move and resize, and fade in views, in that order.</td>
+</tr>
+<tr>
+ <td><code><a href="/reference/android/transition/Fade.html">Fade</a></code></td>
+ <td>&lt;fade/&gt;</td>
+ <td><code>android:fadingMode="[fade_in |<br> fade_out |<br> fade_in_out]"</code></td>
+ <td>
+ <code>fade_in</code> fades in views<br>
+ <code>fade_out</code> fades out views<br>
+ <code>fade_in_out</code> (default) does a <code>fade_out</code> followed by a <code>fade_in</code>.
+ </td>
+</tr>
+<tr>
+ <td><code><a href="/reference/android/transition/ChangeBounds.html">ChangeBounds</a></code></td>
+ <td>&lt;changeBounds/&gt;</td>
+ <td style="text-align=center;"> - </td>
+ <td>Moves and resizes views.</td>
+</tr>
+</table>
+
+
+<h3 id="FromFile">Create a transition instance from a resource file</h3>
+
+<p>This technique enables you to modify your transition definition without having to change
+the code of your activity. This technique is also useful to separate complex transition
+definitions from your application code, as shown in <a href="#Multiple">Specify Multiple
+Transitions</a>.</p>
+
+<p>To specify a built-in transition in a resource file, follow these steps:</p>
+
+<ol>
+<li>Add the <code>res/transition/</code> directory to your project.</li>
+<li>Create a new XML resource file inside this directory.</li>
+<li>Add an XML node for one of the built-in transitions.</li>
+</ol>
+
+<p>For example, the following resource file specifies the {@link android.transition.Fade}
+transition:</p>
+
+<p class="code-caption">res/transition/fade_transition.xml</p>
+
+<pre>
+&lt;fade xmlns:android="http://schemas.android.com/apk/res/android" />
+</pre>
+
+<p>The following code snippet shows how to inflate a {@link android.transition.Transition}
+instance inside your activity from a resource file:</p>
+
+<pre>
+Transition mFadeTransition =
+ TransitionInflater.from(this).
+ inflateTransition(R.transition.fade_transition);
+</pre>
+
+
+<h3 id="FromCode">Create a transition instance in your code</h3>
+
+<p>This technique is useful for creating transition objects dynamically if you modify the user
+interface in your code, and to create simple built-in transition instances with few or
+no parameters.</p>
+
+<p>To create an instance of a built-in transition, invoke one of the public constructors in
+the subclasses of the {@link android.transition.Transition} class. For example, the following
+code snippet creates an instance of the {@link android.transition.Fade} transition:</p>
+
+<pre>
+Transition mFadeTransition = new Fade();
+</pre>
+
+
+
+<h2 id="Apply">Apply a Transition</h2>
+
+<p>You typically apply a transition to change between different view hierarchies in response
+to an event, such as a user action. For example, consider a search app: when the user enters
+a search term and clicks the search button, the app changes to the scene that represents the
+results layout while applying a transition that fades out the search button and fades in the
+search results.</p>
+
+<p>To make a scene change while applying a transition in response to some event in your
+activity, call the {@link android.transition.TransitionManager#go TransitionManager.go()}
+static method with the ending scene and the transition instance to use for the animation,
+as shown in the following snippet:</p>
+
+<pre>
+TransitionManager.go(mEndingScene, mFadeTransition);
+</pre>
+
+<p>The framework changes the view hierarchy inside the scene root with the view hierarchy
+from the ending scene while running the animation specified by the transition instance. The
+starting scene is the ending scene from the last transition. If there was no previous
+transition, the starting scene is determined automatically from the current state of the
+user interface.</p>
+
+<p>If you do not specify a transition instance, the transition manager can apply an automatic
+transition that does something reasonable for most situations. For more information, see the
+API reference for the {@link android.transition.TransitionManager} class.</p>
+
+
+
+<h2 id="Targets">Choose Specific Target Views</h2>
+
+<p>The framework applies transitions to all views in the starting and ending scenes by
+default. In some cases, you may only want to apply an animation to a subset of views in a
+scene. For example, the framework does not support animating changes to
+{@link android.widget.ListView} objects, so you should not try to animate them during a
+transition. The framework enables you to select specific views you want to animate.</p>
+
+<p>Each view that the transition animates is called a <em>target</em>. You can only
+select targets that are part of the view hierarchy associated with a scene.</p>
+
+<p>To remove one or more views from the list of targets, call the {@link
+android.transition.Transition#removeTarget removeTarget()} method before starting
+the transition. To add only the views you specify to the list of targets, call the
+{@link android.transition.Transition#addTarget addTarget()} method. For more
+information, see the API reference for the {@link android.transition.Transition} class.</p>
+
+
+
+<h2 id="Multiple">Specify Multiple Transitions</h2>
+
+<p>To get the most impact from an animation, you should match it to the type of changes
+that occur between the scenes. For example, if you are removing some views and adding others
+between scenes, a fade out/fade in animation provides a noticeable indication that some views
+are no longer available. If you are moving views to different points on the screen, a better
+choice would be to animate the movement so that users notice the new location of the views.</p>
+
+<p>You do not have to choose only one animation, since the transitions framework enables you
+to combine animation effects in a transition set that contains a group of individual built-in
+or custom transitions.</p>
+
+<p>To define a transition set from a collection of transitions in XML, create a resource file
+in the <code>res/transitions/</code> directory and list the transitions under the
+<code>transitionSet</code> element. For example, the following snippet shows how to specify a
+transition set that has the same behaviour as the {@link android.transition.AutoTransition}
+class:</p>
+
+<pre>
+&lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+ android:transitionOrdering="sequential">
+ &lt;fade android:fadingMode="fade_out" />
+ &lt;changeBounds />
+ &lt;fade android:fadingMode="fade_in" />
+&lt;/transitionSet>
+</pre>
+
+<p>To inflate the transition set into a {@link android.transition.TransitionSet} object in
+your code, call the {@link android.transition.TransitionInflater#from TransitionInflater.from()}
+method in your activity. The {@link android.transition.TransitionSet} class extends from the
+{@link android.transition.Transition} class, so you can use it with a transition manager just
+like any other {@link android.transition.Transition} instance.</p>
+
+
+
+<h2 id="NoScenes">Apply a Transition Without Scenes</h2>
+
+<p>Changing view hierarchies is not the only way to modify your user interface. You can also
+make changes by adding, modifying, and removing child views within the current hierarchy. For
+example, you can implement a search interaction with just a single layout. Start with the
+layout showing a search entry field and a search icon. To change the user interface to show
+the results, remove the search button when the user clicks it by calling the {@link
+android.view.ViewGroup#removeView ViewGroup.removeView()} method, and add the search results by
+calling {@link android.view.ViewGroup#addView ViewGroup.addView()} method.</p>
+
+<p>You may want to use this approach if the alternative is to have two hierarchies that are
+nearly identical. Rather than having to create and maintain two separate layout files for a
+minor difference in the user interface, you can have one layout file containing a view
+hierarchy that you modify in code.</p>
+
+<p>If you make changes within the current view hierarchy in this fashion, you do not need to
+create a scene. Instead, you can create and apply a transition between two states of a view
+hierarchy using a <em>delayed transition</em>. This feature of the transitions framework
+starts with the current view hierarchy state, records changes you make to its views, and applies
+a transition that animates the changes when the system redraws the user interface.</p>
+
+<p>To create a delayed transition within a single view hierarchy, follow these steps:</p>
+
+<ol>
+<li>When the event that triggers the transition occurs, call the {@link
+android.transition.TransitionManager#beginDelayedTransition
+TransitionManager.beginDelayedTransition()} method providing the parent view of all the views
+you want to change and the transition to use. The framework stores the current state of the
+child views and their property values.</li>
+<li>Make changes to the child views as required by your use case. The framework records
+the changes you make to the child views and their properties.</li>
+<li>When the system redraws the user interface according to your changes, the framework
+animates the changes between the original state and the new state.</li>
+</ol>
+
+<p>The following example shows how to animate the addition of a text view to a view hierarchy
+using a delayed transition. The first snippet shows the layout definition file:</p>
+
+<p class="code-caption">res/layout/activity_main.xml</p>
+
+<pre>
+&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/mainLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ &lt;EditText
+ android:id="@+id/inputText"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ ...
+&lt;/RelativeLayout>
+</pre>
+
+<p>The next snippet shows the code that animates the addition of the text view:</p>
+
+<p class="code-caption">MainActivity.java</p>
+
+<pre>
+private TextView mLabelText;
+private Fade mFade;
+private ViewGroup mRootView;
+...
+
+// Load the layout
+this.setContentView(R.layout.activity_main);
+...
+
+// Create a new TextView and set some View properties
+mLabelText = new TextView();
+mLabelText.setText("Label").setId("1");
+
+// Get the root view and create a transition
+mRootView = (ViewGroup) findViewById(R.id.mainLayout);
+mFade = new Fade(IN);
+
+// Start recording changes to the view hierarchy
+TransitionManager.beginDelayedTransition(mRootView, mFade);
+
+// Add the new TextView to the view hierarchy
+mRootView.addView(mLabelText);
+
+// When the system redraws the screen to show this update,
+// the framework will animate the addition as a fade in
+</pre>
+
+
+
+<h2 id="Callbacks">Define Transition Lifecycle Callbacks</h2>
+
+<p>The transition lifecycle is similar to the activity lifecycle. It represents the transition
+states that the framework monitors during the time between a call to the {@link
+android.transition.TransitionManager#go TransitionManager.go()} method and the completion of
+the animation. At important lifecycle states, the framework invokes callbacks defined by
+the {@link android.transition.Transition.TransitionListener TransitionListener}
+interface.</p>
+
+<p>Transition lifecycle callbacks are useful, for example, for copying a view property value
+from the starting view hierarchy to the ending view hierarchy during a scene change. You
+cannot simply copy the value from its starting view to the view in the ending view hierarchy,
+because the ending view hierarchy is not inflated until the transition is completed.
+Instead, you need to store the value in a variable and then copy it into the ending view
+hierarchy when the framework has finished the transition. To get notified when the transition
+is completed, you can implement the {@link
+android.transition.Transition.TransitionListener#onTransitionEnd
+TransitionListener.onTransitionEnd()} method in your activity.</p>
+
+<p>For more information, see the API reference for the {@link
+android.transition.Transition.TransitionListener TransitionListener} class.</p>
diff --git a/docs/html/training/wearables/data-layer/data-items.jd b/docs/html/training/wearables/data-layer/data-items.jd
index 12babbf..49a8d32 100644
--- a/docs/html/training/wearables/data-layer/data-items.jd
+++ b/docs/html/training/wearables/data-layer/data-items.jd
@@ -46,7 +46,7 @@ directly. Instead, you:
</ol>
<p>
-However, instead of working with raw bytes using <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])">setData()</a>,
+However, instead of working with raw bytes using <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])"><code>setData()</code></a>,
we recommend you <a href="#SyncData">use a data map</a>, which exposes
a data item in an easy-to-use {@link android.os.Bundle}-like interface.
</p>
@@ -88,39 +88,121 @@ app, you should create a path scheme that matches the structure of the data.
</li>
</ol>
-<p>The following example shows how to create a data map and put data on it:</p>
+<p>The <code>increaseCounter()</code> method in the following example shows how to create a
+data map and put data in it:</p>
<pre>
-PutDataMapRequest dataMap = PutDataMapRequest.create("/count");
-dataMap.getDataMap().putInt(COUNT_KEY, count++);
-PutDataRequest request = dataMap.asPutDataRequest();
-PendingResult&lt;DataApi.DataItemResult&gt; pendingResult = Wearable.DataApi
- .putDataItem(mGoogleApiClient, request);
+public class MainActivity extends Activity implements
+ DataApi.DataListener,
+ GoogleApiClient.ConnectionCallbacks,
+ GoogleApiClient.OnConnectionFailedListener {
+
+ private static final String COUNT_KEY = "com.example.key.count";
+
+ private GoogleApiClient mGoogleApiClient;
+ private int count = 0;
+
+ ...
+
+ // Create a data map and put data in it
+ private void <strong>increaseCounter</strong>() {
+ PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
+ putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
+ PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
+ PendingResult&lt;DataApi.DataItemResult> pendingResult =
+ Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
+ }
+
+ ...
+}
</pre>
+<p>For more information about handling the
+<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">
+<code>PendingResult</code></a> object, see
+<a href="{@docRoot}training/wearables/data-layer/events.html#Wait">Wait for the Status of Data
+Layer Calls</a>.</p>
+
+
<h2 id="ListenEvents">Listen for Data Item Events</h2>
-If one side of the data layer connection changes a data item, you probably want
+
+<p>If one side of the data layer connection changes a data item, you probably want
to be notified of any changes on the other side of the connection.
-You can do this by implementing a listener for data item events.
+You can do this by implementing a listener for data item events.</p>
-<p>For example, here's what a typical callback looks like to carry out certain actions
-when data changes:</p>
+<p>The code snippet in the following example notifies your app when the value of the
+counter defined in the previous example changes:</p>
<pre>
-&#64;Override
-public void onDataChanged(DataEventBuffer dataEvents) {
- for (DataEvent event : dataEvents) {
- if (event.getType() == DataEvent.TYPE_DELETED) {
- Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
- } else if (event.getType() == DataEvent.TYPE_CHANGED) {
- Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
+public class MainActivity extends Activity implements
+ DataApi.DataListener,
+ GoogleApiClient.ConnectionCallbacks,
+ GoogleApiClient.OnConnectionFailedListener {
+
+ private static final String COUNT_KEY = "com.example.key.count";
+
+ private GoogleApiClient mGoogleApiClient;
+ private int count = 0;
+
+ &#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(Wearable.API)
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ &#64;Override
+ protected void onResume() {
+ super.onStart();
+ mGoogleApiClient.connect();
+ }
+
+ &#64;Override
+ public void onConnected(Bundle bundle) {
+ <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this);
+ }
+
+ &#64;Override
+ protected void onPause() {
+ super.onPause();
+ <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this);
+ mGoogleApiClient.disconnect();
+ }
+
+ &#64;Override
+ public void <strong>onDataChanged</strong>(DataEventBuffer dataEvents) {
+ for (DataEvent event : dataEvents) {
+ if (event.getType() == DataEvent.TYPE_CHANGED) {
+ // DataItem changed
+ DataItem item = event.getDataItem();
+ if (item.getUri().getPath().compareTo("/count") == 0) {
+ DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
+ updateCount(dataMap.getInt(COUNT_KEY));
+ }
+ } else if (event.getType() == DataEvent.TYPE_DELETED) {
+ // DataItem deleted
+ }
}
}
+
+ // Our method to update the count
+ private void updateCount(int c) { ... }
+
+ ...
}
</pre>
-<p>
-This is just a snippet that requires more implementation details. Learn about
-how to implement a full listener service or activity in
+
+<p>This activity implements the
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html">
+<code>DataItem.DataListener</code></a> interface. This activity adds itself as a listener
+for data item events inside the <code>onConnected()</code> method and removes the listener
+in the <code>onPause()</code> method.</p>
+
+<p>You can also implement the listener as a service. For more information, see
<a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listen for Data Layer
-Events</a>.
-</p> \ No newline at end of file
+Events</a>.</p>
diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd
index 6a3949a..c797f68 100644
--- a/docs/html/training/wearables/data-layer/events.jd
+++ b/docs/html/training/wearables/data-layer/events.jd
@@ -267,6 +267,8 @@ or <a href="{@docRoot}reference/com/google/android/gms/wearable/NodeApi.html#rem
public class MainActivity extends Activity implements
DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {
+ private GoogleApiClient mGoogleApiClient;
+
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -314,4 +316,5 @@ public class MainActivity extends Activity implements
}
}
}
+}
</pre>
diff --git a/docs/html/training/wearables/data-layer/messages.jd b/docs/html/training/wearables/data-layer/messages.jd
index 822e395..0ca55ba 100644
--- a/docs/html/training/wearables/data-layer/messages.jd
+++ b/docs/html/training/wearables/data-layer/messages.jd
@@ -39,16 +39,24 @@ to Google Play services and when to use each in
</p>
<pre>
-Node node; // the connected device to send the message to
GoogleApiClient mGoogleApiClient;
-public static final START_ACTIVITY_PATH = "/start/MainActivity";
+public static final String START_ACTIVITY_PATH = "/start/MainActivity";
...
- SendMessageResult result = Wearable.MessageApi.sendMessage(
- mGoogleApiClient, node, START_ACTIVITY_PATH, null).await();
- if (!result.getStatus().isSuccess()) {
- Log.e(TAG, "ERROR: failed to send Message: " + result.getStatus());
- }
+private void sendStartActivityMessage(String nodeId) {
+ Wearable.MessageApi.sendMessage(
+ mGoogleApiClient, nodeId, START_ACTIVITY_PATH, new byte[0]).setResultCallback(
+ new ResultCallback&lt;SendMessageResult>() {
+ &#64;Override
+ public void onResult(SendMessageResult sendMessageResult) {
+ if (!sendMessageResult.getStatus().isSuccess()) {
+ Log.e(TAG, "Failed to send message with status code: "
+ + sendMessageResult.getStatus().getStatusCode());
+ }
+ }
+ }
+ );
+}
</pre>
<p>
diff --git a/docs/html/training/wearables/watch-faces/configuration.jd b/docs/html/training/wearables/watch-faces/configuration.jd
index edc7eac..5a4585d 100644
--- a/docs/html/training/wearables/watch-faces/configuration.jd
+++ b/docs/html/training/wearables/watch-faces/configuration.jd
@@ -92,7 +92,7 @@ and declare the following intent filter in the manifest file of the wearable app
&lt;action android:name=
"com.example.android.wearable.watchface.CONFIG_DIGITAL" />
&lt;category android:name=
- "com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION" />
+ <strong>"com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION"</strong> />
&lt;category android:name="android.intent.category.DEFAULT" />
&lt;/intent-filter>
&lt;/activity>
@@ -119,8 +119,21 @@ a handheld device. For example, a configuration activity on a handheld device en
present users with elaborate color pickers to select the background color of a watch face.</p>
<p>To create a companion configuration activity, add a new activity to your handheld app module and
-declare the same intent filter for this activity as the one in <a href="#WearableActivity">Create
-a Wearable Configuration Activity</a>.</p>
+declare the following intent filter in the manifest file of the handheld app:</p>
+
+<pre>
+&lt;activity
+ android:name=".DigitalWatchFaceCompanionConfigActivity"
+ android:label="@string/app_name">
+ &lt;intent-filter>
+ &lt;action android:name=
+ "com.example.android.wearable.watchface.CONFIG_DIGITAL" />
+ &lt;category android:name=
+ <strong>"com.google.android.wearable.watchface.category.COMPANION_CONFIGURATION"</strong> />
+ &lt;category android:name="android.intent.category.DEFAULT" />
+ &lt;/intent-filter>
+&lt;/activity>
+</pre>
<p>In your configuration activity, build a UI that provides options to customize all the
configurable elements of your watch face. When users make a selection, use the <a