summaryrefslogtreecommitdiffstats
path: root/docs/html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html')
-rw-r--r--docs/html/images/training/backward-compatible-ui-classes-eclair.pngbin0 -> 11962 bytes
-rw-r--r--docs/html/images/training/backward-compatible-ui-classes-honeycomb.pngbin0 -> 13123 bytes
-rw-r--r--docs/html/images/training/backward-compatible-ui-classes.pngbin0 -> 22677 bytes
-rw-r--r--docs/html/images/training/backward-compatible-ui-gb.pngbin0 -> 17373 bytes
-rw-r--r--docs/html/images/training/backward-compatible-ui-ics.pngbin0 -> 16147 bytes
-rw-r--r--docs/html/images/training/implementing-navigation-up.pngbin0 -> 8320 bytes
-rw-r--r--docs/html/resources/resources_toc.cs53
-rw-r--r--docs/html/sdk/sdk_toc.cs2
-rw-r--r--docs/html/sdk/tools-notes.jd34
-rw-r--r--docs/html/shareables/training/EffectiveNavigation.zipbin0 -> 29897 bytes
-rw-r--r--docs/html/shareables/training/LocationAware.zipbin36310 -> 261408 bytes
-rw-r--r--docs/html/shareables/training/TabCompat.zipbin0 -> 579116 bytes
-rw-r--r--docs/html/training/backward-compatible-ui/abstracting.jd111
-rw-r--r--docs/html/training/backward-compatible-ui/index.jd57
-rw-r--r--docs/html/training/backward-compatible-ui/new-implementation.jd113
-rw-r--r--docs/html/training/backward-compatible-ui/older-implementation.jd126
-rw-r--r--docs/html/training/backward-compatible-ui/using-component.jd143
-rw-r--r--docs/html/training/implementing-navigation/ancestral.jd124
-rw-r--r--docs/html/training/implementing-navigation/descendant.jd65
-rw-r--r--docs/html/training/implementing-navigation/index.jd68
-rw-r--r--docs/html/training/implementing-navigation/lateral.jd252
-rw-r--r--docs/html/training/implementing-navigation/temporal.jd83
-rw-r--r--docs/html/training/location/locationmanager.jd30
23 files changed, 1258 insertions, 3 deletions
diff --git a/docs/html/images/training/backward-compatible-ui-classes-eclair.png b/docs/html/images/training/backward-compatible-ui-classes-eclair.png
new file mode 100644
index 0000000..febba5b
--- /dev/null
+++ b/docs/html/images/training/backward-compatible-ui-classes-eclair.png
Binary files differ
diff --git a/docs/html/images/training/backward-compatible-ui-classes-honeycomb.png b/docs/html/images/training/backward-compatible-ui-classes-honeycomb.png
new file mode 100644
index 0000000..ba14252
--- /dev/null
+++ b/docs/html/images/training/backward-compatible-ui-classes-honeycomb.png
Binary files differ
diff --git a/docs/html/images/training/backward-compatible-ui-classes.png b/docs/html/images/training/backward-compatible-ui-classes.png
new file mode 100644
index 0000000..c5a3cd8
--- /dev/null
+++ b/docs/html/images/training/backward-compatible-ui-classes.png
Binary files differ
diff --git a/docs/html/images/training/backward-compatible-ui-gb.png b/docs/html/images/training/backward-compatible-ui-gb.png
new file mode 100644
index 0000000..621ee63
--- /dev/null
+++ b/docs/html/images/training/backward-compatible-ui-gb.png
Binary files differ
diff --git a/docs/html/images/training/backward-compatible-ui-ics.png b/docs/html/images/training/backward-compatible-ui-ics.png
new file mode 100644
index 0000000..6460554
--- /dev/null
+++ b/docs/html/images/training/backward-compatible-ui-ics.png
Binary files differ
diff --git a/docs/html/images/training/implementing-navigation-up.png b/docs/html/images/training/implementing-navigation-up.png
new file mode 100644
index 0000000..18f3779
--- /dev/null
+++ b/docs/html/images/training/implementing-navigation-up.png
Binary files differ
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index 5297c23..686bde3 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -227,7 +227,31 @@ class="new">&nbsp;new!</span></span>
</li>
</ul>
</li>
-
+
+ <li class="toggle-list">
+ <div><a href="<?cs var:toroot ?>training/backward-compatible-ui/index.html">
+ <span class="en">Creating Backward-Compatible UIs<span class="new">&nbsp;new!</span></span>
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/abstracting.html">
+ <span class="en">Abstracting the New APIs</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/new-implementation.html">
+ <span class="en">Proxying to the New APIs</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/older-implementation.html">
+ <span class="en">Creating an Implementation with Older APIs</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/backward-compatible-ui/using-component.html">
+ <span class="en">Using the Version-Aware Component</span>
+ </a>
+ </li>
+ </ul>
+ </li>
+
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>training/enterprise/index.html">
<span class="en">Developing for Enterprise</span>
@@ -278,7 +302,32 @@ class="new">&nbsp;new!</span></span>
</a>
</li>
</ul>
- </li>
+ </li>
+
+ <li class="toggle-list">
+ <div><a href="<?cs var:toroot ?>training/implementing-navigation/index.html">
+ <span class="en">Implementing Effective Navigation<span class="new">&nbsp;new!</span></span>
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>training/implementing-navigation/lateral.html">
+ <span class="en">Implementing Lateral Navigation</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/implementing-navigation/ancestral.html">
+ <span class="en">Implementing Ancestral Navigation</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/implementing-navigation/temporal.html">
+ <span class="en">Implementing Temporal Navigation</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/implementing-navigation/descendant.html">
+ <span class="en">Implementing Descendant Navigation</span>
+ </a>
+ </li>
+ </ul>
+ </li>
+
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>training/tv/index.html">
<span class="en">Designing for TV<span class="new">&nbsp;new!</span></span>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index a70b0f3..e994d95 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -151,7 +151,7 @@
</li>
</ul>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r18</a></li>
+ <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r19</a></li>
<li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li>
<li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Support Package, r7</a></li>
</ul>
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index f4e9d4d..062f8f1 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -68,6 +68,40 @@ padding: .25em 1em;
<a href="#" onclick="return toggleDiv(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
width="9px" />
+ SDK Tools, Revision 19</a> <em>(April 2012)</em>
+
+ <div class="toggleme">
+ <p class="note"><strong>Note:</strong> This update of SDK Tools is only available through
+the <a href="{@docRoot}sdk/adding-components.html">Android SDK Manager</a>. Use this tool to
+download and install this update.</p>
+
+ <dl>
+ <dt>Dependencies:</dt>
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 9 or later.</li>
+ <li>If you are developing in Eclipse with ADT, note that the SDK Tools r19 is designed for
+ use with ADT 18.0.0 and later. If you haven't already, we highly recommend updating your
+ <a href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin</a> to 18.0.0.</li>
+ <li>If you are developing outside Eclipse, you must have
+ <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+ </ul>
+ </dd>
+ <dt>Bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed an issue that prevented some developers from running the emulator with GPU
+acceleration.</li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
+
+<div class="toggleable closed">
+ <a href="#" onclick="return toggleDiv(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+ width="9px" />
SDK Tools, Revision 18</a> <em>(April 2012)</em>
<div class="toggleme">
diff --git a/docs/html/shareables/training/EffectiveNavigation.zip b/docs/html/shareables/training/EffectiveNavigation.zip
new file mode 100644
index 0000000..f21af45
--- /dev/null
+++ b/docs/html/shareables/training/EffectiveNavigation.zip
Binary files differ
diff --git a/docs/html/shareables/training/LocationAware.zip b/docs/html/shareables/training/LocationAware.zip
index 46970cd..8ed97cb 100644
--- a/docs/html/shareables/training/LocationAware.zip
+++ b/docs/html/shareables/training/LocationAware.zip
Binary files differ
diff --git a/docs/html/shareables/training/TabCompat.zip b/docs/html/shareables/training/TabCompat.zip
new file mode 100644
index 0000000..b70b442
--- /dev/null
+++ b/docs/html/shareables/training/TabCompat.zip
Binary files differ
diff --git a/docs/html/training/backward-compatible-ui/abstracting.jd b/docs/html/training/backward-compatible-ui/abstracting.jd
new file mode 100644
index 0000000..1141b54
--- /dev/null
+++ b/docs/html/training/backward-compatible-ui/abstracting.jd
@@ -0,0 +1,111 @@
+page.title=Abstracting the New APIs
+parent.title=Creating Backward-Compatible UIs
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Proxying to the New APIs
+next.link=new-implementation.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ul>
+ <li><a href="#prepare-abstraction">Prepare for Abstraction</a></li>
+ <li><a href="#create-abstract-tab">Create an Abstract Tab Interface</a></li>
+ <li><a href="#abstract-actionbar-tab">Abstract ActionBar.Tab</a></li>
+ <li><a href="#abstract-actionbar-methods">Abstract ActionBar Tab Methods</a></li>
+</ul>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/TabCompat.zip"
+ class="button">Download the sample app</a>
+<p class="filename">TabCompat.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>Suppose you want to use <a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">action bar tabs</a> as the primary form of top-level navigation in your application. Unfortunately, the {@link android.app.ActionBar} APIs are only available in Android 3.0 or later (API level 11+). Thus, if you want to distribute your application to devices running earlier versions of the platform, you need to provide an implementation that supports the newer API while providing a fallback mechanism that uses older APIs.</p>
+
+<p>In this class, you build a tabbed user interface (UI) component that uses abstract classes with version-specific implementations to provide backward-compatibility. This lesson describes how to create an abstraction layer for the new tab APIs as the first step toward building the tab component.</p>
+
+<h2 id="prepare-abstraction">Prepare for Abstraction</h2>
+
+<p><a href="http://en.wikipedia.org/wiki/Abstraction_(computer_science)">Abstraction</a> in the Java programming language involves the creation of one or more interfaces or abstract classes to hide implementation details. In the case of newer Android APIs, you can use abstraction to build version-aware components that use the current APIs on newer devices, and fallback to older, more compatible APIs on older devices.</p>
+
+<p>When using this approach, you first determine what newer classes you want to be able to use in a backward compatible way, then create abstract classes, based on the public interfaces of the newer classes. In defining the abstraction interfaces, you should mirror the newer API as much as possible. This maximizes forward-compatibility and makes it easier to drop the abstraction layer in the future when it is no longer necessary.</p>
+
+<p>After creating abstract classes for these new APIs, any number of implementations can be created and chosen at runtime. For the purposes of backward-compatibility, these implementations can vary by required API level. Thus, one implementation may use recently released APIs, while others can use older APIs.</p>
+
+<h2 id="create-abstract-tab">Create an Abstract Tab Interface</h2>
+
+<p>In order to create a backward-compatible version of tabs, you should first determine which features and specific APIs your application requires. In the case of top-level section tabs, suppose you have the following functional requirements:</p>
+
+<ol>
+<li>Tab indicators should show text and an icon.</li>
+<li>Tabs can be associated with a fragment instance.</li>
+<li>The activity should be able to listen for tab changes.</li>
+</ol>
+
+<p>Preparing these requirements in advance allows you to control the scope of your abstraction layer. This means that you can spend less time creating multiple implementations of your abstraction layer and begin using your new backward-compatible implementation sooner.</p>
+
+<p>The key APIs for tabs are in {@link android.app.ActionBar} and {@link android.app.ActionBar.Tab ActionBar.Tab}. These are the APIs to abstract in order to make your tabs version-aware. The requirements for this example project call for compatibility back to Eclair (API level 5) while taking advantage of the new tab features in Honeycomb (API Level 11). A diagram of the class structure to support these two implementations and their abstract base classes (or interfaces) is shown below.</p>
+
+<img src="{@docRoot}images/training/backward-compatible-ui-classes.png"
+ alt="Class diagram of abstract base classes and version-specific implementations." id="figure-classes">
+
+<p class="img-caption"><strong>Figure 1.</strong> Class diagram of abstract base classes and version-specific implementations.</p>
+
+<h2 id="abstract-actionbar-tab">Abstract ActionBar.Tab</h2>
+
+<p>Get started on building your tab abstraction layer by creating an abstract class representing a tab, that mirrors the {@link android.app.ActionBar.Tab ActionBar.Tab} interface:</p>
+
+<pre>
+public abstract class CompatTab {
+ ...
+ public abstract CompatTab setText(int resId);
+ public abstract CompatTab setIcon(int resId);
+ public abstract CompatTab setTabListener(
+ CompatTabListener callback);
+ public abstract CompatTab setFragment(Fragment fragment);
+
+ public abstract CharSequence getText();
+ public abstract Drawable getIcon();
+ public abstract CompatTabListener getCallback();
+ public abstract Fragment getFragment();
+ ...
+}
+</pre>
+
+<p>You can use an abstract class instead of an interface here to simplify the implementation of common features such as association of tab objects with activities (not shown in the code snippet).</p>
+
+<h2 id="abstract-actionbar-methods">Abstract ActionBar Tab Methods</h2>
+
+<p>Next, define an abstract class that allows you to create and add tabs to an activity, like {@link android.app.ActionBar#newTab ActionBar.newTab()} and {@link android.app.ActionBar#addTab ActionBar.addTab()}:</p>
+
+<pre>
+public abstract class TabHelper {
+ ...
+
+ public CompatTab newTab(String tag) {
+ // This method is implemented in a later lesson.
+ }
+
+ public abstract void addTab(CompatTab tab);
+
+ ...
+}
+</pre>
+
+<p>In the next lessons, you create implementations for <code>TabHelper</code> and <code>CompatTab</code> that work across both older and newer platform versions.</p>
diff --git a/docs/html/training/backward-compatible-ui/index.jd b/docs/html/training/backward-compatible-ui/index.jd
new file mode 100644
index 0000000..7e27e68
--- /dev/null
+++ b/docs/html/training/backward-compatible-ui/index.jd
@@ -0,0 +1,57 @@
+page.title=Creating Backward-Compatible UIs
+
+trainingnavtop=true
+startpage=true
+next.title=Abstracting the New Implementation
+next.link=abstracting.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+
+<ul>
+ <li>API level 5</li>
+ <li><a href="{@docRoot}sdk/compatibility-library.html">The Android Support Package</a></li>
+</ul>
+
+<h2>You should also read</h2>
+
+<ul>
+ <li><a href="{@docRoot}resources/samples/ActionBarCompat/index.html">ActionBarCompat</a></li>
+ <li><a href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">How to have your (Cup)cake and eat it too</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/TabCompat.zip"
+ class="button">Download the sample app</a>
+<p class="filename">TabCompat.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>This class demonstrates how to use UI components and APIs available in newer versions of Android in a backward-compatible way, ensuring that your application still runs on previous versions of the platform.</p>
+
+<p>Throughout this class, the new <a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a> feature introduced in Android 3.0 (API level 11) serves as the guiding example, but you can apply these techniques to other UI components and API features.</p>
+
+<h2 id="lessons">Lessons</h2>
+
+
+<dl>
+ <dt><strong><a href="abstracting.html">Abstracting the New APIs</a></strong></dt>
+ <dd>Determine which features and APIs your application needs. Learn how to define application-specific, intermediary Java interfaces that abstract the implementation of the UI component to your application.</dd>
+
+ <dt><strong><a href="new-implementation.html">Proxying to the New APIs</a></strong></dt>
+ <dd>Learn how to create an implementation of your interface that uses newer APIs.</dd>
+
+ <dt><strong><a href="older-implementation.html">Creating an Implementation with Older APIs</a></strong></dt>
+ <dd>Learn how to create a custom implementation of your interface that uses older APIs.</dd>
+
+ <dt><strong><a href="using-component.html">Using the Version-Aware Component</a></strong></dt>
+ <dd>Learn how to choose an implementation to use at runtime, and begin using the interface in your application.</dd>
+</dl>
diff --git a/docs/html/training/backward-compatible-ui/new-implementation.jd b/docs/html/training/backward-compatible-ui/new-implementation.jd
new file mode 100644
index 0000000..5b8b51c
--- /dev/null
+++ b/docs/html/training/backward-compatible-ui/new-implementation.jd
@@ -0,0 +1,113 @@
+page.title=Proxying to the New APIs
+parent.title=Creating Backward-Compatible UIs
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Abstracting the New APIs
+previous.link=abstracting.html
+next.title=Creating an Implementation with Older APIs
+next.link=older-implementation.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ol>
+ <li><a href="#new-tabs">Implement Tabs Using New APIs</a></li>
+ <li><a href="#compattabhoneycomb">Implement CompatTabHoneycomb</a></li>
+ <li><a href="#tabhelperhoneycomb">Implement TabHelperHoneycomb</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/actionbar.html#Tabs">Action Bar Tabs</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/TabCompat.zip"
+ class="button">Download the sample app</a>
+<p class="filename">TabCompat.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>This lesson shows you how to subclass the <code>CompatTab</code> and <code>TabHelper</code> abstract classes and use new APIs. Your application can use this implementation on devices running a platform version that supports them.</p>
+
+<h2 id="new-tabs">Implement Tabs Using New APIs</h2>
+
+<p>The concrete classes for <code>CompatTab</code> and <code>TabHelper</code> that use newer APIs are a <em>proxy</em> implementation. Since the abstract classes defined in the previous lesson mirror the new APIs (class structure, method signatures, etc.), the concrete classes that use these newer APIs simply proxy method calls and their results.</p>
+
+<p>You can directly use newer APIs in these concrete classes&mdash;and not crash on earlier devices&mdash;because of lazy class loading. Classes are loaded and initialized on first access&mdash;instantiating the class or accessing one of its static fields or methods for the first time. Thus, as long as you don't instantiate the Honeycomb-specific implementations on pre-Honeycomb devices, the Dalvik VM won't throw any {@link java.lang.VerifyError} exceptions.</p>
+
+<p>A good naming convention for this implementation is to append the API level or platform version code name corresponding to the APIs required by the concrete classes. For example, the native tab implementation can be provided by <code>CompatTabHoneycomb</code> and <code>TabHelperHoneycomb</code> classes, since they rely on APIs available in Android 3.0 (API level 11) or later.</p>
+
+<img src="{@docRoot}images/training/backward-compatible-ui-classes-honeycomb.png"
+ alt="Class diagram for the Honeycomb implementation of tabs." id="figure-classes">
+
+<p class="img-caption"><strong>Figure 1.</strong> Class diagram for the Honeycomb implementation of tabs.</p>
+
+<h2 id="compattabhoneycomb">Implement CompatTabHoneycomb</h2>
+
+<p><code>CompatTabHoneycomb</code> is the implementation of the <code>CompatTab</code> abstract class that <code>TabHelperHoneycomb</code> uses to reference individual tabs. <code>CompatTabHoneycomb</code> simply proxies all method calls to its contained {@link android.app.ActionBar.Tab} object.</p>
+
+<p>Begin implementing <code>CompatTabHoneycomb</code> using the new {@link android.app.ActionBar.Tab ActionBar.Tab} APIs:</p>
+
+<pre>
+public class CompatTabHoneycomb extends CompatTab {
+ // The native tab object that this CompatTab acts as a proxy for.
+ ActionBar.Tab mTab;
+ ...
+
+ protected CompatTabHoneycomb(FragmentActivity activity, String tag) {
+ ...
+ // Proxy to new ActionBar.newTab API
+ mTab = activity.getActionBar().newTab();
+ }
+
+ public CompatTab setText(int resId) {
+ // Proxy to new ActionBar.Tab.setText API
+ mTab.setText(resId);
+ return this;
+ }
+
+ ...
+ // Do the same for other properties (icon, callback, etc.)
+}
+</pre>
+
+<h2 id="tabhelperhoneycomb">Implement TabHelperHoneycomb</h2>
+
+<p><code>TabHelperHoneycomb</code> is the implementation of the <code>TabHelper</code> abstract class that proxies method calls to an actual {@link android.app.ActionBar}, obtained from its contained {@link android.app.Activity}.</p>
+
+<p>Implement <code>TabHelperHoneycomb</code>, proxying method calls to the {@link android.app.ActionBar} API:</p>
+
+<pre>
+public class TabHelperHoneycomb extends TabHelper {
+ ActionBar mActionBar;
+ ...
+
+ protected void setUp() {
+ if (mActionBar == null) {
+ mActionBar = mActivity.getActionBar();
+ mActionBar.setNavigationMode(
+ ActionBar.NAVIGATION_MODE_TABS);
+ }
+ }
+
+ public void addTab(CompatTab tab) {
+ ...
+ // Tab is a CompatTabHoneycomb instance, so its
+ // native tab object is an ActionBar.Tab.
+ mActionBar.addTab((ActionBar.Tab) tab.getTab());
+ }
+
+ // The other important method, newTab() is part of
+ // the base implementation.
+}
+</pre> \ No newline at end of file
diff --git a/docs/html/training/backward-compatible-ui/older-implementation.jd b/docs/html/training/backward-compatible-ui/older-implementation.jd
new file mode 100644
index 0000000..5006123
--- /dev/null
+++ b/docs/html/training/backward-compatible-ui/older-implementation.jd
@@ -0,0 +1,126 @@
+page.title=Creating an Implementation with Older APIs
+parent.title=Creating Backward-Compatible UIs
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Proxying to the New APIs
+previous.link=new-implementation.html
+next.title=Using the Version-Aware Component
+next.link=using-component.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ol>
+ <li><a href="#decide-substitute">Decide on a Substitute Solution</a></li>
+ <li><a href="#older-tabs">Implement Tabs Using Older APIs</a></li>
+</ol>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/TabCompat.zip"
+ class="button">Download the sample app</a>
+<p class="filename">TabCompat.zip</p>
+</div>
+
+</div>
+</div>
+
+
+<p>This lesson discusses how to create an implementation that mirrors newer APIs yet supports older devices.</p>
+
+<h2 id="decide-substitute">Decide on a Substitute Solution</h2>
+
+<p>The most challenging task in using newer UI features in a backward-compatible way is deciding on and implementing an older (fallback) solution for older platform versions. In many cases, it's possible to fulfill the purpose of these newer UI components using older UI framework features. For example:</p>
+
+<ul>
+
+<li>
+<p>Action bars can be implemented using a horizontal {@link android.widget.LinearLayout} containing image buttons, either as custom title bars or as views in your activity layout. Overflow actions can be presented under the device <em>Menu</em> button.</p>
+</li>
+
+<li>
+<p>Action bar tabs can be implemented using a horizontal {@link android.widget.LinearLayout} containing buttons, or using the {@link android.widget.TabWidget} UI element.</p>
+</li>
+
+<li>
+<p>{@link android.widget.NumberPicker} and {@link android.widget.Switch} widgets can be implemented using {@link android.widget.Spinner} and {@link android.widget.ToggleButton} widgets, respectively.</p>
+</li>
+
+<li>
+<p>{@link android.widget.ListPopupWindow} and {@link android.widget.PopupMenu} widgets can be implemented using {@link android.widget.PopupWindow} widgets.</p>
+</li>
+
+</ul>
+
+<p>There generally isn't a one-size-fits-all solution for backporting newer UI components to older devices. Be mindful of the user experience: on older devices, users may not be familiar with newer design patterns and UI components. Give some thought as to how the same functionality can be delivered using familiar elements. In many cases this is less of a concern&mdash;if newer UI components are prominent in the application ecosystem (such as the action bar), or where the interaction model is extremely simple and intuitive (such as swipe views using a {@link android.support.v4.view.ViewPager}).</p>
+
+<h2 id="older-tabs">Implement Tabs Using Older APIs</h2>
+
+<p>To create an older implementation of action bar tabs, you can use a {@link android.widget.TabWidget} and {@link android.widget.TabHost} (although one can alternatively use horizontally laid-out {@link android.widget.Button} widgets). Implement this in classes called <code>TabHelperEclair</code> and <code>CompatTabEclair</code>, since this implementation uses APIs introduced no later than Android 2.0 (Eclair).</p>
+
+
+<img src="{@docRoot}images/training/backward-compatible-ui-classes-eclair.png"
+ alt="Class diagram for the Eclair implementation of tabs." id="figure-classes">
+
+<p class="img-caption"><strong>Figure 1.</strong> Class diagram for the Eclair implementation of tabs.</p>
+
+<p>The <code>CompatTabEclair</code> implementation stores tab properties such as the tab text and icon in instance variables, since there isn't an {@link android.app.ActionBar.Tab ActionBar.Tab} object available to handle this storage:</p>
+
+<pre>
+public class CompatTabEclair extends CompatTab {
+ // Store these properties in the instance,
+ // as there is no ActionBar.Tab object.
+ private CharSequence mText;
+ ...
+
+ public CompatTab setText(int resId) {
+ // Our older implementation simply stores this
+ // information in the object instance.
+ mText = mActivity.getResources().getText(resId);
+ return this;
+ }
+
+ ...
+ // Do the same for other properties (icon, callback, etc.)
+}
+</pre>
+
+<p>The <code>TabHelperEclair</code> implementation makes use of methods on the
+{@link android.widget.TabHost} widget for creating {@link android.widget.TabHost.TabSpec}
+objects and tab indicators:</p>
+
+<pre>
+public class TabHelperEclair extends TabHelper {
+ private TabHost mTabHost;
+ ...
+
+ protected void setUp() {
+ if (mTabHost == null) {
+ // Our activity layout for pre-Honeycomb devices
+ // must contain a TabHost.
+ mTabHost = (TabHost) mActivity.findViewById(
+ android.R.id.tabhost);
+ mTabHost.setup();
+ }
+ }
+
+ public void addTab(CompatTab tab) {
+ ...
+ TabSpec spec = mTabHost
+ .newTabSpec(tag)
+ .setIndicator(tab.getText()); // And optional icon
+ ...
+ mTabHost.addTab(spec);
+ }
+
+ // The other important method, newTab() is part of
+ // the base implementation.
+}
+</pre>
+
+<p>You now have two implementations of <code>CompatTab</code> and <code>TabHelper</code>: one that works on devices running Android 3.0 or later and uses new APIs, and another that works on devices running Android 2.0 or later and uses older APIs. The next lesson discusses using these implementations in your application.</p>
diff --git a/docs/html/training/backward-compatible-ui/using-component.jd b/docs/html/training/backward-compatible-ui/using-component.jd
new file mode 100644
index 0000000..4bf7fa0
--- /dev/null
+++ b/docs/html/training/backward-compatible-ui/using-component.jd
@@ -0,0 +1,143 @@
+page.title=Using the Version-Aware Component
+parent.title=Creating Backward-Compatible UIs
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Creating an Implementation with Older APIs
+previous.link=older-implementation.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ol>
+ <li><a href="#switching-logic">Add the Switching Logic</a></li>
+ <li><a href="#layout">Create a Version-Aware Activity Layout</a></li>
+ <li><a href="#use-tabhelper">Use TabHelper in Your Activity</a></li>
+</ol>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/TabCompat.zip"
+ class="button">Download the sample app</a>
+<p class="filename">TabCompat.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>Now that you have two implementations of <code>TabHelper</code> and <code>CompatTab</code>&mdash;one for Android 3.0 and later and one for earlier versions of the platform&mdash;it's time to do something with these implementations. This lesson discusses creating the logic for switching between these implementations, creating version-aware layouts, and finally using the backward-compatible UI component.</p>
+
+<h2 id="switching-logic">Add the Switching Logic</h2>
+
+<p>The <code>TabHelper</code> abstract class acts as a <a href="http://en.wikipedia.org/wiki/Factory_(software_concept)">factory</a> for creating version-appropriate <code>TabHelper</code> and <code>CompatTab</code> instances, based on the current device's platform version:</p>
+
+<pre>
+public abstract class TabHelper {
+ ...
+ // Usage is TabHelper.createInstance(activity)
+ public static TabHelper createInstance(FragmentActivity activity) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ return new TabHelperHoneycomb(activity);
+ } else {
+ return new TabHelperEclair(activity);
+ }
+ }
+
+ // Usage is mTabHelper.newTab("tag")
+ public CompatTab newTab(String tag) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ return new CompatTabHoneycomb(mActivity, tag);
+ } else {
+ return new CompatTabEclair(mActivity, tag);
+ }
+ }
+ ...
+}
+</pre>
+
+<h2 id="layout">Create a Version-Aware Activity Layout</h2>
+
+<p>The next step is to provide layouts for your activity that can support the two tab implementations. For the older implementation (<code>TabHelperEclair</code>), you need to ensure that your activity layout contains a {@link android.widget.TabWidget} and {@link android.widget.TabHost}, along with a container for tab contents:</p>
+
+<p><strong>res/layout/main.xml:</strong></p>
+
+<pre>
+&lt;!-- This layout is for API level 5-10 only. --&gt;
+&lt;TabHost xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/tabhost"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"&gt;
+
+ &lt;LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="5dp"&gt;
+
+ &lt;TabWidget
+ android:id="@android:id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" /&gt;
+
+ &lt;FrameLayout
+ android:id="@android:id/tabcontent"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" /&gt;
+
+ &lt;/LinearLayout&gt;
+&lt;/TabHost&gt;
+</pre>
+
+<p>For the <code>TabHelperHoneycomb</code> implementation, all you need is a {@link android.widget.FrameLayout} to contain the tab contents, since the tab indicators are provided by the {@link android.app.ActionBar}:</p>
+
+<p><strong>res/layout-v11/main.xml:</strong></p>
+
+<pre>
+&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/tabcontent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" /&gt;
+</pre>
+
+<p>At runtime, Android will decide which version of the <code>main.xml</code> layout to inflate depending on the platform version. This is the same logic shown in the previous section to determine which <code>TabHelper</code> implementation to use.</p>
+
+<h2 id="use-tabhelper">Use TabHelper in Your Activity</h2>
+
+<p>In your activity's {@link android.app.Activity#onCreate onCreate()} method, you can obtain a <code>TabHelper</code> object and add tabs with the following code:</p>
+
+<pre>
+{@literal @}Override
+public void onCreate(Bundle savedInstanceState) {
+ setContentView(R.layout.main);
+
+ TabHelper tabHelper = TabHelper.createInstance(this);
+ tabHelper.setUp();
+
+ CompatTab photosTab = tabHelper
+ .newTab("photos")
+ .setText(R.string.tab_photos);
+ tabHelper.addTab(photosTab);
+
+ CompatTab videosTab = tabHelper
+ .newTab("videos")
+ .setText(R.string.tab_videos);
+ tabHelper.addTab(videosTab);
+}
+</pre>
+
+<p>When running the application, this code inflates the correct activity layout and instantiates either a <code>TabHelperHoneycomb</code> or <code>TabHelperEclair</code> object. The concrete class that's actually used is opaque to the activity, since they share the common <code>TabHelper</code> interface.</p>
+
+<p>Below are two screenshots of this implementation running on an Android 2.3 and Android 4.0 device.</p>
+
+<img src="{@docRoot}images/training/backward-compatible-ui-gb.png"
+ alt="Example screenshot of tabs running on an Android 2.3 device (using TabHelperEclair)." width="200">
+
+<img src="{@docRoot}images/training/backward-compatible-ui-ics.png"
+ alt="Example screenshots of tabs running on an Android 4.0 device (using TabHelperHoneycomb)." width="200">
+
+<p class="img-caption"><strong>Figure 1.</strong> Example screenshots of backward-compatible tabs running on an Android 2.3 device (using <code>TabHelperEclair</code>) and an Android 4.0 device (using <code>TabHelperHoneycomb</code>).</p>
diff --git a/docs/html/training/implementing-navigation/ancestral.jd b/docs/html/training/implementing-navigation/ancestral.jd
new file mode 100644
index 0000000..495b45d
--- /dev/null
+++ b/docs/html/training/implementing-navigation/ancestral.jd
@@ -0,0 +1,124 @@
+page.title=Implementing Ancestral Navigation
+parent.title=Implementing Effective Navigation
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Implementing Lateral Navigation
+previous.link=lateral.html
+next.title=Implementing Temporal Navigation
+next.link=temporal.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ol>
+ <li><a href="#up">Implement <em>Up</em> Navigation</a></li>
+ <li><a href="#app-home">Properly Handle the Application Home Screen</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}training/design-navigation/ancestral-temporal.html">Providing Ancestral and Temporal Navigation</a></li>
+ <li><a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a></li>
+ <li><a href="{@docRoot}design/patterns/navigation.html">Android Design: Navigation</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip"
+ class="button">Download the sample app</a>
+<p class="filename">EffectiveNavigation.zip</p>
+</div>
+
+</div>
+</div>
+
+
+<p><em>Ancestral navigation</em> is up the application's information hierarchy, where the top of the hierarchy (or root) is the application's home screen. This navigation concept is described in <a href="{@docRoot}training/design-navigation/ancestral-temporal.html">Designing Effective Navigation</a>. This lesson discusses how to provide ancestral navigation using the <em>Up</em> button in the action bar.</p>
+
+
+<h2 id="up">Implement <em>Up</em> Navigation</h2>
+
+<p>When implementing ancestral navigation, all screens in your application that aren't the home screen should offer a means of navigating to the immediate parent screen in the hierarchy via the <em>Up</em> button in the action bar.</p>
+
+
+<img src="{@docRoot}images/training/implementing-navigation-up.png"
+ alt="The Up button in the action bar." id="figure-up">
+
+<p class="img-caption"><strong>Figure 1.</strong> The <em>Up</em> button in the action bar.</p>
+
+<p>Regardless of how the current screen was reached, pressing this button should always take the user to the same screen in the hierarchy.</p>
+
+<p>To implement <em>Up</em>, enable it in the action bar in your activity's {@link android.app.Activity#onCreate onCreate()} method:</p>
+
+<pre>
+{@literal @}Override
+public void onCreate(Bundle savedInstanceState) {
+ ...
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ ...
+}
+</pre>
+
+<p>You should also handle <code>android.R.id.home</code> in {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()}. This resource is the menu item ID for the <em>Home</em> (or <em>Up</em>) button. To ensure that a specific parent activity is shown, <em>DO NOT</em> simply call {@link android.app.Activity#finish finish()}. Instead, use an intent such as the one described below.</p>
+
+<pre>
+{@literal @}Override
+public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // This is called when the Home (Up) button is pressed
+ // in the Action Bar.
+ Intent parentActivityIntent = new Intent(this, MyParentActivity.class);
+ parentActivityIntent.addFlags(
+ Intent.FLAG_ACTIVITY_CLEAR_TOP |
+ Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(parentActivityIntent);
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+}
+</pre>
+
+<p>When the current activity belongs to a task from a different application&mdash;for example if it was reached via an intent from another application&mdash;pressing <em>Up</em> should create a new task for the application with a synthesized back stack. This approach is described in <a href="{@docRoot}design/patterns/navigation.html">Android Design: Navigation</a> and the {@link android.support.v4.app.TaskStackBuilder} class reference.</p>
+
+<p>The {@link android.support.v4.app.NavUtils} and {@link android.support.v4.app.TaskStackBuilder} classes in the <a href="{@docRoot}sdk/compatibility-library.html">Android Support Package</a> provide helpers for implementing this behavior correctly. An example usage of these two helper classes is below:</p>
+
+<pre>
+{@literal @}Override
+public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ Intent upIntent = new Intent(this, MyParentActivity.class);
+ if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
+ // This activity is not part of the application's task, so create a new task
+ // with a synthesized back stack.
+ TaskStackBuilder.from(this)
+ .addNextIntent(new Intent(this, MyGreatGrandParentActivity.class))
+ .addNextIntent(new Intent(this, MyGrandParentActivity.class))
+ .addNextIntent(upIntent)
+ .startActivities();
+ finish();
+ } else {
+ // This activity is part of the application's task, so simply
+ // navigate up to the hierarchical parent activity.
+ NavUtils.navigateUpTo(this, upIntent);
+ }
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+}
+</pre>
+
+<h2 id="app-home">Properly Handle the Application Home Screen</h2>
+
+<p>By default, the <em>Home</em> button in the action bar is interactive. Since it does not make much sense to navigate home&mdash;or up one level&mdash;while on the home screen, you should disable the button like so:</p>
+
+<pre>
+getActionBar().setHomeButtonEnabled(false);
+</pre>
diff --git a/docs/html/training/implementing-navigation/descendant.jd b/docs/html/training/implementing-navigation/descendant.jd
new file mode 100644
index 0000000..7d0063c
--- /dev/null
+++ b/docs/html/training/implementing-navigation/descendant.jd
@@ -0,0 +1,65 @@
+page.title=Implementing Descendant Navigation
+parent.title=Implementing Effective Navigation
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Implementing Temporal Navigation
+previous.link=temporal.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ol>
+ <li><a href="#master-detail">Implement Master/Detail Flows Across Handsets and Tablets</a></li>
+ <li><a href="#external-activities">Navigate into External Activities</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}training/design-navigation/descendant-lateral.html">Providing Descendant and Lateral Navigation</a></li>
+ <li><a href="{@docRoot}design/patterns/app-structure.html">Android Design: App Structure</a></li>
+ <li><a href="{@docRoot}design/patterns/multi-pane-layouts.html">Android Design: Multi-pane Layouts</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip"
+ class="button">Download the sample app</a>
+<p class="filename">EffectiveNavigation.zip</p>
+</div>
+
+</div>
+</div>
+
+
+<p><em>Descendant navigation</em> is navigation down the application's information hierarchy. This is described in <a href="{@docRoot}training/design-navigation/descendant-lateral.html">Designing Effective Navigation</a> and also covered in <a href="{@docRoot}design/patterns/app-structure.html">Android Design: Application Structure</a>.</p>
+
+<p>Descendant navigation is usually implemented using {@link android.content.Intent} objects and {@link android.content.Context#startActivity startActivity()}, or by adding fragments to an activity using {@link android.app.FragmentTransaction} objects. This lesson covers other interesting cases that arise when implementing descendant navigation.</p>
+
+<h2 id="master-detail">Implement Master/Detail Flows Across Handsets and Tablets</h2>
+
+<p>In a <em>master/detail</em> navigation flow, a <em>master</em> screen contains a list of items in a collection, and a <em>detail</em> screen shows detailed information about a specific item within that collection. Implementing navigation from the master screen to the detail screen is one form of descendant navigation.</p>
+
+<p>Handset touchscreens are most suitable for displaying one screen at a time (either the master or the detail screen); this concern is further discussed in <a href="{@docRoot}training/design-navigation/multiple-sizes.html">Planning for Multiple Touchscreen Sizes</a>. Descendant navigation in this case is often implemented using an {@link android.content.Intent} that starts an activity representing the detail screen. On the other hand, tablet displays, especially when viewed in the landscape orientation, are best suited for showing multiple content panes at a time: the master on the left, and the detail to the right). Here, descendant navigation is usually implemented using a {@link android.app.FragmentTransaction} that adds, removes, or replaces the detail pane with new content.</p>
+
+<p>The basics of implementing this pattern are described in the <a href="{@docRoot}training/multiscreen/adaptui.html">Implementing Adaptive UI Flows</a> lesson of the <em>Designing for Multiple Screens</em> class. The class describes how to implement a master/detail flow using two activities on a handset and a single activity on a tablet.</p>
+
+<h2 id="external-activities">Navigate into External Activities</h2>
+
+<p>There are cases where descending into your application's information hierarchy leads to activities from other applications. For example, when viewing the contact details screen for an entry in the phone address book, a child screen detailing recent posts by the contact on a social network may belong to a social networking application.</p>
+
+<p>When launching another application's activity to allow the user to say, compose an email or pick a photo attachment, you generally don't want the user to return to this activity if they relaunch your application from the Launcher (the device home screen). It would be confusing if touching your application icon brought the user to a "compose email" screen.</p>
+
+<p>To prevent this from occurring, simply add the {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET} flag to the intent used to launch the external activity, like so:</p>
+
+<pre>
+Intent externalActivityIntent = new Intent(Intent.ACTION_PICK);
+externalActivityIntent.setType("image/*");
+externalActivityIntent.addFlags(
+ Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+startActivity(externalActivityIntent);
+</pre>
diff --git a/docs/html/training/implementing-navigation/index.jd b/docs/html/training/implementing-navigation/index.jd
new file mode 100644
index 0000000..da61c81
--- /dev/null
+++ b/docs/html/training/implementing-navigation/index.jd
@@ -0,0 +1,68 @@
+page.title=Implementing Effective Navigation
+
+trainingnavtop=true
+startpage=true
+next.title=Implementing Lateral Navigation
+next.link=lateral.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+
+<ul>
+ <li>API level 14</li>
+ <li>Understanding of fragments and Android layouts</li>
+ <li><a href="{@docRoot}sdk/compatibility-library.html">The Android Support Package</a></li>
+ <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li>
+</ul>
+
+<h2>You should also read</h2>
+
+<ul>
+ <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
+ <li><a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a></li>
+ <li><a href="{@docRoot}training/multiscreen/index.html">Designing for Multiple Screens</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip"
+ class="button">Download the sample app</a>
+<p class="filename">EffectiveNavigation.zip</p>
+</div>
+
+</div>
+</div>
+
+
+<p>This class demonstrates how to implement the key navigation design patterns detailed in the
+<a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a> class.
+The lessons in this class cover implementing navigation up, down, and across your application's <a
+href="{@docRoot}training/design-navigation/screen-planning.html#diagram- relationships">screen
+map</a>.</p>
+
+<p>After reading through the lessons in this class and exploring the associated sample application
+(see right), you should also have a basic understanding of how to use
+{@link android.app.ActionBar} and {@link android.support.v4.view.ViewPager}, two components that are fundamental to core app navigation.</p>
+
+
+<h2 id="lessons">Lessons</h2>
+
+
+<dl>
+ <dt><strong><a href="lateral.html">Implementing Lateral Navigation</a></strong></dt>
+ <dd>Learn how to implement tabs and horizontal paging (swipe views).</dd>
+
+ <dt><strong><a href="ancestral.html">Implementing Ancestral Navigation</a></strong></dt>
+ <dd>Learn how to implement <em>Up</em> navigation.</dd>
+
+ <dt><strong><a href="temporal.html">Implementing Temporal Navigation</a></strong></dt>
+ <dd>Learn how to correctly handle the <em>Back</em> button.</dd>
+
+ <dt><strong><a href="descendant.html">Implementing Descendant Navigation</a></strong></dt>
+ <dd>Learn the finer points of implementing navigation into your application's information hierarchy.</dd>
+</dl>
diff --git a/docs/html/training/implementing-navigation/lateral.jd b/docs/html/training/implementing-navigation/lateral.jd
new file mode 100644
index 0000000..d9ba5c9
--- /dev/null
+++ b/docs/html/training/implementing-navigation/lateral.jd
@@ -0,0 +1,252 @@
+page.title=Implementing Lateral Navigation
+parent.title=Implementing Effective Navigation
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Implementing Ancestral Navigation
+next.link=ancestral.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#tabs">Implement Tabs</a></li>
+ <li><a href="#horizontal-paging">Implement Horizontal Paging (Swipe Views)</a></li>
+ <li><a href="#swipe-tabs">Implement Swiping Between Tabs</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}training/design-navigation/descendant-lateral.html">Providing Descendant and Lateral Navigation</a></li>
+ <li><a href="{@docRoot}design/building-blocks/tabs.html">Android Design: Tabs</a></li>
+ <li><a href="{@docRoot}design/patterns/swipe-views.html">Android Design: Swipe Views</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+<a href="http://developer.android.com/shareables/training/EffectiveNavigation.zip"
+ class="button">Download the sample app</a>
+<p class="filename">EffectiveNavigation.zip</p>
+</div>
+
+</div>
+</div>
+
+
+<p><em>Lateral navigation</em> is navigation between sibling screens in the application's screen hierarchy (sometimes referred to as a screen map). The most prominent lateral navigation patterns are tabs and horizontal paging (also known as swipe views). This pattern and others are described in <a href="{@docRoot}training/design-navigation/descendant-lateral.html">Designing Effective Navigation</a>. This lesson covers how to implement several of the primary lateral navigation patterns in Android.</p>
+
+<h2 id="tabs">Implement Tabs</h2>
+
+<p>Tabs allow the user to navigate between sibling screens by selecting the appropriate tab indicator available at the top of the display. In Android 3.0 and later, tabs are implemented using the {@link android.app.ActionBar} class, and are generally set up in {@link android.app.Activity#onCreate Activity.onCreate()}. In some cases, such as when horizontal space is limited and/or the number of tabs is large, an appropriate alternate presentation for tabs is a dropdown list (sometimes implemented using a {@link android.widget.Spinner}).</p>
+
+<p>In previous versions of Android, tabs could be implemented using a {@link android.widget.TabWidget} and {@link android.widget.TabHost}. For details, see the <a href="{@docRoot}resources/tutorials/views/hello-tabwidget.html">Hello, Views</a> tutorial.</p>
+
+<p>As of Android 3.0, however, you should use either {@link android.app.ActionBar#NAVIGATION_MODE_TABS} or {@link android.app.ActionBar#NAVIGATION_MODE_LIST} along with the {@link android.app.ActionBar} class.</p>
+
+<h3>Implement the Tabs Pattern with NAVIGATION_MODE_TABS</h3>
+
+<p>To create tabs, you can use the following code in your activity's {@link android.app.Activity#onCreate onCreate()} method. Note that the exact presentation of tabs may vary per device and by the current device configuration, to make best use of available screen space. For example, Android may automatically collapse tabs into a dropdown list if tabs don't fit horizontally in the action bar.</p>
+
+<pre>
+{@literal @}Override
+public void onCreate(Bundle savedInstanceState) {
+ ...
+ final ActionBar actionBar = getActionBar();
+
+ // Specify that tabs should be displayed in the action bar.
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+
+ // Create a tab listener that is called when the user changes tabs.
+ ActionBar.TabListener tabListener = new ActionBar.TabListener() {
+ public void onTabSelected(ActionBar.Tab tab,
+ FragmentTransaction ft) { }
+
+ public void onTabUnselected(ActionBar.Tab tab,
+ FragmentTransaction ft) { }
+
+ public void onTabReselected(ActionBar.Tab tab,
+ FragmentTransaction ft) { }
+ };
+
+ // Add 3 tabs.
+ for (int i = 0; i &lt; 3; i++) {
+ actionBar.addTab(
+ actionBar.newTab()
+ .setText("Tab " + (i + 1))
+ .setTabListener(tabListener));
+ }
+ ...
+}
+</pre>
+
+<h3>Implement the Tabs Pattern with NAVIGATION_MODE_LIST</h3>
+
+<p>To use a dropdown list instead, use the following code in your activity's {@link android.app.Activity#onCreate onCreate()} method. Dropdown lists are often preferable in cases where more information must be shown per navigation item, such as unread message counts, or where the number of available navigation items is large.</p>
+
+<pre>
+{@literal @}Override
+public void onCreate(Bundle savedInstanceState) {
+ ...
+ final ActionBar actionBar = getActionBar();
+
+ // Specify that a dropdown list should be displayed in the action bar.
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+
+ actionBar.setListNavigationCallbacks(
+ // Specify a SpinnerAdapter to populate the dropdown list.
+ new ArrayAdapter<String>(
+ actionBar.getThemedContext(),
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ new String[]{ "Tab 1", "Tab 2", "Tab 3" }),
+
+ // Provide a listener to be called when an item is selected.
+ new ActionBar.OnNavigationListener() {
+ public boolean onNavigationItemSelected(
+ int position, long id) {
+ // Take action here, e.g. switching to the
+ // corresponding fragment.
+ return true;
+ }
+ });
+ ...
+}
+</pre>
+
+<h2 id="horizontal-paging">Implement Horizontal Paging (Swipe Views)</h2>
+
+<p>Horizontal paging, or swipe views, allow users to <a href="{@docRoot}design/patterns/swipe-views">swipe</a> horizontally on the current screen to navigate to adjacent screens. This pattern can be implemented using the {@link android.support.v4.view.ViewPager} widget, currently available as part of the <a href="{@docRoot}sdk/compatibility-library.html">Android Support Package</a>. For navigating between sibling screens representing a fixed number of sections, it's best to provide the {@link android.support.v4.view.ViewPager} with a {@link android.support.v4.app.FragmentPagerAdapter}. For horizontal paging across collections of objects, it's best to use a {@link android.support.v4.app.FragmentStatePagerAdapter}, which destroys fragments as the user navigates to other pages, minimizing memory usage.</p>
+
+<p>Below is an example of using a {@link android.support.v4.view.ViewPager} to swipe across a collection of objects.</p>
+
+<pre>
+public class CollectionDemoActivity extends FragmentActivity {
+ // When requested, this adapter returns a DemoObjectFragment,
+ // representing an object in the collection.
+ DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
+ ViewPager mViewPager;
+
+ public void onCreate(Bundle savedInstanceState) {
+ // ViewPager and its adapters use support library
+ // fragments, so use getSupportFragmentManager.
+ mDemoCollectionPagerAdapter =
+ new DemoCollectionPagerAdapter(
+ getSupportFragmentManager());
+ mViewPager = (ViewPager) findViewById(R.id.pager);
+ mViewPager.setAdapter(mDemoCollectionPagerAdapter);
+ }
+}
+
+// Since this is an object collection, use a FragmentStatePagerAdapter,
+// and NOT a FragmentPagerAdapter.
+public class DemoCollectionPagerAdapter extends
+ FragmentStatePagerAdapter {
+ public DemoCollectionPagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ {@literal @}Override
+ public Fragment getItem(int i) {
+ Fragment fragment = new DemoObjectFragment();
+ Bundle args = new Bundle();
+ // Our object is just an integer :-P
+ args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ {@literal @}Override
+ public int getCount() {
+ return 100;
+ }
+
+ {@literal @}Override
+ public CharSequence getPageTitle(int position) {
+ return "OBJECT " + (position + 1);
+ }
+}
+
+// Instances of this class are fragments representing a single
+// object in our collection.
+public static class DemoObjectFragment extends Fragment {
+ public static final String ARG_OBJECT = "object";
+
+ {@literal @}Override
+ public View onCreateView(LayoutInflater inflater,
+ ViewGroup container, Bundle savedInstanceState) {
+ // The last two arguments ensure LayoutParams are inflated
+ // properly.
+ View rootView = inflater.inflate(
+ R.layout.fragment_collection_object, container, false);
+ Bundle args = getArguments();
+ ((TextView) rootView.findViewById(android.R.id.text1)).setText(
+ Integer.toString(args.getInt(ARG_OBJECT)));
+ return rootView;
+ }
+}
+</pre>
+
+<p>You can also add indicators to your horizontal paging UI by adding a {@link android.support.v4.view.PagerTitleStrip}. Below is an example layout XML file for an activity whose entire contents are a {@link android.support.v4.view.ViewPager} and a top-aligned {@link android.support.v4.view.PagerTitleStrip} inside it. Individual pages (provided by the adapter) occupy the remaining space inside the {@link android.support.v4.view.ViewPager}.</p>
+
+<pre>
+&lt;android.support.v4.view.ViewPager
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"&gt;
+
+ &lt;android.support.v4.view.PagerTitleStrip
+ android:id="@+id/pager_title_strip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:background="#33b5e5"
+ android:textColor="#fff"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp" /&gt;
+
+&lt;/android.support.v4.view.ViewPager&gt;
+</pre>
+
+<h2 id="swipe-tabs">Implement Swiping Between Tabs</h2>
+
+<p>One of the key design recommendations in Android 4.0 for tabs is to <a href="{@docRoot}design/patterns/swipe-views.html">allow swiping</a> between them where appropriate. This behavior enables users to swipe horizontally across the selected tab's contents to navigate to adjacent tabs, without needed to directly interact with the tabs themselves. To implement this, you can use a {@link android.support.v4.view.ViewPager} in conjunction with the {@link android.app.ActionBar} tabs API.</p>
+
+<p>Upon observing the current page changing, select the corresponding tab. You can set up this behavior using an {@link android.support.v4.view.ViewPager.OnPageChangeListener} in your activity's {@link android.app.Activity#onCreate onCreate()} method:</p>
+
+<pre>
+{@literal @}Override
+public void onCreate(Bundle savedInstanceState) {
+ ...
+ mViewPager.setOnPageChangeListener(
+ new ViewPager.SimpleOnPageChangeListener() {
+ {@literal @}Override
+ public void onPageSelected(int position) {
+ // When swiping between pages, select the
+ // corresponding tab.
+ getActionBar().setSelectedNavigationItem(position);
+ }
+ });
+ ...
+}
+</pre>
+
+<p>And upon selecting a tab, switch to the corresponding page in the {@link android.support.v4.view.ViewPager}. To do this, add an {@link android.app.ActionBar.TabListener} to your tab when creating it using the {@link android.app.ActionBar#newTab newTab()} method:</p>
+
+<pre>
+actionBar.newTab()
+ ...
+ .setTabListener(new ActionBar.TabListener() {
+ public void onTabSelected(ActionBar.Tab tab,
+ FragmentTransaction ft) {
+ // When the tab is selected, switch to the
+ // corresponding page in the ViewPager.
+ mViewPager.setCurrentItem(tab.getPosition());
+ }
+ ...
+ }));
+</pre>
diff --git a/docs/html/training/implementing-navigation/temporal.jd b/docs/html/training/implementing-navigation/temporal.jd
new file mode 100644
index 0000000..f36991f
--- /dev/null
+++ b/docs/html/training/implementing-navigation/temporal.jd
@@ -0,0 +1,83 @@
+page.title=Implementing Temporal Navigation
+parent.title=Implementing Effective Navigation
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Implementing Ancestral Navigation
+previous.link=ancestral.html
+next.title=Implementing Descendant Navigation
+next.link=descendant.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to:</h2>
+<ol>
+ <li><a href="#back-fragments">Implement <em>Back</em> Navigation with Fragments</a></li>
+ <li><a href="#back-webviews">Implement <em>Back</em> Navigation with WebViews</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}training/design-navigation/ancestral-temporal.html">Providing Ancestral and Temporal Navigation</a></li>
+ <li><a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a></li>
+ <li><a href="{@docRoot}design/patterns/navigation.html">Android Design: Navigation</a></li>
+</ul>
+
+</div>
+</div>
+
+
+<p><em>Temporal navigation</em> is navigation to previously visited screens. Users can visit previous screens by pressing the device <em>Back</em> button. This user interface pattern is described further in <a href="{@docRoot}training/design-navigation/ancestral-temporal.html">Providing Ancestral and Temporal Navigation</a> in <em>Designing Effective Navigation</em> and in <a href="{@docRoot}design/patterns/navigation.html">Android Design: Navigation</a>.</p>
+
+<p>Android handles basic <em>Back</em> navigation for you (see <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a> for details on this behavior). This lesson discusses a number of cases where applications should provide specialized logic for the <em>Back</em> button.</p>
+
+
+<h2 id="back-fragments">Implement <em>Back</em> Navigation with Fragments</h2>
+
+<p>When using fragments in your application, individual {@link android.app.FragmentTransaction} objects can represent context changes that should be added to the back stack. For example, if you are implementing a <a href="descendant.html#master-detail">master/detail flow</a> on a handset by swapping out fragments (thus emulating a {@link android.app.Activity#startActivity startActivity()} call), you should ensure that pressing the <em>Back</em> button on a detail screen returns the user to the master screen. To do so, you can use {@link android.app.FragmentTransaction#addToBackStack addToBackStack()}:</p>
+
+<pre>
+// Works with either the framework FragmentManager or the
+// support package FragmentManager (getSupportFragmentManager).
+getFragmentManager().beginTransaction()
+ .add(detailFragment, "detail")
+
+ // Add this transaction to the back stack and commit.
+ .addToBackStack()
+ .commit();
+</pre>
+
+<p>The activity's {@link android.app.FragmentManager} handles <em>Back</em> button presses if there are {@link android.app.FragmentTransaction} objects on the back stack. When this happens, the {@link android.app.FragmentManager} pops the most recent transaction off the back stack and performs the reverse action (e.g., removing a fragment if the transaction added it).</p>
+
+<p>If your application updates other user interface elements to reflect the current state of your fragments, such as the action bar, remember to update the UI when you commit the transaction. You should update your user interface after the fragment manager back stack changes in addition to when you commit the transaction. You can listen for when a <code>FragmentTransaction</code> is reverted by setting up an {@link android.app.FragmentManager.OnBackStackChangedListener}:</p>
+
+<pre>
+getFragmentManager().addOnBackStackChangedListener(
+ new FragmentManager.OnBackStackChangedListener() {
+ public void onBackStackChanged() {
+ // Update your UI here.
+ }
+ });
+</pre>
+
+<h2 id="back-webviews">Implement <em>Back</em> Navigation with WebViews</h2>
+
+<p>If a part of your application is contained in a {@link android.webkit.WebView}, it may be appropriate for <em>Back</em> to traverse browser history. To do so, you can override {@link android.app.Activity#onBackPressed onBackPressed()} and proxy to the <code>WebView</code> if it has history state:</p>
+
+<pre>
+{@literal @}Override
+public void onBackPressed() {
+ if (mWebView.canGoBack()) {
+ mWebView.goBack();
+ return;
+ }
+
+ // Otherwise defer to system default behavior.
+ super.onBackPressed();
+}
+</pre>
+
+<p>Be careful when using this mechanism with highly dynamic web pages that can grow a large history. Pages that generate an extensive history, such as those that make frequent changes to the document hash, may make it tedious for users to get out of your activity.</p>
diff --git a/docs/html/training/location/locationmanager.jd b/docs/html/training/location/locationmanager.jd
index 5da1205..61abcbd 100644
--- a/docs/html/training/location/locationmanager.jd
+++ b/docs/html/training/location/locationmanager.jd
@@ -18,6 +18,7 @@ next.link=currentlocation.html
<li><a href="locationmanager.html#TaskDeclarePermissions">Declare Proper Permissions in Android Manifest</a></li>
<li><a href="locationmanager.html#TaskGetLocationManagerRef">Get a Reference to LocationManager</a></li>
<li><a href="locationmanager.html#TaskPickLocationProvider">Pick a Location Provider</a></li>
+ <li><a href="locationmanager.html#TaskVerifyProvider">Verify the Location Provider is Enabled</a></li>
</ol>
<h2>You should also read</h2>
@@ -88,3 +89,32 @@ if (providerName != null) {
...
}
</pre>
+
+<h2 id="TaskVerifyProvider">Verify the Location Provider is Enabled</h2>
+
+<p>Some location providers such as the GPS can be disabled in Settings. It is good practice to check whether the desired location provider is currently enabled by calling the {@link android.location.LocationManager#isProviderEnabled(java.lang.String) isProviderEnabled()} method. If the location provider is disabled, you can offer the user an opportunity to enable it in Settings by firing an {@link android.content.Intent} with the {@link android.provider.Settings#ACTION_LOCATION_SOURCE_SETTINGS} action.</p>
+
+<pre>
+&#64;Override
+protected void onStart() {
+ super.onStart();
+
+ // This verification should be done during onStart() because the system calls
+ // this method when the user returns to the activity, which ensures the desired
+ // location provider is enabled each time the activity resumes from the stopped state.
+ LocationManager locationManager =
+ (LocationManager) getSystemService(Context.LOCATION_SERVICE);
+ final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+
+ if (!gpsEnabled) {
+ // Build an alert dialog here that requests that the user enable
+ // the location services, then when the user clicks the "OK" button,
+ // call enableLocationSettings()
+ }
+}
+
+private void enableLocationSettings() {
+ Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ startActivity(settingsIntent);
+}
+</pre>