summaryrefslogtreecommitdiffstats
path: root/docs/html/training
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/training')
-rw-r--r--docs/html/training/articles/wear-location-detection.jd375
-rw-r--r--docs/html/training/basics/firstapp/building-ui.jd10
-rw-r--r--docs/html/training/basics/firstapp/creating-project.jd5
-rw-r--r--docs/html/training/basics/firstapp/index.jd8
-rw-r--r--docs/html/training/basics/firstapp/running-app.jd7
-rw-r--r--docs/html/training/basics/firstapp/starting-activity.jd5
-rw-r--r--docs/html/training/building-wearables.jd2
-rw-r--r--docs/html/training/material/compatibility.jd6
-rw-r--r--docs/html/training/material/drawables.jd2
-rw-r--r--docs/html/training/material/lists-cards.jd4
-rw-r--r--docs/html/training/training_toc.cs6
-rw-r--r--docs/html/training/tv/games/index.jd94
-rw-r--r--docs/html/training/wearables/apps/index.jd3
-rw-r--r--docs/html/training/wearables/notifications/index.jd2
-rw-r--r--docs/html/training/wearables/notifications/stacks.jd4
-rw-r--r--docs/html/training/wearables/ui/index.jd1
16 files changed, 472 insertions, 62 deletions
diff --git a/docs/html/training/articles/wear-location-detection.jd b/docs/html/training/articles/wear-location-detection.jd
new file mode 100644
index 0000000..b0d9755
--- /dev/null
+++ b/docs/html/training/articles/wear-location-detection.jd
@@ -0,0 +1,375 @@
+page.title=Detecting Location on Android Wear
+page.tags="gps"
+
+page.article=true
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>In this document</h2>
+<ol class="nolist">
+ <li><a href="#Connect">Connect to Google Play Services</a></li>
+ <li><a href="#Request">Request Location Updates</a></li>
+ <li><a href="#DetectGPS">Detect On-Board GPS</a></li>
+ <li><a href="#Disconnection">Handle Disconnection Events</a></li>
+ <li><a href="#Notify">Handle Location Not Found</a></li>
+ <li><a href="#Synchronize">Synchronize Data</a></li>
+</ol>
+<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+<h2>Dependencies and prerequisites</h2>
+<ul>
+ <li>Android 4.3 (API Level 18) or higher on the handset device</li>
+ <li><a href="{@docRoot}google/play-services/index.html">Google Play services</a> 6.1 or higher</li>
+ <li>An Android Wear device</li>
+</ul>
+<h2>See also</h2>
+<ul>
+ <li><a href="{@docRoot}training/location/index.html">Making Your App Location-Aware
+ </a></li>
+</ul>
+</div></div>
+
+<p>Location awareness on wearable devices enables you to create apps that give users a better
+understanding of their geographic position, movement and what's around them. With the small form
+factor and glanceable nature of a wearable device, you can build low-friction apps that record and
+respond to location data.</p>
+
+<p>Some wearable devices include a GPS sensor that can retrieve location data without another
+tethered device. However, when you request location data in a wearable app, you don't have to worry
+about where the location data originates; the system retrieves the location updates using the most
+power-efficient method. Your app should be able to handle loss of location data, in case the wear
+device loses connection with its paired device and does not have a built-in GPS sensor.</p>
+
+<p>This document shows you how to check for on-device location sensors, receive location data, and
+monitor tethered data connections.</p>
+
+<p class="note"><b>Note:</b> The article assumes that you know how to use the Google Play services
+API to retrieve location data. For more information, see <a href="{@docRoot}training/
+location/index.html">Making Your App Location-Aware</a>.</p>
+
+<h2 id="Connect">Connect to Google Play Services</h2>
+
+<p>Location data on wearable devices is obtained though the Google Play services location APIs. You
+use the <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">
+<code>FusedLocationProviderApi</code></a> and its accompanying classes to obtain this data.
+To access location services, create an instance of
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">
+<code>GoogleApiClient</code></a>, which is
+the main entry point for any of the Google Play services APIs.
+</p>
+
+<p class="caution"><b>Caution:</b> Do not use the existing <a href="{@docRoot}reference/android/location/package-summary.html">Location</a>
+APIs in the Android framework. The best practice for retrieving location updates is through the
+Google Play services API as outlined in this article.</p>
+
+<p>To connect to Google Play services, configure your app to create an instance of
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">
+<code>GoogleApiClient</code></a>:</p>
+
+<ol>
+ <li>Create an activity that specifies an implementation for the interfaces <a
+href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html"
+>{@code ConnectionCallbacks}</a>, <a href="{@docRoot}reference/com/google/android/gms/common/api/
+GoogleApiClient.OnConnectionFailedListener.html">{@code OnConnectionFailedListener}</a>, and <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code
+LocationListener}</a>.</li>
+ <li>In your activity's {@link android.app.Activity#onCreate onCreate()} method, create an instance
+of <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>
+GoogleApiClient</code></a> and add the Location service.
+ </li>
+ <li>To gracefully manage the lifecycle of the connection, call <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()">
+ {@code connect()}</a> in the {@link android.app.Activity#onResume onResume()} method and
+ <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#disconnect()">
+ {@code disconnect()}</a> in the {@link android.app.Activity#onPause onPause()} method.
+ </li>
+</ol>
+
+<p>The following code example shows an implementation of an activity that implements the
+<a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">
+{@code LocationListener}</a> interface:</p>
+
+<pre>
+public class WearableMainActivity extends Activity implements
+ GoogleApiClient.ConnectionCallbacks,
+ GoogleApiClient.OnConnectionFailedListener,
+ LocationListener {
+
+ private GoogleApiClient mGoogleApiClient;
+ ...
+
+ &#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ...
+ mGoogleApiClient = new GoogleApiClient.Builder(this)
+ .addApi(LocationServices.API)
+ .addApi(Wearable.API) // used for data layer API
+ .addConnectionCallbacks(this)
+ .addOnConnectionFailedListener(this)
+ .build();
+ }
+
+ &#64;Override
+ protected void onResume() {
+ super.onResume();
+ mGoogleApiClient.connect();
+ ...
+ }
+
+ &#64;Override
+ protected void onPause() {
+ super.onPause();
+ ...
+ mGoogleApiClient.disconnect();
+ }
+}
+</pre>
+
+<p>For more information on connecting to Google Play services, see <a href="{@docRoot}google/auth
+/api-client.html">Accessing Google APIs</a>.</p>
+
+<h2 id="Request">Request Location Updates</h2>
+
+<p>After your app has connected to the Google Play services API, it is ready to start receiving
+location updates. When the system invokes the
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">
+<code>onConnected()</code></a> callback for your client, you build the location data request as
+follows:</p>
+
+<ol>
+ <li>Create a <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html"
+>{@code LocationRequest}</a> object and set any options using methods like <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setPriority(int)"
+>{@code setPriority()}</a>.
+ </li>
+ <li>Request location updates using <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">
+ <code>requestLocationUpdates()</code></a>.
+ </li>
+ <li>Remove location updates using <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#removeLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationListener)">
+ <code>removeLocationUpdates()</code></a> in the {@link android.app.Activity#onPause
+ onPause()} method.
+ </li>
+</ol>
+
+<p>The following example shows how to retrieve and remove location updates:</p>
+
+<pre>
+&#64;Override
+public void onConnected(Bundle bundle) {
+ LocationRequest locationRequest = LocationRequest.create()
+ .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
+ .setInterval(UPDATE_INTERVAL_MS)
+ .setFastestInterval(FASTEST_INTERVAL_MS);
+
+ LocationServices.FusedLocationApi
+ .requestLocationUpdates(mGoogleApiClient, locationRequest, this)
+ .setResultCallback(new ResultCallback<Status>() {
+
+ &#64;Override
+ public void onResult(Status status) {
+ if (status.getStatus().isSuccess()) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Successfully requested location updates");
+ }
+ } else {
+ Log.e(TAG,
+ "Failed in requesting location updates, "
+ + "status code: "
+ + status.getStatusCode()
+ + ", message: "
+ + status.getStatusMessage());
+ }
+ }
+ });
+}
+
+&#64;Override
+protected void onPause() {
+ super.onPause();
+ if (mGoogleApiClient.isConnected()) {
+ LocationServices.FusedLocationApi
+ .removeLocationUpdates(mGoogleApiClient, this);
+ }
+ mGoogleApiClient.disconnect();
+}
+
+&#64;Override
+public void onConnectionSuspended(int i) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "connection to location client suspended");
+ }
+}
+
+</pre>
+
+<p>Now that you have enabled location updates, the system calls the {@link android.location.LocationListener#onLocationChanged
+onLocationChanged()} method with the updated location at the interval specified in <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">
+{@code setInterval()}</a>
+</p>
+
+<h2 id="DetectGPS">Detect On-Board GPS</h2>
+
+<p>Not all wearables have a GPS sensor. If your user goes out for a run and leaves their phone at
+home, your wearable app cannot receive location data through a tethered connection. If the
+wearable device does not have a sensor, you should detect this situation and warn the user that
+location functionality is not available.
+
+<p>To determine whether your Android Wear device has a built-in GPS sensor, use the
+{@link android.content.pm.PackageManager#hasSystemFeature hasSystemFeature()}
+method. The following code detects whether the device has built-in GPS when you start an activity:
+</p>
+
+<pre>
+
+protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.main_activity);
+ if (!hasGps()) {
+ Log.d(TAG, "This hardware doesn't have GPS.");
+ // Fall back to functionality that does not use location or
+ // warn the user that location function is not available.
+ }
+
+ ...
+}
+
+private boolean hasGps() {
+ return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
+}
+</pre>
+
+<h2 id="Disconnection">Handle Disconnection Events</h2>
+
+<p>Wearable devices relying on a tethered connection for location data may lose their connections
+abruptly. If your wearable app expects a constant stream of data, you must handle the
+disconnection based upon where that data is interrupted or unavailable. On a wearable device with no
+onboard GPS sensor, loss of location data occurs when the device loses its tethered data connection.
+</p>
+
+<p>In cases where your app depends on a tethered data connection for location data and the wear
+device does not have a GPS sensor, you should detect the loss of that connection, warn the user, and
+gracefully degrade the functionality of your app.</p>
+
+<p>To detect the loss of a tethered data connection:</p>
+
+<ol>
+ <li>Extend a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html">
+ <code>WearableListenerService</code></a> that lets you listen for important data layer events.
+ </li>
+ <li>Declare an intent filter in your Android manifest to notify the system about your
+ <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>
+ WearableListenerService</code></a>.
+ This filter allows the system to bind your service as needed.
+<pre>
+&lt;service android:name=".NodeListenerService"&gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="com.google.android.gms.wearable.BIND_LISTENER" /&gt;
+ &lt;/intent-filter&gt;
+&lt;/service>
+</pre>
+ </li>
+ <li>Implement the <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onPeerDisconnected(com.google.android.gms.wearable.Node)">
+ <code>onPeerDisconnected()</code></a> method and handle cases of whether or not the device has
+ built-in
+ GPS.
+<pre>
+public class NodeListenerService extends WearableListenerService {
+
+ private static final String TAG = "NodeListenerService";
+
+ &#64;Override
+ public void onPeerDisconnected(Node peer) {
+ Log.d(TAG, "You have been disconnected.");
+ if(!hasGPS()) {
+ // Notify user to bring tethered handset
+ // Fall back to functionality that does not use location
+ }
+ }
+ ...
+}
+</pre>
+ </li>
+</ol>
+
+For more information, read the <a href="{@docRoot}training/wearables/data-layer/events.html#Listen">
+Listen for Data Layer Events</a> guide.
+
+<h2 id="Notify">Handle Location Not Found</h2>
+
+<p>When the GPS signal is lost, you can still retrieve the last known location using
+<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">
+<code>getLastLocation()</code></a>. This method can be helpful in situations where you are unable to
+get a GPS fix, or when your wearable doesn't have built-in GPS and loses its connection with the
+phone.</p>
+
+<p>The following code uses <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">
+<code>getLastLocation()</code></a> to retrieve the last known location if available:
+</p>
+
+<pre>
+Location location = LocationServices.FusedLocationApi
+ .getLastLocation(mGoogleApiClient);
+</pre>
+
+<h2 id="Synchronize">Synchronize Data</h2>
+
+<p>If your wearable app records data using the built-in GPS, you may want to synchronize
+the location data with the handset. With the {@link android.location.LocationListener}, you
+implement the {@link android.location.LocationListener#onLocationChanged onLocationChanged()}
+method to detect and record the location as it changes.
+
+<p>The following code for wearable apps detects when the location changes and uses the data layer
+API to store the data for later retrieval by your phone app:</p>
+
+<pre>
+&#64;Override
+public void onLocationChanged(Location location) {
+ ...
+ addLocationEntry(location.getLatitude(), location.getLongitude());
+
+}
+
+private void addLocationEntry(double latitude, double longitude) {
+ if (!mSaveGpsLocation || !mGoogleApiClient.isConnected()) {
+ return;
+ }
+
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
+
+ // Set the path of the data map
+ String path = Constants.PATH + "/" + mCalendar.getTimeInMillis();
+ PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(path);
+
+ // Set the location values in the data map
+ putDataMapRequest.getDataMap()
+ .putDouble(Constants.KEY_LATITUDE, latitude);
+ putDataMapRequest.getDataMap()
+ .putDouble(Constants.KEY_LONGITUDE, longitude);
+ putDataMapRequest.getDataMap()
+ .putLong(Constants.KEY_TIME, mCalendar.getTimeInMillis());
+
+ // Prepare the data map for the request
+ PutDataRequest request = putDataMapRequest.asPutDataRequest();
+
+ // Request the system to create the data item
+ Wearable.DataApi.putDataItem(mGoogleApiClient, request)
+ .setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
+ &#64;Override
+ public void onResult(DataApi.DataItemResult dataItemResult) {
+ if (!dataItemResult.getStatus().isSuccess()) {
+ Log.e(TAG, "Failed to set the data, "
+ + "status: " + dataItemResult.getStatus()
+ .getStatusCode());
+ }
+ }
+ });
+}
+</pre>
+
+<p>For more information on how to use the Data Layer API, see the <a href="{@docRoot}training/
+wearables/data-layer/index.html">Sending and Syncing Data</a>
+guide.</p>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index 179b3ac..c082642 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -1,12 +1,8 @@
page.title=Building a Simple User Interface
-parent.title=Building Your First App
-parent.link=index.html
-
trainingnavtop=true
-previous.title=Running Your App
-previous.link=running-app.html
-next.title=Starting Another Activity
-next.link=starting-activity.html
+
+page.tags=ui, views, layouts, widgets, string resources
+helpoutsWidget=true
@jd:body
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index c4cb362..418eb68 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -1,6 +1,7 @@
page.title=Creating an Android Project
-parent.title=Building Your First App
-parent.link=index.html
+
+page.tags=eclipse adt, sdk tools, project setup
+helpoutsWidget=true
trainingnavtop=true
next.title=Running Your App
diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd
index 1b49096..ac8e64a 100644
--- a/docs/html/training/basics/firstapp/index.jd
+++ b/docs/html/training/basics/firstapp/index.jd
@@ -3,8 +3,9 @@ page.metaDescription=If you're new to Android app development, this where you sh
trainingnavtop=true
startpage=true
-next.title=Creating an Android Project
-next.link=creating-project.html
+
+page.tags=sdk tools
+helpoutsWidget=true
@jd:body
@@ -47,6 +48,3 @@ not apply to earlier versions.</p>
<p>This class uses a tutorial format that incrementally builds a small Android app that teaches
you some fundamental concepts about Android development, so it's important that you follow each
step.</p>
-
-<p><strong><a href="creating-project.html">Start the first lesson &rsaquo;</a></strong></p>
-
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index 23cedba..96b7172 100644
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -3,10 +3,9 @@ parent.title=Building Your First App
parent.link=index.html
trainingnavtop=true
-previous.title=Creating a Project
-previous.link=creating-project.html
-next.title=Building a Simple User Interface
-next.link=building-ui.html
+
+page.tags=emulator
+helpoutsWidget=true
@jd:body
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 27d2c10..f9dcba4 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -3,8 +3,9 @@ parent.title=Building Your First App
parent.link=index.html
trainingnavtop=true
-previous.title=Building a Simpler User Interface
-previous.link=building-ui.html
+
+page.tags=input events, intents, activity lifecycle
+helpoutsWidget=true
@jd:body
diff --git a/docs/html/training/building-wearables.jd b/docs/html/training/building-wearables.jd
index 0745c93..d751a81 100644
--- a/docs/html/training/building-wearables.jd
+++ b/docs/html/training/building-wearables.jd
@@ -1,6 +1,6 @@
page.title=Building Apps for Wearables
page.trainingcourse=true
-page.image=wear/images/notifications.png
+page.image=wear/images/02_create.png
page.metaDescription=Learn how to build notifications, send and sync data, and use voice actions.
@jd:body
diff --git a/docs/html/training/material/compatibility.jd b/docs/html/training/material/compatibility.jd
index 5e03450..49ef7f7 100644
--- a/docs/html/training/material/compatibility.jd
+++ b/docs/html/training/material/compatibility.jd
@@ -131,9 +131,9 @@ href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle dependenc
<pre>
dependencies {
- compile 'com.android.support:appcompat-v7:+'
- compile 'com.android.support:cardview-v7:+'
- compile 'com.android.support:recyclerview-v7:+'
+ compile 'com.android.support:appcompat-v7:21.0.+'
+ compile 'com.android.support:cardview-v7:21.0.+'
+ compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>
diff --git a/docs/html/training/material/drawables.jd b/docs/html/training/material/drawables.jd
index 8d7f453..fd21e3d 100644
--- a/docs/html/training/material/drawables.jd
+++ b/docs/html/training/material/drawables.jd
@@ -73,7 +73,7 @@ app's module:</p>
<pre>
dependencies {
...
- compile 'com.android.support:palette-v7:+'
+ compile 'com.android.support:palette-v7:21.0.+'
}
</pre>
diff --git a/docs/html/training/material/lists-cards.jd b/docs/html/training/material/lists-cards.jd
index eb45f0d..e7bdfe0 100644
--- a/docs/html/training/material/lists-cards.jd
+++ b/docs/html/training/material/lists-cards.jd
@@ -260,7 +260,7 @@ app's module:</p>
<pre>
dependencies {
...
- compile 'com.android.support:cardview-v7:+'
- compile 'com.android.support:recyclerview-v7:+'
+ compile 'com.android.support:cardview-v7:21.0.+'
+ compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0fee771..9f06666 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -834,6 +834,12 @@ include the action bar on devices running Android 2.1 or higher."
</li>
</ul>
</li>
+ <li>
+ <a href="<?cs var:toroot ?>training/articles/wear-location-detection.html"
+ description=
+ "How to detect location data on Android Wear devices."
+ >Detecting Location</a>
+ </li>
</ul>
</li>
<!-- End Building for wearables -->
diff --git a/docs/html/training/tv/games/index.jd b/docs/html/training/tv/games/index.jd
index 29b055b..2f510a9 100644
--- a/docs/html/training/tv/games/index.jd
+++ b/docs/html/training/tv/games/index.jd
@@ -31,7 +31,7 @@ page.article=true
</p>
-<h3 id="shared-display">Shared display</h3>
+<h3 id="shared-display">Consider the shared display</h3>
<p>
A living-room TV poses design challenges for multiplayer games, in that all players can see
@@ -57,7 +57,7 @@ page.article=true
</ul>
-<h3 id="landscape-display">Landscape display</h3>
+<h3 id="landscape-display">Support landscape display</h3>
<p>
A TV is always sideways: You can’t turn it, and there is no portrait orientation. Always design
@@ -69,19 +69,19 @@ page.article=true
<p>
TVs don't have touch interfaces, so it's even more important to get your controls right and make
- sure that players find them intuitive and fun to use. The separation of controller from device
- also introduces some other issues to pay attention to, like keeping track of multiple players'
+ sure players find them intuitive and fun to use. Handling controllers
+ also introduces some other issues to pay attention to, like keeping track of multiple
controllers, and handling disconnects gracefully.
</p>
-<h3 id="d-pad">D-pad</h3>
+<h3 id="d-pad">Support D-pad controls</h3>
<p>
Plan your control scheme around a directional pad (D-pad) control, since this control set is the
default for Android TV devices. The player needs to be able to use a D-Pad in all aspects of the
- game–not just controlling core gameplay, but also navigating menus and ads. For this reason, you
- should also ensure that your Android TV game does not refer to a touch interface: For example, an
- Android TV game should not tell a player to <strong>Tap here to skip</strong>.
+ game&mdash;not just controlling core gameplay, but also navigating menus and ads. For this reason, you
+ should also ensure that your Android TV game does not refer to a touch interface. For example, an
+ Android TV game should not tell a player to "<em>Tap</em> here to continue."
</p>
<p>
@@ -91,35 +91,35 @@ page.article=true
<ul>
<li>
- <strong>Communicate Controller Requirements up Front</strong> - Use your Play Store description
+ <strong>Communicate Controller Requirements up Front</strong>. Use your Google Play description
to communicate to the player any expectations about controllers. If a game is better suited to
a gamepad with a joystick than one with only a D-pad, make this fact clear. A player who uses
- an ill-suited controller for a game is likely to have a subpar experience–and penalize your
+ an ill-suited controller for a game is likely to have a subpar experience and penalize your
game in the ratings.
</li>
<li>
- <strong>Use Consistent Button Mapping</strong> - Intuitive and flexible button mapping is key
- to a good user experience. For example, you can adhere to accepted custom by using the A button
- to <code>Accept</code>, and the B button to <code>Cancel</code>. You can also offer flexibility
- in the form of remappability. For more information on button mapping, see <a href=
+ <strong>Use Consistent Button Mapping</strong>. Intuitive and flexible button mapping is key
+ to a good user experience. For example, you should adhere to accepted customs by using the A button
+ to <em>Accept</em>, and the B button to <em>Cancel</em>. You can also offer flexibility
+ in the form of remappability. For more information about button mapping, see <a href=
"http://developer.android.com/training/game-controllers/controller-input.html">Handling
Controller Actions</a>.
</li>
<li>
- <strong>Detect Controller Capabilities and Adjust Accordingly</strong> - Query the controller
+ <strong>Detect Controller Capabilities and Adjust Accordingly</strong>. Query the controller
about its capabilities in order to optimize the match between controller and game. For example,
you may intend for a player to steer an object by waving the controller in the air. If a
player's controller lacks accelerometer and gyroscope hardware, however, waving will not work.
- When, however, your game queries the controller and discovers that motion detection is not
- supported, it can switch over to an alternative, available control scheme. For more information
- on querying controller capabilities, see <a href=
+ So, your game should query the controller and if motion detection is not
+ supported, switch over to an alternative, available control scheme. For more information
+ about querying controller capabilities, see <a href=
"http://developer.android.com/training/game-controllers/compatibility.html">Supporting
Controllers Across Android Versions</a>.
</li>
</ul>
-<h3 id="back-button">Back-button behavior</h3>
+<h3 id="back-button">Provide appropriate Back-button behavior</h3>
<p>
The Back button should never act as a toggle. For example, do not use it to both open and close a
@@ -139,18 +139,18 @@ page.article=true
</p>
-<h3 id="multiple-controllers">Handling multiple controllers</h3>
+<h3 id="multiple-controllers">Handle multiple controllers</h3>
<p>
When multiple players are playing a game, each with his or her own controller, it is important to
- map each player-controller pair. For information on how to implement controller-number
+ map each player-controller pair. For information about how to implement controller-number
identification, see <a href=
"http://developer.android.com/reference/android/view/InputDevice.html#getControllerNumber">Input
Devices</a>.
</p>
-<h3 id="handle-disconnect">Handling disconnects</h3>
+<h3 id="handle-disconnect">Handle controller disconnects</h3>
<p>
When a controller is disconnected in the middle of gameplay, the game should pause, and a dialog
@@ -159,7 +159,7 @@ page.article=true
<p>
The dialog should also offer troubleshooting tips (for example, a pop-up dialog telling the
- player to "Check your Bluetooth connection"). For more information on implementing input-device
+ player to "Check your Bluetooth connection"). For more information about implementing input-device
support, see <a href=
"http://developer.android.com/training/game-controllers/controller-input.html">Handling Controller
Actions</a>. Specific information about Bluetooth connections is at <a href=
@@ -167,25 +167,53 @@ page.article=true
</p>
+<h3 id="ControllerHelp">Show controller instructions</h3>
+
+<p>If your game provides visual game control instructions, the
+controller image should be free of branding and include only <a
+href="{@docRoot}training/game-controllers/controller-input.html#button"
+>buttons compatible with Android</a>.</p>
+
+<p>For sample images of an Android-compatible controller, download the
+<a href="http://storage.googleapis.com/androiddevelopers/design/android_tv_gamepad_template-2014-10.zip"
+>Android TV Gamepad Template (ZIP)</a>.
+It includes a white controller on black background and a black controller on white background
+(shown in figure 1), as a PNG file and an Adobe&reg; Illustrator&reg; file.</p>
+
+<img src="{@docRoot}images/games/game-controller-buttons_2x.png" width="700"
+ srcset="{@docRoot}images/games/game-controller-buttons_2x.png 2x,
+ {@docRoot}images/games/game-controller-buttons.png 1x" />
+<p class="img-caption"><b>Figure 1.</b> Example controller instructions using the
+<a href="http://storage.googleapis.com/androiddevelopers/design/android_tv_gamepad_template-2014-10.zip"
+>Android TV Gamepad Template (ZIP)</a>.
+
+
+
+
<h2 id="manifest">Manifest</h2>
+<p>There are a some special things games should include in the Android manifest.</p>
+
+<h3 id="Launcher">Show your game in the launcher</h3>
<p>
- The Android TV launcher home screen displays games in a separate row from regular apps. The TV
- framework uses the <code>android:isGame</code> manifest attribute to differentiate games from
- non-game apps. Set this value to <code>true</code> in your game's app manifest, as shown in the
- following code example:
+ The Android TV launcher home screen displays games in a separate row from regular apps.
+ To make your game appear in the list of games, add the
+ <a href="{@docRoot}guide/topics/manifest/meta-data-element.html"
+ ><code>&lt;meta-data></code></a> tag in your app manifest with <code>android:name</code>
+ set to <code>"isGame"</code> and <code>android:value</code>
+ set to <code>"true"</code>. For example:
</p>
<pre class="fragment">
&lt;application&gt;
...
- &lt; meta-data android:name="isGame" android:value="true" &gt;
+ &lt;meta-data android:name="isGame" android:value="true" &gt;
...
&lt;/application&gt;
</pre>
-<h3 id="gamepad">Game Controllers</h3>
+<h3 id="gamepad">Declare support for game controllers</h3>
<p>
Games controllers may not be available or active for users of a TV device. In order to properly
@@ -215,7 +243,9 @@ page.article=true
<h2 id="gpgs">Google Play Game Services</h2>
<p>
- If your game integrates Google Play Game Services, you should keep in mind a number of
+ If your game integrates <a
+ href="https://developers.google.com/games/services/">Google Play Game services</a>,
+ you should keep in mind a number of
considerations pertaining to achievements, sign-in, saving games, and multiplayer play.
</p>
@@ -224,7 +254,7 @@ page.article=true
<p>
Your game should include at least five (earnable) achievements. Only a user controlling gameplay
- from a supported input device should be able to earn achievements. For more information on
+ from a supported input device should be able to earn achievements. For more information about
achievements and how to implement them, see <a href=
"https://developers.google.com/games/services/android/achievements">Achievements in Android</a>.
</p>
@@ -262,7 +292,7 @@ page.article=true
<p>
A game offering a multiplayer experience must allow at least two players to enter a room. For
- further information on multiplayer games in Android, see the <a href=
+ further information about multiplayer games in Android, see the <a href=
"https://developers.google.com/games/services/android/realtimeMultiplayer">Real-time
Multiplayer</a> and <a href="">Turn-based Multiplayer</a> documentation on the Android developer
site.
diff --git a/docs/html/training/wearables/apps/index.jd b/docs/html/training/wearables/apps/index.jd
index 7d961b7..256205b 100644
--- a/docs/html/training/wearables/apps/index.jd
+++ b/docs/html/training/wearables/apps/index.jd
@@ -1,5 +1,6 @@
page.title=Creating Wearable Apps
-page.image=wear/images/notifications.png
+page.tags="wear","wearable","app"
+page.image=wear/images/01_create.png
@jd:body
diff --git a/docs/html/training/wearables/notifications/index.jd b/docs/html/training/wearables/notifications/index.jd
index 17f3cb3..a7b6733 100644
--- a/docs/html/training/wearables/notifications/index.jd
+++ b/docs/html/training/wearables/notifications/index.jd
@@ -1,4 +1,6 @@
page.title=Adding Wearable Features to Notifications
+page.tags="wear","notifications","wearables"
+page.image=wear/images/01_notifications.png
@jd:body
<div id="tb-wrapper">
diff --git a/docs/html/training/wearables/notifications/stacks.jd b/docs/html/training/wearables/notifications/stacks.jd
index e71e74c..9a528a4 100644
--- a/docs/html/training/wearables/notifications/stacks.jd
+++ b/docs/html/training/wearables/notifications/stacks.jd
@@ -45,7 +45,7 @@ final static String GROUP_KEY_EMAILS = "group_key_emails";
Notification notif = new NotificationCompat.Builder(mContext)
.setContentTitle("New mail from " + sender1)
.setContentText(subject1)
- .setSmallIcon(R.drawable.new_mail);
+ .setSmallIcon(R.drawable.new_mail)
.setGroup(GROUP_KEY_EMAILS)
.build();
@@ -65,7 +65,7 @@ instead of as a new card:</p>
Notification notif2 = new NotificationCompat.Builder(mContext)
.setContentTitle("New mail from " + sender2)
.setContentText(subject2)
- .setSmallIcon(R.drawable.new_mail);
+ .setSmallIcon(R.drawable.new_mail)
.setGroup(GROUP_KEY_EMAILS)
.build();
diff --git a/docs/html/training/wearables/ui/index.jd b/docs/html/training/wearables/ui/index.jd
index 8ef6fe7..5d97490 100644
--- a/docs/html/training/wearables/ui/index.jd
+++ b/docs/html/training/wearables/ui/index.jd
@@ -1,4 +1,5 @@
page.title=Creating Custom UIs for Wear Devices
+page.image=wear/images/10_uilib.png
@jd:body