summaryrefslogtreecommitdiffstats
path: root/docs/html/resources/articles
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/resources/articles')
-rw-r--r--docs/html/resources/articles/avoiding-memory-leaks.jd109
-rw-r--r--docs/html/resources/articles/backward-compatibility.jd238
-rw-r--r--docs/html/resources/articles/can-i-use-this-intent.jd69
-rw-r--r--docs/html/resources/articles/creating-input-method.jd235
-rw-r--r--docs/html/resources/articles/drawable-mutations.jd91
-rw-r--r--docs/html/resources/articles/faster-screen-orientation-change.jd115
-rw-r--r--docs/html/resources/articles/future-proofing.jd89
-rw-r--r--docs/html/resources/articles/gestures.jd211
-rw-r--r--docs/html/resources/articles/glsurfaceview.jd268
-rw-r--r--docs/html/resources/articles/images/File.pngbin0 -> 14329 bytes
-rw-r--r--docs/html/resources/articles/images/File_002.pngbin0 -> 13623 bytes
-rw-r--r--docs/html/resources/articles/images/JFlubber.pngbin0 -> 8824 bytes
-rw-r--r--docs/html/resources/articles/images/WikiNotes.pngbin0 -> 58942 bytes
-rw-r--r--docs/html/resources/articles/images/all_drawables_changed.pngbin0 -> 60168 bytes
-rw-r--r--docs/html/resources/articles/images/android.pngbin0 -> 79299 bytes
-rw-r--r--docs/html/resources/articles/images/buttons.pngbin0 -> 4733 bytes
-rw-r--r--docs/html/resources/articles/images/contacts.pngbin0 -> 73617 bytes
-rw-r--r--docs/html/resources/articles/images/correct_drawables.pngbin0 -> 60746 bytes
-rw-r--r--docs/html/resources/articles/images/ddms_allocation_tracker.pngbin0 -> 83383 bytes
-rw-r--r--docs/html/resources/articles/images/ddms_allocation_trackerl.pngbin0 -> 514553 bytes
-rw-r--r--docs/html/resources/articles/images/device.pngbin0 -> 112261 bytes
-rw-r--r--docs/html/resources/articles/images/device_002.pngbin0 -> 97176 bytes
-rw-r--r--docs/html/resources/articles/images/gestures.pngbin0 -> 11254 bytes
-rw-r--r--docs/html/resources/articles/images/gestures_002.pngbin0 -> 140982 bytes
-rw-r--r--docs/html/resources/articles/images/gestures_003.pngbin0 -> 15609 bytes
-rw-r--r--docs/html/resources/articles/images/gestures_004.pngbin0 -> 15484 bytes
-rw-r--r--docs/html/resources/articles/images/gestures_005.pngbin0 -> 14652 bytes
-rw-r--r--docs/html/resources/articles/images/gestures_006.pngbin0 -> 14643 bytes
-rw-r--r--docs/html/resources/articles/images/grid.pngbin0 -> 32134 bytes
-rw-r--r--docs/html/resources/articles/images/ime.pngbin0 -> 14225 bytes
-rw-r--r--docs/html/resources/articles/images/ime_002.pngbin0 -> 14589 bytes
-rw-r--r--docs/html/resources/articles/images/ime_003.pngbin0 -> 51163 bytes
-rw-r--r--docs/html/resources/articles/images/ime_004.pngbin0 -> 10840 bytes
-rw-r--r--docs/html/resources/articles/images/ime_005.pngbin0 -> 13099 bytes
-rw-r--r--docs/html/resources/articles/images/ime_006.pngbin0 -> 14041 bytes
-rw-r--r--docs/html/resources/articles/images/layouts_comparison_small.pngbin0 -> 132330 bytes
-rw-r--r--docs/html/resources/articles/images/list01.pngbin0 -> 81747 bytes
-rw-r--r--docs/html/resources/articles/images/list02.pngbin0 -> 85815 bytes
-rw-r--r--docs/html/resources/articles/images/list_fade_1.pngbin0 -> 44890 bytes
-rw-r--r--docs/html/resources/articles/images/list_fade_2.pngbin0 -> 136484 bytes
-rw-r--r--docs/html/resources/articles/images/list_fade_3.pngbin0 -> 105257 bytes
-rw-r--r--docs/html/resources/articles/images/list_fade_4.pngbin0 -> 190068 bytes
-rw-r--r--docs/html/resources/articles/images/merge1.jpgbin0 -> 49327 bytes
-rw-r--r--docs/html/resources/articles/images/merge2.pngbin0 -> 29721 bytes
-rw-r--r--docs/html/resources/articles/images/merge3.pngbin0 -> 26044 bytes
-rw-r--r--docs/html/resources/articles/images/merge4.jpgbin0 -> 44128 bytes
-rw-r--r--docs/html/resources/articles/images/merge5.pngbin0 -> 35091 bytes
-rw-r--r--docs/html/resources/articles/images/mutated_states.pngbin0 -> 60394 bytes
-rw-r--r--docs/html/resources/articles/images/on-screen-inputs.pngbin0 -> 44392 bytes
-rw-r--r--docs/html/resources/articles/images/on-screen-inputs_002.pngbin0 -> 34148 bytes
-rw-r--r--docs/html/resources/articles/images/on-screen-inputs_003.pngbin0 -> 24749 bytes
-rw-r--r--docs/html/resources/articles/images/on-screen-inputs_004.pngbin0 -> 55736 bytes
-rw-r--r--docs/html/resources/articles/images/on-screen-inputs_005.pngbin0 -> 14092 bytes
-rw-r--r--docs/html/resources/articles/images/on-screen-inputs_006.pngbin0 -> 24405 bytes
-rw-r--r--docs/html/resources/articles/images/photostream_landscape.pngbin0 -> 104835 bytes
-rw-r--r--docs/html/resources/articles/images/photostream_portrait.pngbin0 -> 124993 bytes
-rw-r--r--docs/html/resources/articles/images/qsb.pngbin0 -> 34882 bytes
-rw-r--r--docs/html/resources/articles/images/qsb_002.pngbin0 -> 246945 bytes
-rw-r--r--docs/html/resources/articles/images/qsb_003.pngbin0 -> 43897 bytes
-rw-r--r--docs/html/resources/articles/images/relativelayout_1.pngbin0 -> 10385 bytes
-rw-r--r--docs/html/resources/articles/images/relativelayout_2.pngbin0 -> 8335 bytes
-rw-r--r--docs/html/resources/articles/images/relativelayout_3.pngbin0 -> 8394 bytes
-rw-r--r--docs/html/resources/articles/images/relativelayout_wire_1.pngbin0 -> 3554 bytes
-rw-r--r--docs/html/resources/articles/images/relativelayout_wire_2.pngbin0 -> 3553 bytes
-rw-r--r--docs/html/resources/articles/images/relativelayout_wire_3.pngbin0 -> 3543 bytes
-rw-r--r--docs/html/resources/articles/images/search01.pngbin0 -> 132998 bytes
-rw-r--r--docs/html/resources/articles/images/search02.pngbin0 -> 115605 bytes
-rw-r--r--docs/html/resources/articles/images/shared_states.pngbin0 -> 54451 bytes
-rw-r--r--docs/html/resources/articles/images/shelves2.pngbin0 -> 123418 bytes
-rw-r--r--docs/html/resources/articles/images/text_field.pngbin0 -> 63949 bytes
-rw-r--r--docs/html/resources/articles/images/ui-1.6.pngbin0 -> 14329 bytes
-rw-r--r--docs/html/resources/articles/images/ui-1.6_002.pngbin0 -> 13623 bytes
-rw-r--r--docs/html/resources/articles/images/viewstub1.pngbin0 -> 123418 bytes
-rw-r--r--docs/html/resources/articles/images/viewstub2.pngbin0 -> 112198 bytes
-rw-r--r--docs/html/resources/articles/images/viewstub3.pngbin0 -> 30279 bytes
-rw-r--r--docs/html/resources/articles/images/viewstub4.pngbin0 -> 46944 bytes
-rw-r--r--docs/html/resources/articles/images/webview.pngbin0 -> 14463 bytes
-rw-r--r--docs/html/resources/articles/images/window_background.pngbin0 -> 136846 bytes
-rw-r--r--docs/html/resources/articles/images/window_background_null.pngbin0 -> 136728 bytes
-rw-r--r--docs/html/resources/articles/images/window_background_root.pngbin0 -> 29229 bytes
-rw-r--r--docs/html/resources/articles/index.jd9
-rw-r--r--docs/html/resources/articles/layout-tricks-efficiency.jd177
-rw-r--r--docs/html/resources/articles/layout-tricks-merge.jd198
-rw-r--r--docs/html/resources/articles/layout-tricks-reuse.jd67
-rw-r--r--docs/html/resources/articles/layout-tricks-stubs.jd84
-rw-r--r--docs/html/resources/articles/listview-backgrounds.jd86
-rw-r--r--docs/html/resources/articles/live-folders.jd168
-rw-r--r--docs/html/resources/articles/on-screen-inputs.jd249
-rw-r--r--docs/html/resources/articles/painless-threading.jd147
-rw-r--r--docs/html/resources/articles/qsb.jd151
-rw-r--r--docs/html/resources/articles/timed-ui-updates.jd149
-rw-r--r--docs/html/resources/articles/touch-mode.jd138
-rw-r--r--docs/html/resources/articles/track-mem.jd62
-rw-r--r--docs/html/resources/articles/tts.jd241
-rw-r--r--docs/html/resources/articles/ui-1.5.jd48
-rw-r--r--docs/html/resources/articles/ui-1.6.jd130
-rw-r--r--docs/html/resources/articles/using-webviews.jd61
-rw-r--r--docs/html/resources/articles/wikinotes-intents.jd255
-rw-r--r--docs/html/resources/articles/wikinotes-linkify.jd113
-rw-r--r--docs/html/resources/articles/window-bg-speed.jd125
-rw-r--r--docs/html/resources/articles/zipalign.jd98
101 files changed, 4181 insertions, 0 deletions
diff --git a/docs/html/resources/articles/avoiding-memory-leaks.jd b/docs/html/resources/articles/avoiding-memory-leaks.jd
new file mode 100644
index 0000000..3361bc1
--- /dev/null
+++ b/docs/html/resources/articles/avoiding-memory-leaks.jd
@@ -0,0 +1,109 @@
+page.title=Avoiding Memory Leaks
+@jd:body
+
+
+<p>Android applications are, at least on the T-Mobile G1, limited
+to 16 MB of heap. It's both a lot of memory for a phone and yet very
+little for what some developers want to achieve. Even if you do not
+plan on using all of this memory, you should use as little as possible
+to let other applications run without getting them killed. The more
+applications Android can keep in memory, the faster it will be for the
+user to switch between his apps. As part of my job, I ran into memory
+leaks issues in Android applications and they are most of the time due
+to the same mistake: keeping a long-lived reference to a
+{@link android.content.Context Context}.</p>
+
+<p>On Android, a <code>Context</code> is used for many operations
+ but mostly to load and access resources. This is why all the widgets
+receive a <code>Context</code> parameter in their constructor. In a
+regular Android application, you usually have two kinds of
+<code>Context</code>, {@link android.app.Activity} and
+{@link android.app.Application}. It's usually the first one that
+the developer passes to classes and methods that need a <code>Context</code>:</p>
+
+<pre class="prettyprint">&#64;Override
+protected void onCreate(Bundle state) {
+ super.onCreate(state);
+
+ TextView label = new TextView(this);
+ label.setText("Leaks are bad");
+
+ setContentView(label);
+}
+</pre>
+
+<p>This means that views have a reference to the entire activity and
+therefore to anything your activity is holding onto; usually the entire
+View hierarchy and all its resources. Therefore, if you leak the <code>Context</code>
+("leak" meaning you keep a reference to it thus preventing the GC from
+collecting it), you leak a lot of memory. Leaking an entire activity
+can be really easy if you're not careful.</p>
+
+<p>When the screen orientation changes the system will, by default,
+destroy the current activity and create a new one while preserving its
+state. In doing so, Android will reload the application's UI from the
+resources. Now imagine you wrote an application with a large bitmap
+that you don't want to load on every rotation. The easiest way to keep
+it around and not having to reload it on every rotation is to keep in a
+static field:</p>
+
+<pre class="prettyprint">private static Drawable sBackground;
+
+&#64;Override
+protected void onCreate(Bundle state) {
+ super.onCreate(state);
+
+ TextView label = new TextView(this);
+ label.setText("Leaks are bad");
+
+ if (sBackground == null) {
+ sBackground = getDrawable(R.drawable.large_bitmap);
+ }
+ label.setBackgroundDrawable(sBackground);
+
+ setContentView(label);
+}
+</pre>
+
+<p>This code is very fast and also very wrong; it leaks the first activity
+created upon the first screen orientation change. When a
+{@link android.graphics.drawable.Drawable Drawable} is attached to a view, the view is set as a
+{@link android.graphics.drawable.Drawable#setCallback(android.graphics.drawable.Drawable.Callback) callback}
+on the drawable. In the code snippet above, this means the drawable has a
+reference to the <code>TextView</code> which itself has a reference to the
+activity (the <code>Context</code>) which in turns has references to
+pretty much anything (depending on your code.)</p>
+
+<p>This example is one of the simplest cases of leaking the
+<code>Context</code> and you can see how we worked around it in the
+<a href="http://android.git.kernel.org/?p=platform/packages/apps/Launcher.git;a=blob;f=src/com/android/launcher/LauncherModel.java;h=0ef2a806b767142b28b2ff3b37f21f4ca16c355d;hb=cupcake">Home screen's source code</a>
+(look for the <code>unbindDrawables()</code> method) by setting the stored
+drawables' callbacks to null when the activity is destroyed. Interestingly
+enough, there are cases where you can create a chain of leaked contexts,
+and they are bad. They make you run out of memory rather quickly.</p>
+
+<p>There are two easy ways to avoid context-related memory leaks. The most
+obvious one is to avoid escaping the context outside of its own scope. The
+example above showed the case of a static reference but inner classes and
+their implicit reference to the outer class can be equally dangerous. The
+second solution is to use the <code>Application</code> context. This
+context will live as long as your application is alive and does not depend
+on the activities life cycle. If you plan on keeping long-lived objects
+that need a context, remember the application object. You can obtain it
+easily by calling
+{@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
+or {@link android.app.Activity#getApplication() Activity.getApplication()}.</p>
+
+<p>In summary, to avoid context-related memory leaks, remember the following:</p>
+<ul>
+<li>Do not keep long-lived references to a context-activity (a reference
+to an activity should have the same life cycle as the activity itself)</li>
+<li>Try using the context-application instead of a context-activity</li>
+<li>Avoid non-static inner classes in an activity if you don't control
+their life cycle, use a static inner class and make a weak reference to
+the activity inside. The solution to this issue is to use a static inner
+class with a {@link java.lang.ref.WeakReference WeakReference} to the
+outer class, as done in <a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/ViewRoot.java;h=9d7a124cb01ab94bf53e34f6e5e8a07f81e2423c;hb=master">ViewRoot</a>
+and its W inner class for instance</li>
+<li>A garbage collector is not an insurance against memory leaks</li>
+</ul>
diff --git a/docs/html/resources/articles/backward-compatibility.jd b/docs/html/resources/articles/backward-compatibility.jd
new file mode 100644
index 0000000..9f0ddf5
--- /dev/null
+++ b/docs/html/resources/articles/backward-compatibility.jd
@@ -0,0 +1,238 @@
+page.title=Backward Compatibility for Applications
+@jd:body
+
+<p>A variety of Android-powered devices are now available to consumers from carriers
+in geographies around the world. Across those devices, a range of Android
+platform versions are in use, some running the latest version of the platform,
+others running older versions. As a developer, you need to consider the approach
+to backward compatibility that you will take in your application &mdash; do you
+want to allow your application to run on all devices, or just those running the
+latest software? In some cases it will be useful to employ the newer APIs on
+devices that support them, while continuing to support older devices. </p>
+
+<h3>Setting the minSdkVersion</h3>
+<p>If the use of a new API is integral to the application &mdash; perhaps you
+need to record video using an API introduced in Android 1.5 (API Level 3)
+&mdash; you should add a <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;android:minSdkVersion&gt;</code></a>
+ to the application's manifest, to ensure your app won't
+be installed on older devices. For example, if your application depends on an
+API introduced in API Level 3, you would specify "3" as the value of the minimum
+SDK version</a>:</p>
+
+<pre> &lt;manifest&gt;
+ ...
+ &lt;uses-sdk android:minSdkVersion="3" /&gt;
+ ...
+ &lt;/manifest&gt;</pre>
+
+<p>However, if you want to add a useful but non-essential feature, such as
+popping up an on-screen keyboard even when a hardware keyboard is available, you
+can write your program in a way that allows it to use the newer features without
+failing on older devices.</p>
+
+<h3>Using reflection</h3>
+
+<p>Suppose there's a simple new call you want to use, like {@link
+android.os.Debug#dumpHprofData(java.lang.String)
+android.os.Debug.dumpHprofData(String filename)}. The {@link android.os.Debug}
+class has existed since Android 1.0, but the method is new in Anroid 1.5 (API
+Level 3). If you try to call it directly, your app will fail to run on devices
+running Android 1.1 or earlier.</p>
+
+<p>The simplest way to call the method is through reflection. This requires
+doing a one-time lookup and caching the result in a <code>Method</code> object.
+Using the method is a matter of calling <code>Method.invoke</code> and un-boxing
+the result. Consider the following:</p>
+
+<pre>public class Reflect {
+ private static Method mDebug_dumpHprofData;
+
+ static {
+ initCompatibility();
+ };
+
+ private static void initCompatibility() {
+ try {
+ mDebug_dumpHprofData = Debug.class.getMethod(
+ "dumpHprofData", new Class[] { String.class } );
+ /* success, this is a newer device */
+ } catch (NoSuchMethodException nsme) {
+ /* failure, must be older device */
+ }
+ }
+
+ private static void dumpHprofData(String fileName) throws IOException {
+ try {
+ mDebug_dumpHprofData.invoke(null, fileName);
+ } catch (InvocationTargetException ite) {
+ /* unpack original exception when possible */
+ Throwable cause = ite.getCause();
+ if (cause instanceof IOException) {
+ throw (IOException) cause;
+ } else if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ /* unexpected checked exception; wrap and re-throw */
+ throw new RuntimeException(ite);
+ }
+ } catch (IllegalAccessException ie) {
+ System.err.println("unexpected " + ie);
+ }
+ }
+
+ public void fiddle() {
+ if (mDebug_dumpHprofData != null) {
+ /* feature is supported */
+ try {
+ dumpHprofData("/sdcard/dump.hprof");
+ } catch (IOException ie) {
+ System.err.println("dump failed!");
+ }
+ } else {
+ /* feature not supported, do something else */
+ System.out.println("dump not supported");
+ }
+ }
+}</pre>
+
+<p>This uses a static initializer to call <code>initCompatibility</code>,
+which does the method lookup. If that succeeds, it uses a private
+method with the same semantics as the original (arguments, return
+value, checked exceptions) to do the call. The return value (if it had
+one) and exception are unpacked and returned in a way that mimics the
+original. The <code>fiddle</code> method demonstrates how the
+application logic would choose to call the new API or do something
+different based on the presence of the new method.</p>
+
+<p>For each additional method you want to call, you would add an additional
+private <code>Method</code> field, field initializer, and call wrapper to the
+class.</p>
+
+<p>This approach becomes a bit more complex when the method is declared in a
+previously undefined class. It's also much slower to call
+<code>Method.invoke()</code> than it is to call the method directly. These
+issues can be mitigated by using a wrapper class.</p>
+
+<h3>Using a wrapper class</h3>
+
+<p>The idea is to create a class that wraps all of the new APIs exposed by a new
+or existing class. Each method in the wrapper class just calls through to the
+corresponding real method and returns the same result.</p>
+
+<p>If the target class and method exist, you get the same behavior you would get
+by calling the class directly, with a small amount of overhead from the
+additional method call. If the target class or method doesn't exist, the
+initialization of the wrapper class fails, and your application knows that it
+should avoid using the newer calls.</p>
+
+<p>Suppose this new class were added:</p><pre>public class NewClass {
+ private static int mDiv = 1;
+
+ private int mMult;
+
+ public static void setGlobalDiv(int div) {
+ mDiv = div;
+ }
+
+ public NewClass(int mult) {
+ mMult = mult;
+ }
+
+ public int doStuff(int val) {
+ return (val * mMult) / mDiv;
+ }
+}</pre>
+
+<p>We would create a wrapper class for it:</p>
+
+<pre>class WrapNewClass {
+ private NewClass mInstance;
+
+ /* class initialization fails when this throws an exception */
+ static {
+ try {
+ Class.forName("NewClass");
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /* calling here forces class initialization */
+ public static void checkAvailable() {}
+
+ public static void setGlobalDiv(int div) {
+ NewClass.setGlobalDiv(div);
+ }
+
+ public WrapNewClass(int mult) {
+ mInstance = new NewClass(mult);
+ }
+
+ public int doStuff(int val) {
+ return mInstance.doStuff(val);
+ }
+}</pre>
+
+<p>This has one method for each constructor and method in the original, plus a
+static initializer that tests for the presence of the new class. If the new
+class isn't available, initialization of <code>WrapNewClass</code> fails,
+ensuring that the wrapper class can't be used inadvertently. The
+<code>checkAvailable</code> method is used as a simple way to force class
+initialization. We use it like this:</p>
+
+<pre>public class MyApp {
+ private static boolean mNewClassAvailable;
+
+ /* establish whether the "new" class is available to us */
+ static {
+ try {
+ WrapNewClass.checkAvailable();
+ mNewClassAvailable = true;
+ } catch (Throwable t) {
+ mNewClassAvailable = false;
+ }
+ }
+
+ public void diddle() {
+ if (mNewClassAvailable) {
+ WrapNewClass.setGlobalDiv(4);
+ WrapNewClass wnc = new WrapNewClass(40);
+ System.out.println("newer API is available - " + wnc.doStuff(10));
+ } else {
+ System.out.println("newer API not available");
+ }
+ }
+}</pre>
+
+<p>If the call to <code>checkAvailable</code> succeeds, we know the new class is
+part of the system. If it fails, we know the class isn't there, and adjust our
+expectations accordingly. It should be noted that the call to
+<code>checkAvailable</code> will fail before it even starts if the bytecode
+verifier decides that it doesn't want to accept a class that has references to a
+nonexistent class. The way this code is structured, the end result is the same
+whether the exception comes from the verifier or from the call to
+<code>Class.forName</code>.</p>
+
+<p>When wrapping an existing class that now has new methods, you only need to
+put the new methods in the wrapper class. Invoke the old methods directly. The
+static initializer in <code>WrapNewClass</code> would be augmented to do a
+one-time check with reflection.</p>
+
+<h3>Testing is key</h3>
+
+<p>You must test your application on every version of the Android framework that
+is expected to support it. By definition, the behavior of your application will
+be different on each. Remember the mantra: if you haven't tried it, it doesn't
+work.</p>
+
+<p>You can test for backward compatibility by running your application in an
+emulator that uses an older version of the platform. The Android SDK allows you
+to do this easily by creating "Android Virtual Devices" with different API
+levels. Once you create the AVDs, you can test your application with old and new
+versions of the system, perhaps running them side-by-side to see the
+differences. More information about emulator AVDs can be found <a
+href={@docRoot}guide/developing/tools/avd.html">in the AVD documentation</a> and
+from <code>emulator -help-virtual-device</code>.</p> \ No newline at end of file
diff --git a/docs/html/resources/articles/can-i-use-this-intent.jd b/docs/html/resources/articles/can-i-use-this-intent.jd
new file mode 100644
index 0000000..a726189
--- /dev/null
+++ b/docs/html/resources/articles/can-i-use-this-intent.jd
@@ -0,0 +1,69 @@
+page.title=Can I Use this Intent?
+@jd:body
+
+<p>Android offers a very powerful and yet easy-to-use message type called
+an <a href="{@docRoot}guide/topics/intents/intents-filters.html">intents</a>.
+You can use intents to turn applications into high-level libraries and
+make code modular and reusable. The Android Home screen and AnyCut
+applications, for instance, use intents extensively to create shortcuts. </p>
+
+<p>While it is nice to be able to make use of a loosely coupled
+API, there is no guarantee that the intent you send will be received by
+another application. This happens in particular with third-party apps, like
+<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Panoramio">Panoramio</a>
+and its RADAR intent.</p>
+
+<p>This article describes a technique you can use to find out whether the system
+contains any application capable of responding to the intent you want to use.
+The example below shows a helper method that queries the system package manager
+to determine whether there's an app that can respond to a specified intent. Your
+application can pass an intent to the method and then, for example, show or hide
+user options that the user would normally use to trigger the intent. </p>
+
+<pre class="prettyprint">/**
+ * Indicates whether the specified action can be used as an intent. This
+ * method queries the package manager for installed packages that can
+ * respond to an intent with the specified action. If no suitable package is
+ * found, this method returns false.
+ *
+ * @param context The application's environment.
+ * @param action The Intent action to check for availability.
+ *
+ * @return True if an Intent with the specified action can be sent and
+ * responded to, false otherwise.
+ */
+public static boolean isIntentAvailable(Context context, String action) {
+ final PackageManager packageManager = context.getPackageManager();
+ final Intent intent = new Intent(action);
+ List&lt;ResolveInfo&gt; list =
+ packageManager.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ return list.size() &gt; 0;
+}
+</pre>
+
+<p>Here is how you could use the helper method:</p>
+
+<pre class="prettyprint">@Override
+public boolean onPrepareOptionsMenu(Menu menu) {
+ final boolean scanAvailable = isIntentAvailable(this,
+ "com.google.zxing.client.android.SCAN");
+
+ MenuItem item;
+ item = menu.findItem(R.id.menu_item_add);
+ item.setEnabled(scanAvailable);
+
+ return super.onPrepareOptionsMenu(menu);
+}
+</pre>
+
+<p>In this example, the menu is grayed out if the <em>Barcode Scanner</em>
+application is not installed. </p>
+
+<p>Another, simpler, way to do this is to catch the
+<code>ActivityNotFoundException</code> when calling <code>startActivity()</code>
+but it only lets you react to the problem, you cannot predict it and update the
+UI accordingly to prevent the user from doing something that won't work. The
+technique described here can also be used at startup time to ask the user
+whether he'd like to install the missing package, you can then simply redirect
+him to the Android Market by using the appropriate URI.</p> \ No newline at end of file
diff --git a/docs/html/resources/articles/creating-input-method.jd b/docs/html/resources/articles/creating-input-method.jd
new file mode 100644
index 0000000..5a92970
--- /dev/null
+++ b/docs/html/resources/articles/creating-input-method.jd
@@ -0,0 +1,235 @@
+page.title=Creating an Input Method
+@jd:body
+
+
+<p>To create an input method (IME) for entering text into text fields
+and other Views, you need to extend the {@link android.inputmethodservice.InputMethodService}.
+class. This class provides much of the basic implementation for an input
+method, in terms of managing the state and visibility of the input method and
+communicating with the currently visible activity.</p>
+
+<p>A good starting point would be the SoftKeyboard sample code provided as part
+of the SDK. You can modify the sample code to start building your own input
+method.</p>
+
+<p>An input method is packaged like any other application or service. In the
+<code>AndroidManifest.xml</code> file, you declare the input method as a
+service, with the appropriate intent filter and any associated meta data:</p>
+
+<pre>&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.fastinput"&gt;
+
+ &lt;application android:label="@string/app_label"&gt;<br>
+ &lt;!-- Declares the input method service --&gt;
+ &lt;service android:name="FastInputIME"
+ android:label="@string/fast_input_label"
+ android:permission="android.permission.BIND_INPUT_METHOD"&gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="android.view.InputMethod" /&gt;
+ &lt;/intent-filter&gt;
+ &lt;meta-data android:name="android.view.im" android:resource="@xml/method" /&gt;
+ &lt;/service&gt;
+
+ &lt;!-- Optional activities. A good idea to have some user settings. --&gt;
+ &lt;activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"&gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="android.intent.action.MAIN"/&gt;
+ &lt;/intent-filter&gt;
+ &lt;/activity&gt;
+ &lt;/application&gt;
+&lt;/manifest&gt;</pre>
+
+<p>If your input method allows the user to tweak some settings, you should
+provide a settings activity that can be launched from the Settings application.
+This is optional and you may choose to provide all user settings directly in
+your IME's UI.</p>
+
+<p>The typical life-cycle of an <code>InputMethodService</code> looks like
+this:</p>
+
+<p><img src="images/ime_003.png" style="border: medium none ; width: 374px; height: 871px;"></p>
+
+<h3>Visual Elements</h3>
+
+<p>There are two main visual elements for an input method—the input view and the
+candidates view. You don't have to follow this style though, if one of them is
+not relevant to your input method experience.</p>
+
+<h4>Input View</h4>
+
+<p>This is where the user can input text either in the form of keypresses,
+handwriting or other gestures. When the input method is displayed for the first
+time, <code>InputMethodService.onCreateInputView()</code> will be called. Create
+and return the view hierarchy that you would like to display in the input method
+window.</p>
+
+<h4>Candidates View</h4>
+
+<p>This is where potential word corrections or completions are presented to the
+user for selection. Again, this may or may not be relevant to your input method
+and you can return <code>null</code> from calls to
+<code>InputMethodService.onCreateCandidatesView()</code>, which is the default
+behavior.</p>
+
+<h3>Designing for the different Input Types</h3>
+
+<p>An application's text fields can have different input types specified on
+them, such as free form text, numeric, URL, email address and search. When you
+implement a new input method, you need to be aware of the different input types.
+Input methods are not automatically switched for different input types and so
+you need to support all types in your IME. However, the IME is not responsible
+for validating the input sent to the application. That's the responsibility of
+the application.</p>
+
+<p>For example, the LatinIME provided with the Android platform provides
+different layouts for text and phone number entry:</p>
+
+<p><img style="margin: 0pt 10px 0pt 0pt; width: 319px; height: 198px;" src="images/ime_002.png"><img style="width: 320px; height: 199px;" src="images/ime.png"></p>
+
+<p><code>InputMethodService.onStartInputView()</code> is called with an<code>
+EditorInfo</code> object that contains details about the input type and other
+attributes of the application's text field.</p><p>(<code>EditorInfo.inputType
+&amp; EditorInfo.TYPE_CLASS_MASK</code>) can be one of many different values,
+including:</p>
+
+<ul>
+<li><code>TYPE_CLASS_NUMBER</code></li>
+<li><code>TYPE_CLASS_DATETIME</code></li>
+<li><code>TYPE_CLASS_PHONE</code></li>
+<li><code>TYPE_CLASS_TEXT</code></li>
+</ul>
+
+<p>See <code>android.text.InputType</code> for more details.</p>
+
+<p><code>EditorInfo.inputType</code> can contain other masked bits that
+indicate the class variation and other flags. For example,
+<code>TYPE_TEXT_VARIATION_PASSWORD</code> or <code>TYPE_TEXT_VARIATION_URI</code>
+or <code>TYPE_TEXT_FLAG_AUTO_COMPLETE</code>.</p>
+
+<h4>Password fields</h4>
+
+<p>Pay
+specific attention when sending text to password fields. Make sure that
+the password is not visible within your UI &mdash; neither in the input
+view or the candidates view. Also, do not save the password anywhere without
+explicitly informing the user.</p>
+
+<h3>Landscape vs. portrait</h3>
+
+<p>The UI needs to be able to scale between landscape and portrait orientations.
+In non-fullscreen IME mode, leave sufficient space for the application to show
+the text field and any associated context. Preferably, no more than half the
+screen should be occupied by the IME. In fullscreen IME mode this is not an
+issue.</p>
+
+<h3>Sending text to the application</h3>
+
+<p>There are two ways to send text to the application. You can either send
+individual key events or you can edit the text around the cursor in the
+application's text field.</p>
+
+<p>To send a key event, you can simply construct KeyEvent objects and call
+<code>InputConnection.sendKeyEvent()</code>. Here are some examples:</p>
+
+<pre>InputConnection ic = getCurrentInputConnection();
+long eventTime = SystemClock.uptimeMillis();
+ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
+ KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
+ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+ KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));</pre>
+
+<p>Or use the convenience method:</p>
+
+<pre>InputMethodService.sendDownUpKeyEvents(keyEventCode);</pre>
+
+<p class="note"><strong>Note</strong>:
+It is recommended to use the above method for certain fields such as
+phone number fields because of filters that may be applied to the text
+after each key press. Return key and delete key should also be sent as
+raw key events for certain input types, as applications may be watching
+for specific key events in order to perform an action.</p>
+
+<p>When editing text in a text field, some of the more useful methods on
+<code>android.view.inputmethod.InputConnection</code> are:</p>
+
+<ul>
+<li><code>getTextBeforeCursor()</code></li>
+<li><code>getTextAfterCursor()</code></li>
+<li><code>deleteSurroundingText()</code></li>
+<li><code>commitText()</code></li>
+</ul>
+
+<p>For example, let's say the text "Fell" is to the left of the cursor
+and you want to replace it with "Hello!":</p>
+
+<pre>InputConnection ic = getCurrentInputConnection();
+ic.deleteSurroundingText(4, 0);
+ic.commitText("Hello", 1);
+ic.commitText("!", 1);</pre>
+
+<h4>Composing text before committing</h4>
+
+<p>If your input method does some kind of text prediction or requires multiple
+steps to compose a word or glyph, you can show the progress in the text field
+until the user commits the word and then you can replace the partial composition
+with the completed text. The text that is being composed will be highlighted in
+the text field in some fashion, such as an underline.</p>
+
+<pre>InputConnection ic = getCurrentInputConnection();
+ic.setComposingText("Composi", 1);
+...
+ic.setComposingText("Composin", 1);
+...
+ic.commitText("Composing ", 1);</pre>
+
+<p><img style="width: 320px; height: 98px; margin-bottom: 10px;" src="images/ime_006.png">
+<img style="width: 320px; height: 97px; margin-bottom: 10px;" src="images/ime_005.png">
+<img style="width: 320px; height: 97px;" src="images/ime_004.png"></p>
+
+<h3>Intercepting hard key events</h3>
+
+<p>Even though the input method window doesn't have explicit focus, it receives
+hard key events first and can choose to consume them or forward them along to
+the application. For instance, you may want to consume the directional keys to
+navigate within your UI for candidate selection during composition. Or you may
+want to trap the back key to dismiss any popups originating from the input
+method window. To intercept hard keys, override
+<code>InputMethodService.onKeyDown()</code> and
+<code>InputMethodService.onKeyUp().</code> Remember to call
+<code>super.onKey</code>* if you don't want to consume a certain key
+yourself.</p>
+
+<h3>Other considerations</h3>
+
+<ul>
+<li>Provide a way for the user to easily bring up any associated settings
+directly from the input method UI</li>
+<li>Provide
+a way for the user to switch to a different input method (multiple
+input methods may be installed) directly from the input method UI.</li>
+<li>Bring
+up the UI quickly - preload or lazy-load any large resources so that
+the user sees the input method quickly on tapping on a text field. And
+cache any resources and views for subsequent invocations of the input
+method.</li>
+<li>On the flip side, any large memory allocations should
+be released soon after the input method window is hidden so that
+applications can have sufficient memory to run. Consider using a
+delayed message to release resources if the input method is in a hidden
+state for a few seconds.</li>
+<li>Make sure that most common characters
+can be entered using the input method, as users may use punctuation in
+passwords or user names and they shouldn't be stuck in a situation
+where they can't enter a certain character in order to gain access into
+a password-locked device.</li>
+</ul>
+
+<h3>Samples</h3>
+
+<p>For a real world example, with support for multiple input types and text
+prediction, see the <a id="ccpb"
+href="http://android.git.kernel.org/?p=platform/packages/inputmethods/LatinIME.
+git;a=tree" title="LatinIME source code online">LatinIME source code</a>. The
+Android SDK also includes a SoftKeyboard sample as well.</p>
diff --git a/docs/html/resources/articles/drawable-mutations.jd b/docs/html/resources/articles/drawable-mutations.jd
new file mode 100644
index 0000000..f979829
--- /dev/null
+++ b/docs/html/resources/articles/drawable-mutations.jd
@@ -0,0 +1,91 @@
+page.title=Drawable Mutations
+@jd:body
+
+<p>Android's drawables are extremely useful to easily build applications. A
+{@link android.graphics.drawable.Drawable Drawable} is a pluggable drawing
+container that is usually associated with a View. For instance, a
+{@link android.graphics.drawable.BitmapDrawable BitmapDrawable} is used to display
+images, a {@link android.graphics.drawable.ShapeDrawable ShapeDrawable} to draw
+shapes and gradients, and so on. You can even combine them to create complex
+renderings.</p>
+
+<p>Drawables allow you to easily customize the rendering of the widgets without
+subclassing them. As a matter of fact, they are so convenient that most of the
+default Android apps and widgets are built using drawables; there are about 700
+drawables used in the core Android framework. Because drawables are used so
+extensively throughout the system, Android optimizes them when they are loaded
+from resources. For instance, every time you create a
+{@link android.widget.Button Button}, a new drawable is loaded from the framework
+resources (<code>android.R.drawable.btn_default</code>). This means all buttons
+across all the apps use a different drawable instance as their background.
+However, all these drawables share a common state, called the "constant state."
+The content of this state varies according to the type of drawable you are
+using, but it usually contains all the properties that can be defined by a
+resource. In the case of a button, the constant state contains a bitmap image.
+This way, all buttons across all applications share the same bitmap, which saves
+a lot of memory.</p>
+
+<p>The following diagram shows what entities are
+created when you assign the same image resource as the background of
+two different views. As you can see, two drawables are created but they
+both share the same constant state, hence the same bitmap:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 307px; height: 400px;" src="images/shared_states.png" alt="" id="BLOGGER_PHOTO_ID_5331437883277472082" border="0">
+
+<p>This state sharing feature is great to avoid wasting memory but it can cause
+problems when you try to modify the properties of a drawable. Imagine an
+application with a list of books. Each book has a star next to its name, totally
+opaque when the user marks the book as a favorite, and translucent when the book
+is not a favorite. To achieve this effect, you would probably write the
+following code in your list adapter's <code>getView()</code> method:</p>
+
+<pre>Book book = ...;
+TextView listItem = ...;
+
+listItem.setText(book.getTitle());
+
+Drawable star = context.getResources().getDrawable(R.drawable.star);
+if (book.isFavorite()) {
+ star.setAlpha(255); // opaque
+} else {
+ star.setAlpha(70); // translucent
+}</pre>
+
+<p>Unfortunately, this piece of code yields a rather strange result:
+all of the drawables have the same opacity:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 267px; height: 400px;" src="images/all_drawables_changed.png" alt="" id="BLOGGER_PHOTO_ID_5331438978390342066" border="0">
+
+<p>This
+result is explained by the constant state. Even though we are getting a
+new drawable instance for each list item, the constant state remains
+the same and, in the case of BitmapDrawable, the opacity is part of the
+constant state. Thus, changing the opacity of one drawable instance
+changes the opacity of all the other instances. Even worse, working
+around this issue was not easy with Android 1.0 and 1.1.</p>
+
+<p>Android 1.5 and higher offers a very easy way to solve this issue
+with the new {@link android.graphics.drawable.Drawable#mutate()} method</a>.
+When you invoke this method on a drawable, the constant state of the
+drawable is duplicated to allow you to change any property without
+affecting other drawables. Note that bitmaps are still shared, even
+after mutating a drawable. The diagram below shows what happens when
+you invoke <code>mutate()</code> on a drawable:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 307px; height: 400px;" src="images/mutated_states.png" alt="" id="BLOGGER_PHOTO_ID_5331440144116345074" border="0">
+
+<p>Let's update our previous piece of code to make use of <code>mutate()</code>:</p>
+
+<pre>Drawable star = context.getResources().getDrawable(R.drawable.star);
+if (book.isFavorite()) {
+ star.mutate().setAlpha(255); // opaque
+} else {
+ star. mutate().setAlpha(70); // translucent
+}</pre>
+
+<p>For convenience, <code>mutate()</code>
+returns the drawable itself, which allows to chain method calls. It
+does not however create a new drawable instance. With this new piece of
+code, our application now behaves correctly:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 267px; height: 400px;" src="images/correct_drawables.png" alt="" id="BLOGGER_PHOTO_ID_5331440757515573842" border="0">
diff --git a/docs/html/resources/articles/faster-screen-orientation-change.jd b/docs/html/resources/articles/faster-screen-orientation-change.jd
new file mode 100644
index 0000000..c500035
--- /dev/null
+++ b/docs/html/resources/articles/faster-screen-orientation-change.jd
@@ -0,0 +1,115 @@
+page.title=Faster Screen Orientation Change
+@jd:body
+
+<p>Android is designed to run efficiently on a wide
+array of devices, with very different hardware configurations. Some
+devices, like the T-Mobile G1, can change their hardware configuration
+at runtime. For instance, when you open the keyboard, the screen change
+from the portrait orientation to the landscape orientation.
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Using the alternate resources framework</h2>
+
+<p>The platform's support for loading orientation-specific
+resources at run time is based on the alternate resources framework.</p>
+
+<p>Providing orientation-specific resources is an important part of
+developing your app. If you are not familiar with resource directory qualifiers
+or how the platform uses them, please read
+<a href="{@docRoot}guide/topics/resources/resources-i18n.html#AlternateResources">
+Alternate Resources</a>.
+</div>
+</div>
+
+<p>To make
+Android app development easier, the Android system automatically handles
+configuration change events and restarts the current activity with the new
+configuration. This is the default behavior that lets you declare
+resources like layouts and drawables based on the orientation, screen
+size, locale, etc. </p>
+
+<p>While this behavior is really powerful, since your application adapts
+automatically to the device's configuration at runtime, it is sometimes
+confusing for new Android developers, who wonder why their activity is
+destroyed and recreated. </p>
+
+<p>Facing this "issue," some developers choose to handle configuration changes
+themselves which is, in general, a short-term solution that will only complicate
+their lives later. On the other hand, the system's automatic resource handling
+is a very efficient and easy way to adapt an application's user interface to
+various devices and devices configurations. It sometimes comes at a price,
+though.</p>
+
+<p>When your application displays a lot of data, or data that is expensive to fetch,
+the automatic destruction/creation of the activities can be lead to a
+painful user experience. Take the example of <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/">Photostream</a>,
+a simple Flickr browsing application. After you launch the application and choose a Flickr account, the
+application downloads a set of 6 photos (on a T-Mobile G1) from the
+Flickr servers and displays them on screen. To improve the user
+experience, the application uses slightly different layouts and drawables in
+portrait and landscape modes and this is what the result looks like:</p>
+
+<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9l0GmPwgCzk/SZoGyJyg6-I/AAAAAAAAACU/ItuVwhegPb8/s1600-h/photostream_landscape.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 214px;" src="images/photostream_landscape.png" alt="" id="BLOGGER_PHOTO_ID_5303558969873198050" border="0"></a></p>
+
+<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9l0GmPwgCzk/SZoGx4I-QlI/AAAAAAAAACM/-GkZR5MUKhY/s1600-h/photostream_portrait.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 214px; height: 320px;" src="images/photostream_portrait.png" alt="" id="BLOGGER_PHOTO_ID_5303558965135557202" border="0"></a></p>
+
+<p>Photostream lets Android take care of the configuration change when the
+screen is rotated. However, can you imagine how painful it would be for the user
+to see all the images being downloaded again? The obvious solution to this
+problem is to temporarily cache the images. They could be cached on the SD card
+(if there's one), in the Application object, in a static field, etc. None of
+these techniques is adapted to the current situation: why should we bother
+caching the images when the screen is not rotated? Fortunately for us, Android
+offers a great API exactly for that purpose.</p>
+
+<p>The Activity class has a special method called
+{@link android.app.Activity#onRetainNonConfigurationInstance()}. This method
+can be used to pass an arbitrary object <em>your future self</em> and Android
+is smart enough to call this method only when needed. In the case of Photostream,
+the application <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java#226">used this method</a>
+to pass the downloaded images to the future activity on orientation change.
+The implementation can be summarized like so:</p>
+
+<pre class="prettyprint">&#64;Override
+public Object onRetainNonConfigurationInstance() {
+ final LoadedPhoto[] list = new LoadedPhoto[numberOfPhotos];
+ keepPhotos(list);
+ return list;
+}
+</pre>
+
+<p>In the new activity, in <code>onCreate()</code>, all you have to do to
+get your object back is to call {@link android.app.Activity#getLastNonConfigurationInstance()}.
+In Photostream, <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java#251">this method is invoked</a>
+and if the returned value is not null, the grid is loaded with the list of
+photos from the previous activity:</p>
+
+<pre class="prettyprint">private void loadPhotos() {
+ final Object data = getLastNonConfigurationInstance();
+
+ // The activity is starting for the first time, load the photos from Flickr
+ if (data == null) {
+ mTask = new GetPhotoListTask().execute(mCurrentPage);
+ } else {
+ // The activity was destroyed/created automatically, populate the grid
+ // of photos with the images loaded by the previous activity
+ final LoadedPhoto[] photos = (LoadedPhoto[]) data;
+ for (LoadedPhoto photo : photos) {
+ addPhoto(photo);
+ }
+ }
+}
+</pre>
+
+<p>Be very careful with the object you pass through
+<code>onRetainNonConfigurationChange()</code>, though. If the object you
+pass is for some reason tied to the Activity/Context, <a
+href="http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/">you will leak</a>
+all the views and resources of the activity. This means you should
+never pass a View, a Drawable, an Adapter, etc. Photostream for
+instance extracts the bitmaps from the drawables and pass the bitmaps
+only, not the drawables. Finally, remember that
+<code>onRetainNonConfigurationChange()</code> should be used only to retain
+data that is expensive to load. Otherwise, keep it simple and let Android
+do everything.</p>
diff --git a/docs/html/resources/articles/future-proofing.jd b/docs/html/resources/articles/future-proofing.jd
new file mode 100644
index 0000000..ee98186
--- /dev/null
+++ b/docs/html/resources/articles/future-proofing.jd
@@ -0,0 +1,89 @@
+page.title=Future-Proofing Your Apps
+@jd:body
+
+<p>It's important to implement your application so that it will not break as new
+versions of the Android platform are loaded onto the users device. The list
+below is based on our observations of five ways that we've seen bad apps fail.
+You can think of these as "anti-patterns" (that is, techniques to avoid) for
+Android development.</p>
+
+<p>If your application uses any of the dubious techniques below, break out
+your IDE and duct tape, spackle, and patch up the app.</p>
+
+<p><b>Technique to Avoid, #1: Using Internal APIs</b></p>
+
+<p>Even
+though we've always strongly advised against doing so, some developers
+have chosen to use unsupported or internal APIs. For instance, many
+developers are using the internal brightness control and bluetooth
+toggle APIs that were present in 1.0 and 1.1. A bug -- which was
+fixed in Android 1.5 -- allowed apps to use those APIs without
+requesting permission. As a result, apps that used those APIs broke
+on 1.5. If you've used internal APIs in your apps, you need to update
+your apps to stop doing so. </p>
+
+<p><b>Technique to Avoid, #2: Directly Manipulating Settings</b></p>
+
+<p>Strictly speaking this one isn't evil, since this is a change in
+behavior that we made to Android itself. But we made it because some
+developers were doing naughty things: a number of apps were changing
+system settings silently without even notifying the user. For instance,
+some apps turn on GPS without asking the user, and others might turn on
+data roaming.</p>
+
+<p>As a result, applications can no longer directly
+manipulate the values of certain system Settings, even if they
+previously had permission to do so. For instance, apps can no longer
+directly turn on or off GPS. These apps won't crash, but the APIs in
+question now have no effect, and do nothing. Instead, apps will need to
+issue an Intent to launch the appropriate Settings configuration
+screen, so that the user can change these settings manually. For
+details, see the android.provider.Settings.Secure class, which you can
+find in the 1.5_pre SDK documentation (and later). Note that only
+Settings that were moved to the Settings.Secure class are affected.
+Other, less sensitive, settings will continue to have the same behavior
+as in Android 1.1.</p>
+
+<p><b>Technique to Avoid, #3: Going Overboard with Layouts</b></p>
+
+<p>Due to changes in the View rendering infrastructure, unreasonably deep
+(more than 10 or so) or broad (more than 30 total) View hierarchies in
+layouts are now likely to cause crashes. This was always a risk for
+excessively complex layouts, but you can think of Android 1.5 as being
+better than 1.1 at exposing this problem. Most developers won't need to
+worry about this, but if your app has very complicated layouts, you'll
+need to put it on a diet. You can simplify your layouts using the more
+advanced layout classes like FrameLayout and TableLayout.</p>
+
+<p><b>Technique to Avoid, #4: Bad Hardware Assumptions</b></p>
+
+<p>Android 1.5 includes support for soft keyboards, and there will soon be many
+devices that run Android but do not have physical keyboards. If your
+application assumes the presence of a physical keyboard (such as if you
+have created a custom View that sinks keypress events) you should make
+sure it degrades gracefully on devices that only have soft keyboards.
+For more information on this, keep on eye on this blog as we'll be
+posting more detailed information about handling the new soft keyboards.</p>
+
+<p><b>Technique to Avoid, #5: Incautious Rotations </b></p>
+
+<p>Devices running Android 1.5 and later can automatically rotate the screen,
+depending on how the user orients the device. Some 1.5 devices will do
+this by default, and on all others it can be turned on by the user.
+This can sometimes result in unpredictable behavior from applications
+that do their own reorientations (whether using the accelerometer, or
+something else.) This often happens when applications assume that the
+screen can only rotate if the physical keyboard is exposed; if the
+device lacks a physical keyboard, these apps do not expect to be
+reoriented, which is a coding error. Developers should be sure that
+their applications can gracefully handle being reoriented at any time.</p>
+
+<p>Also, apps that use the accelerometer directly to reorient themselves
+sometimes compete with the system doing the same thing, with odd
+results. And finally, some apps that use the accelerometer to detect
+things like shaking motions and that don't lock their orientation to
+portrait or landscape, often end up flipping back and forth between
+orientations. This can be irritating to the user. (You can lock your
+app's orientation to portrait or landscape using the
+<code>android:screenOrientation</code> attribute in the manifest file.)</p>
+
diff --git a/docs/html/resources/articles/gestures.jd b/docs/html/resources/articles/gestures.jd
new file mode 100644
index 0000000..8711645
--- /dev/null
+++ b/docs/html/resources/articles/gestures.jd
@@ -0,0 +1,211 @@
+page.title=Gestures
+@jd:body
+
+<p>Touch screens are a great way to interact with applications on
+mobile devices. With a touch screen, users can easily tap, drag, fling,
+or slide to quickly perform actions in their favorite applications.
+For app developers. the Android framework makes it's easy to
+recognize simple actions, like a swipe, but it has been more
+difficult to handle complicated gestures, sometimes requiring
+developers to write a lot of code.</p>
+
+<p>That's why we introduced a new gestures API in Android 1.6. This API, located
+in the new package {@link android.gesture}, lets you store, load, draw, and
+recognize gestures. This article will show you how you can use the
+<code>android.gesture</code> API in your applications. Before going any further,
+you should <a
+href="http://code.google.com/p/apps-for-android/downloads/detail?name=
+GesturesDemos.zip&amp;can=2&amp;q=#makechanges">download the source code
+of the examples</a>.</p>
+
+<h3>Creating a gestures library</h3>
+
+<p>Android 1.6 and higher SDK platforms include a new application pre-installed
+on the emulator, called Gestures Builder. You can use this application to create
+a set of pre-defined gestures for your own application. It also serves as an
+example of how to let the user define his own gestures in your applications. You
+can find the source code of Gestures Builders in the samples directory of each
+SDK platform. In our example we will use Gestures Builder to generate a set of
+gestures for us (make sure to create an AVD with an SD card image to use
+Gestures Builder.) The screenshot below shows what the application looks like
+after adding a few gestures:</p>
+
+<img src="images/gestures_006.png" style="width: 320px; height: 480px;">
+
+<p>As you can see, a gesture is always associated with a name. That name is very
+important because it identifies each gesture within your application. The names
+do not have to be unique. Actually it can be very useful to have several
+gestures with the same name to increase the precision of the recognition. Every
+time you add or edit a gesture in the Gestures Builder, a file is generated on
+the emulator's SD card, <code>/sdcard/gestures</code>. This file contains the
+description of all the gestures, and you will need to package it inside your
+application inside the resources directory, in
+<code>/res/raw</code>.</p>
+
+<h3>Loading the gestures library</h3>
+
+<p>Now that you have a set of pre-defined gestures, you must load it inside your
+application. This can be achieved in several ways but the easiest is to use the
+<code>GestureLibraries</code> class:</p>
+
+<pre class="prettyprint">mLibrary = GestureLibraries.fromRawResource(this, R.raw.spells);
+if (!mLibrary.load()) {
+ finish();
+}</pre>
+
+<p>In this example, the gesture library is loaded from the file
+<code>/res/raw/spells</code>. You can easily load libraries from other sources,
+like the SD card, which is very important if you want your application to be
+able to save the library; a library loaded from a raw resource is read-only and
+cannot be modified. The following diagram shows the structure of a library:</p>
+
+<img src="images/gestures_002.png" style="width: 600px; height: 512px;">
+
+<h3>Recognizing gestures</h3>
+
+<p>To start recognizing gestures in your application, all you have to do
+is add a <code>GestureOverlayView</code> to your XML layout:</p>
+
+<pre>&lt;android.gesture.GestureOverlayView
+ android:id="@+id/gestures"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0" /&gt;</pre>
+
+<p>Notice that the <code>GestureOverlayView</code>
+is not part of the usual android.widget package. Therefore, you must
+use its fully qualified name. A gesture overlay acts as a simple
+drawing board on which the user can draw his gestures. You can tweak
+several visual properties, like the color and the width of the stroke
+used to draw gestures, and register various listeners to follow what
+the user is doing. The most commonly used listener is
+<code>GestureOverlayView.OnGesturePerformedListener</code>,
+which fires whenever a user is done drawing a gesture:</p>
+
+<pre>GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
+gestures.addOnGesturePerformedListener(this);</pre>
+
+<p>When the listener fires, you can ask the <code>GestureLibrary</code>
+to try to recognize the gesture. In return, you will get a list of
+Prediction instances, each with a name - the same name you entered in
+the Gestures Builder - and a score. The list is sorted by descending
+scores; the higher the score, the more likely the associated gesture is
+the one the user intended to draw. The following code snippet
+demonstrates how to retrieve the name of the first prediction:</p>
+
+<pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+ ArrayList&lt;prediction&gt; predictions = mLibrary.recognize(gesture);
+
+ // We want at least one prediction
+ if (predictions.size() &gt; 0) {
+ Prediction prediction = predictions.get(0);
+ // We want at least some confidence in the result
+ if (prediction.score &gt; 1.0) {
+ // Show the spell
+ Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
+ }
+ }
+}</pre>
+
+<p>In this example, the first prediction is taken into account only if it's
+score is greater than 1.0. The threshold you use is entirely up to you
+but know that scores lower than 1.0 are typically poor matches. And
+this is all the code you need to create a simple application that can
+recognize pre-defined gestures (see the source code of the project
+GesturesDemo):</p>
+
+<img src="images/gestures.png" style="width: 320px; height: 480px;">
+
+<h3>Gestures overlay</h3>
+
+<p>In the example above, the <code>GestureOverlayView</code> was used
+as a normal view, embedded inside a <code>LinearLayout</code>.
+However, as its name suggests, it can also be used as an overlay on top
+of other views. This can be useful to recognize gestures in a game or
+just anywhere in the UI of an application. In the second example,
+called GesturesListDemo, we'll create an overlay on top of a list of
+contacts. We start again in Gestures Builder to create a new set of
+pre-defined gestures:</p>
+
+<p><img src="images/gestures_005.png" style="width: 320px; height: 480px;"></p>
+
+<p>And here is what the XML layout looks like:</p>
+
+<pre>&lt;android.gesture.GestureOverlayView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/gestures"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:gestureStrokeType="multiple"
+ android:eventsInterceptionEnabled="true"
+ android:orientation="vertical"&gt;
+
+ &lt;ListView
+ android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" /&gt;
+
+&lt;/android.gesture.GestureOverlayView&gt;</pre>
+
+<p>In this application, the gestures view is an overlay on top of a regular
+ListView. The overlay also specifies a few properties that we did not
+need before:</p>
+
+<ul>
+<li><code>gestureStrokeType</code>: indicates
+whether we want to recognize gestures made of a single stroke or
+multiple strokes. Since one of our gestures is the "+" symbol, we need
+multiple strokes</li>
+<li><code>eventsInterceptionEnabled</code>: when
+set to true, this property tells the overlay to steal the events from
+its children as soon as it knows the user is really drawing a gesture.
+This is useful when there's a scrollable view under the overlay, to
+avoid scrolling the underlying child as the user draws his gesture </li>
+<li><code>orientation</code>:
+indicates the scroll orientation of the views underneath. In this case
+the list scrolls vertically, which means that any horizontal gestures
+(like <code>action_delete</code>) can immediately be recognized as a
+gesture. Gestures that start with a vertical stroke must contain at
+least one horizontal component to be recognized. In other words, a
+simple vertical line cannot be recognized as a gesture since it would
+conflict with the list's scrolling.</li>
+</ul>
+
+<p>The code used to load and set up the gestures library and overlay is exactly
+the same as before. The only difference is that we now check the name of the
+predictions to know what the user intended to do:</p>
+
+<pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+ ArrayList&lt;Prediction&gt; predictions = mLibrary.recognize(gesture);
+ if (predictions.size() &gt; 0 &amp;&amp; predictions.get(0).score &gt; 1.0) {
+ String action = predictions.get(0).name;
+ if ("action_add".equals(action)) {
+ Toast.makeText(this, "Adding a contact", Toast.LENGTH_SHORT).show();
+ } else if ("action_delete".equals(action)) {
+ Toast.makeText(this, "Removing a contact", Toast.LENGTH_SHORT).show();
+ } else if ("action_refresh".equals(action)) {
+ Toast.makeText(this, "Reloading contacts", Toast.LENGTH_SHORT).show();
+ }
+ }
+}</pre>
+
+<p>The user is now able to draw his gestures on top of the list without
+interfering with the scrolling:</p>
+
+<img src="images/gestures_004.png" style="width: 320px; height: 480px;">
+
+<p>The overlay even gives visual clues as to whether the gesture is considered
+valid for recognition. In the case of a vertical overlay, for instance,
+a single vertical stroke cannot be recognized as a gesture and is
+therefore drawn with a translucent color:</p>
+
+<img src="images/gestures_003.png" style="width: 320px; height: 480px;">
+
+<h3>It's your turn</h3>
+
+<p>Adding support for gestures in your application is easy and can be a valuable
+addition. The gestures API does not even have to be used to recognize complex
+shapes; it will work equally well to recognize simple swipes. We are very
+excited by the possibilities the gestures API offers, and we're eager to see
+what cool applications the community will create with it.</p>
diff --git a/docs/html/resources/articles/glsurfaceview.jd b/docs/html/resources/articles/glsurfaceview.jd
new file mode 100644
index 0000000..57403ea
--- /dev/null
+++ b/docs/html/resources/articles/glsurfaceview.jd
@@ -0,0 +1,268 @@
+page.title=Introducing GLSurfaceView
+@jd:body
+
+
+<p>The {@link android android.opengl.GLSurfaceView} class makes it
+easier for you to use OpenGL ES rendering in your applications by:</p>
+
+<ul>
+<li>Providing the glue code to connect OpenGL ES to the {@link
+android.view.View} system.</li>
+<li>Providing the glue code to make OpenGL ES work with the {@link
+android.app.Activity} life-cycle.</li>
+<li>Making it easy to choose an appropriate frame buffer pixel format.</li>
+<li>Creating and managing a separate rendering thread, to enable smooth
+animation.</li>
+<li>Providing easy-to-use debugging tools for tracing OpenGL ES API calls and
+checking for errors.</li>
+</ul>
+
+<p>GLSurfaceView is a good base for building an application that uses OpenGL ES
+for part or all of its rendering. A 2D or 3D action game would be a good
+candidate, as would a 2D or 3D data visualization application such as <a
+href="http://www.youtube.com/watch?v=4PRfVKzuUJ4&amp;fmt=18" title="Google Maps
+StreetView">Google Maps StreetView</a>.</p>
+
+<h3>A simple GLSurfaceView application</h3>
+
+<p>Here's the source code to the simplest possible OpenGL ES application:</p>
+
+<pre>package com.example.android.apis.graphics;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+public class ClearActivity extends Activity {
+ &#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mGLView = new GLSurfaceView(this);
+ mGLView.setRenderer(new ClearRenderer());
+ setContentView(mGLView);
+ }
+
+ &#64;Override
+ protected void onPause() {
+ super.onPause();
+ mGLView.onPause();
+ }
+
+ &#64;Override
+ protected void onResume() {
+ super.onResume();
+ mGLView.onResume();
+ }
+
+ private GLSurfaceView mGLView;
+}
+
+class ClearRenderer implements GLSurfaceView.Renderer {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ // Do nothing special.
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
+ gl.glViewport(0, 0, w, h);
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ }
+}</pre>
+
+<p>This program doesn't do much: it clears the screen to black on every frame.
+But it is a complete OpenGL application that correctly implements the
+Android activity life-cycle. It pauses rendering when the activity is
+paused, and resumes it when the activity is resumed. You could use this
+application as the basis for non-interactive demonstration programs.
+Just add more OpenGL calls to the <code>ClearRenderer.onDrawFrame()</code> method.
+Notice that you don't even need to subclass the <code>GLSurfaceView</code> view.</p>
+
+<p>The {@link android.opengl.GLSurfaceView.Renderer} interface has three methods:</p>
+
+<ul>
+<li>The
+<code>onSurfaceCreated()</code> method is called at the start of rendering, and
+whenever the OpenGL ES drawing context has to be recreated. (The
+drawing context is typically lost and recreated when the activity is
+paused and resumed.) <code>OnSurfaceCreated()</code> is a good place to create
+long-lived OpenGL resources such as textures.</li>
+<li>The <code>onSurfaceChanged()</code>
+method is called when the surface changes size. It's a good place to
+set your OpenGL viewport. You may also want to set your camera here, if
+it's a fixed camera that doesn't move around the scene.</li>
+<li>The <code>onDrawFrame()</code> method is called every frame, and is
+responsible for drawing the scene. You would typically start by calling
+<code>glClear</code> to clear the framebuffer, followed by other OpenGL ES calls
+to draw the current scene.</li>
+</ul>
+
+<h3>How about user input?</h3>
+
+<p>If you want an interactive application (such as a game), you will typically
+subclass <code>GLSurfaceView</code>, because that's an easy way of obtaining
+input events. Here's a slightly longer example showing how to do that:</p>
+
+<pre>package com.google.android.ClearTest;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.MotionEvent;
+
+public class ClearActivity extends Activity {
+ &#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mGLView = new ClearGLSurfaceView(this);
+ setContentView(mGLView);
+ }
+
+ &#64;Override
+ protected void onPause() {
+ super.onPause();
+ mGLView.onPause();
+ }
+
+ &#64;Override
+ protected void onResume() {
+ super.onResume();
+ mGLView.onResume();
+ }
+
+ private GLSurfaceView mGLView;
+}
+
+class ClearGLSurfaceView extends GLSurfaceView {
+ public ClearGLSurfaceView(Context context) {
+ super(context);
+ mRenderer = new ClearRenderer();
+ setRenderer(mRenderer);
+ }
+
+ public boolean onTouchEvent(final MotionEvent event) {
+ queueEvent(new Runnable(){
+ public void run() {
+ mRenderer.setColor(event.getX() / getWidth(),
+ event.getY() / getHeight(), 1.0f);
+ }});
+ return true;
+ }
+
+ ClearRenderer mRenderer;
+}
+
+class ClearRenderer implements GLSurfaceView.Renderer {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ // Do nothing special.
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
+ gl.glViewport(0, 0, w, h);
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ }
+
+ public void setColor(float r, float g, float b) {
+ mRed = r;
+ mGreen = g;
+ mBlue = b;
+ }
+
+ private float mRed;
+ private float mGreen;
+ private float mBlue;
+}</pre>
+
+<p>This application clears the screen for every frame. When you tap on the
+screen, it sets the clear color based on the (x,y) coordinates of your touch
+event. Note the use of <code>queueEvent()</code> in
+<code>ClearGLSurfaceView.onTouchEvent()</code>. The <code>queueEvent()</code>
+method is used to safely communicate between the UI thread and the rendering
+thread. If you prefer, you can use some other Java cross-thread communication
+technique, such as synchronized methods on the <code>Renderer</code> class
+itself. However, queueing events is often the simplest way of dealing with
+cross-thread communication.</p>
+
+<h3>Other GLSurfaceView samples</h3>
+
+<p>Tired
+of just clearing the screen? You can find more interesting samples in
+the API Demos sample included in the Android SDK. All the OpenGL ES samples have been
+converted to use the <code>GLSurfaceView</code> view:</p>
+
+<ul>
+<li>GLSurfaceView - a spinning triangle</li>
+<li>Kube - a cube puzzle demo</li>
+<li>Translucent GLSurfaceView - shows how to display 3D graphics on a translucent background</li>
+<li>Textured Triangle - shows how to draw a textured 3D triangle</li>
+<li>Sprite Text - shows how to draw text into a texture and then composite it into a 3D scene</li>
+<li>Touch Rotate - shows how to rotate a 3D object in response to user input.</li>
+</ul>
+
+<h3>Choosing a surface</h3>
+
+<p><code>GLSurfaceView</code>
+helps you choose the type of surface to render to. Different Android
+devices support different types of surfaces, with no common subset.
+This makes it tricky problem to choose the best available surface on
+each device. </p>
+
+<p>By default, <code>GLSurfaceView</code> tries to find a surface that's as
+close as possible to a 16-bit RGB frame buffer with a 16-bit depth
+buffer. Depending upon your application's needs you may want to change
+this behavior. For example, the Translucent GLSurfaceView sample needs
+an Alpha channel in order to render translucent data. <code>GLSurfaceView</code>
+provides an overloaded <code>setEGLSurfaceChooser()</code> method to give
+you control over which surface type is chosen:</p>
+
+<dl>
+<dt><code>setEGLConfigChooser(boolean needDepth)</code></dt>
+<dd>Choose a config that's closest to R5G6B5 with or without a 16-bit framebuffer</dd>
+<dt><code>setEGLConfigChooser(int redSize, int greenSize,int blueSize,
+int alphaSize,int depthSize, int stencilSize)</code></dt>
+<dd>Choose the config with the fewest number of bits per pixel that has at least
+as many bits-per-channel as specified in the constructor.</dd>
+<dt><code>setEGLConfigChooser(EGLConfigChooser configChooser)</code></dt>
+<dd>Allow total control over choosing a configuration. You pass in your own
+implementation of <code>EGLConfigChooser</code>, which gets to inspect the
+device's capabilities and choose a configuration.</dd>
+</dl>
+
+<h3>Continuous rendering versus render-when-dirty</h3>
+
+<p>Most 3D applications, such as games or simulations, are continuously
+animated. But some 3D applications are more reactive: they wait passively until
+the user does something, and then react to it. For those types of applications,
+the default <code>GLSurfaceView</code> behavior of continuously redrawing the
+screen is a waste of time. If you are developing a reactive application, you can
+call <code>GLSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY)</code>, which
+turns off the continuous animation. Then you call
+<code>GLSurfaceView.requestRender()</code> whenever you want to re-render.</p>
+
+<h3>Help With debugging</h3>
+
+<p><code>GLSurfaceView</code> has a handy built-in feature for debugging OpenGL ES
+applications: the <code>GLSurfaceView.setDebugFlags()</code> method can be used
+to enable logging and/or error checking your OpenGL ES calls. Call this method
+in your <code>GLSurfaceView</code>'s constructor, before calling
+<code>setRenderer()</code>:</p>
+
+<pre>public ClearGLSurfaceView(Context context) {
+ super(context);
+ // Turn on error-checking and logging
+ setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
+ mRenderer = new ClearRenderer();
+ setRenderer(mRenderer);
+}</pre> \ No newline at end of file
diff --git a/docs/html/resources/articles/images/File.png b/docs/html/resources/articles/images/File.png
new file mode 100644
index 0000000..bc5a2b8
--- /dev/null
+++ b/docs/html/resources/articles/images/File.png
Binary files differ
diff --git a/docs/html/resources/articles/images/File_002.png b/docs/html/resources/articles/images/File_002.png
new file mode 100644
index 0000000..39254b30
--- /dev/null
+++ b/docs/html/resources/articles/images/File_002.png
Binary files differ
diff --git a/docs/html/resources/articles/images/JFlubber.png b/docs/html/resources/articles/images/JFlubber.png
new file mode 100644
index 0000000..d95e32b
--- /dev/null
+++ b/docs/html/resources/articles/images/JFlubber.png
Binary files differ
diff --git a/docs/html/resources/articles/images/WikiNotes.png b/docs/html/resources/articles/images/WikiNotes.png
new file mode 100644
index 0000000..d52c4fc
--- /dev/null
+++ b/docs/html/resources/articles/images/WikiNotes.png
Binary files differ
diff --git a/docs/html/resources/articles/images/all_drawables_changed.png b/docs/html/resources/articles/images/all_drawables_changed.png
new file mode 100644
index 0000000..04ec4a2
--- /dev/null
+++ b/docs/html/resources/articles/images/all_drawables_changed.png
Binary files differ
diff --git a/docs/html/resources/articles/images/android.png b/docs/html/resources/articles/images/android.png
new file mode 100644
index 0000000..6dc88cc
--- /dev/null
+++ b/docs/html/resources/articles/images/android.png
Binary files differ
diff --git a/docs/html/resources/articles/images/buttons.png b/docs/html/resources/articles/images/buttons.png
new file mode 100644
index 0000000..8c220b9
--- /dev/null
+++ b/docs/html/resources/articles/images/buttons.png
Binary files differ
diff --git a/docs/html/resources/articles/images/contacts.png b/docs/html/resources/articles/images/contacts.png
new file mode 100644
index 0000000..d8b067d
--- /dev/null
+++ b/docs/html/resources/articles/images/contacts.png
Binary files differ
diff --git a/docs/html/resources/articles/images/correct_drawables.png b/docs/html/resources/articles/images/correct_drawables.png
new file mode 100644
index 0000000..516309b
--- /dev/null
+++ b/docs/html/resources/articles/images/correct_drawables.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ddms_allocation_tracker.png b/docs/html/resources/articles/images/ddms_allocation_tracker.png
new file mode 100644
index 0000000..b9fa0a1
--- /dev/null
+++ b/docs/html/resources/articles/images/ddms_allocation_tracker.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ddms_allocation_trackerl.png b/docs/html/resources/articles/images/ddms_allocation_trackerl.png
new file mode 100644
index 0000000..5ac8d2a
--- /dev/null
+++ b/docs/html/resources/articles/images/ddms_allocation_trackerl.png
Binary files differ
diff --git a/docs/html/resources/articles/images/device.png b/docs/html/resources/articles/images/device.png
new file mode 100644
index 0000000..186b960
--- /dev/null
+++ b/docs/html/resources/articles/images/device.png
Binary files differ
diff --git a/docs/html/resources/articles/images/device_002.png b/docs/html/resources/articles/images/device_002.png
new file mode 100644
index 0000000..4bc3b0c
--- /dev/null
+++ b/docs/html/resources/articles/images/device_002.png
Binary files differ
diff --git a/docs/html/resources/articles/images/gestures.png b/docs/html/resources/articles/images/gestures.png
new file mode 100644
index 0000000..fe8f7cd
--- /dev/null
+++ b/docs/html/resources/articles/images/gestures.png
Binary files differ
diff --git a/docs/html/resources/articles/images/gestures_002.png b/docs/html/resources/articles/images/gestures_002.png
new file mode 100644
index 0000000..b20da98
--- /dev/null
+++ b/docs/html/resources/articles/images/gestures_002.png
Binary files differ
diff --git a/docs/html/resources/articles/images/gestures_003.png b/docs/html/resources/articles/images/gestures_003.png
new file mode 100644
index 0000000..a295939
--- /dev/null
+++ b/docs/html/resources/articles/images/gestures_003.png
Binary files differ
diff --git a/docs/html/resources/articles/images/gestures_004.png b/docs/html/resources/articles/images/gestures_004.png
new file mode 100644
index 0000000..3fe5fb1
--- /dev/null
+++ b/docs/html/resources/articles/images/gestures_004.png
Binary files differ
diff --git a/docs/html/resources/articles/images/gestures_005.png b/docs/html/resources/articles/images/gestures_005.png
new file mode 100644
index 0000000..3efc519
--- /dev/null
+++ b/docs/html/resources/articles/images/gestures_005.png
Binary files differ
diff --git a/docs/html/resources/articles/images/gestures_006.png b/docs/html/resources/articles/images/gestures_006.png
new file mode 100644
index 0000000..399c31d
--- /dev/null
+++ b/docs/html/resources/articles/images/gestures_006.png
Binary files differ
diff --git a/docs/html/resources/articles/images/grid.png b/docs/html/resources/articles/images/grid.png
new file mode 100644
index 0000000..4713de5
--- /dev/null
+++ b/docs/html/resources/articles/images/grid.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ime.png b/docs/html/resources/articles/images/ime.png
new file mode 100644
index 0000000..57f6df1
--- /dev/null
+++ b/docs/html/resources/articles/images/ime.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ime_002.png b/docs/html/resources/articles/images/ime_002.png
new file mode 100644
index 0000000..3ec00b2
--- /dev/null
+++ b/docs/html/resources/articles/images/ime_002.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ime_003.png b/docs/html/resources/articles/images/ime_003.png
new file mode 100644
index 0000000..a3f57bb
--- /dev/null
+++ b/docs/html/resources/articles/images/ime_003.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ime_004.png b/docs/html/resources/articles/images/ime_004.png
new file mode 100644
index 0000000..efeddf0
--- /dev/null
+++ b/docs/html/resources/articles/images/ime_004.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ime_005.png b/docs/html/resources/articles/images/ime_005.png
new file mode 100644
index 0000000..a7394e0
--- /dev/null
+++ b/docs/html/resources/articles/images/ime_005.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ime_006.png b/docs/html/resources/articles/images/ime_006.png
new file mode 100644
index 0000000..0b55c79
--- /dev/null
+++ b/docs/html/resources/articles/images/ime_006.png
Binary files differ
diff --git a/docs/html/resources/articles/images/layouts_comparison_small.png b/docs/html/resources/articles/images/layouts_comparison_small.png
new file mode 100644
index 0000000..0ba4cb8
--- /dev/null
+++ b/docs/html/resources/articles/images/layouts_comparison_small.png
Binary files differ
diff --git a/docs/html/resources/articles/images/list01.png b/docs/html/resources/articles/images/list01.png
new file mode 100644
index 0000000..e1b7fa8
--- /dev/null
+++ b/docs/html/resources/articles/images/list01.png
Binary files differ
diff --git a/docs/html/resources/articles/images/list02.png b/docs/html/resources/articles/images/list02.png
new file mode 100644
index 0000000..7f72a3f
--- /dev/null
+++ b/docs/html/resources/articles/images/list02.png
Binary files differ
diff --git a/docs/html/resources/articles/images/list_fade_1.png b/docs/html/resources/articles/images/list_fade_1.png
new file mode 100644
index 0000000..43013d6
--- /dev/null
+++ b/docs/html/resources/articles/images/list_fade_1.png
Binary files differ
diff --git a/docs/html/resources/articles/images/list_fade_2.png b/docs/html/resources/articles/images/list_fade_2.png
new file mode 100644
index 0000000..160d3ff
--- /dev/null
+++ b/docs/html/resources/articles/images/list_fade_2.png
Binary files differ
diff --git a/docs/html/resources/articles/images/list_fade_3.png b/docs/html/resources/articles/images/list_fade_3.png
new file mode 100644
index 0000000..70dca64
--- /dev/null
+++ b/docs/html/resources/articles/images/list_fade_3.png
Binary files differ
diff --git a/docs/html/resources/articles/images/list_fade_4.png b/docs/html/resources/articles/images/list_fade_4.png
new file mode 100644
index 0000000..7619fca
--- /dev/null
+++ b/docs/html/resources/articles/images/list_fade_4.png
Binary files differ
diff --git a/docs/html/resources/articles/images/merge1.jpg b/docs/html/resources/articles/images/merge1.jpg
new file mode 100644
index 0000000..114eed6
--- /dev/null
+++ b/docs/html/resources/articles/images/merge1.jpg
Binary files differ
diff --git a/docs/html/resources/articles/images/merge2.png b/docs/html/resources/articles/images/merge2.png
new file mode 100644
index 0000000..b4a8d4c
--- /dev/null
+++ b/docs/html/resources/articles/images/merge2.png
Binary files differ
diff --git a/docs/html/resources/articles/images/merge3.png b/docs/html/resources/articles/images/merge3.png
new file mode 100644
index 0000000..61ed983
--- /dev/null
+++ b/docs/html/resources/articles/images/merge3.png
Binary files differ
diff --git a/docs/html/resources/articles/images/merge4.jpg b/docs/html/resources/articles/images/merge4.jpg
new file mode 100644
index 0000000..17b6c20
--- /dev/null
+++ b/docs/html/resources/articles/images/merge4.jpg
Binary files differ
diff --git a/docs/html/resources/articles/images/merge5.png b/docs/html/resources/articles/images/merge5.png
new file mode 100644
index 0000000..289f47e
--- /dev/null
+++ b/docs/html/resources/articles/images/merge5.png
Binary files differ
diff --git a/docs/html/resources/articles/images/mutated_states.png b/docs/html/resources/articles/images/mutated_states.png
new file mode 100644
index 0000000..50518b6
--- /dev/null
+++ b/docs/html/resources/articles/images/mutated_states.png
Binary files differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs.png b/docs/html/resources/articles/images/on-screen-inputs.png
new file mode 100644
index 0000000..b8b3cf7
--- /dev/null
+++ b/docs/html/resources/articles/images/on-screen-inputs.png
Binary files differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_002.png b/docs/html/resources/articles/images/on-screen-inputs_002.png
new file mode 100644
index 0000000..a5d21c7
--- /dev/null
+++ b/docs/html/resources/articles/images/on-screen-inputs_002.png
Binary files differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_003.png b/docs/html/resources/articles/images/on-screen-inputs_003.png
new file mode 100644
index 0000000..81ee257
--- /dev/null
+++ b/docs/html/resources/articles/images/on-screen-inputs_003.png
Binary files differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_004.png b/docs/html/resources/articles/images/on-screen-inputs_004.png
new file mode 100644
index 0000000..651b72a
--- /dev/null
+++ b/docs/html/resources/articles/images/on-screen-inputs_004.png
Binary files differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_005.png b/docs/html/resources/articles/images/on-screen-inputs_005.png
new file mode 100644
index 0000000..75185ff
--- /dev/null
+++ b/docs/html/resources/articles/images/on-screen-inputs_005.png
Binary files differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_006.png b/docs/html/resources/articles/images/on-screen-inputs_006.png
new file mode 100644
index 0000000..b653d75
--- /dev/null
+++ b/docs/html/resources/articles/images/on-screen-inputs_006.png
Binary files differ
diff --git a/docs/html/resources/articles/images/photostream_landscape.png b/docs/html/resources/articles/images/photostream_landscape.png
new file mode 100644
index 0000000..ad4a0c5
--- /dev/null
+++ b/docs/html/resources/articles/images/photostream_landscape.png
Binary files differ
diff --git a/docs/html/resources/articles/images/photostream_portrait.png b/docs/html/resources/articles/images/photostream_portrait.png
new file mode 100644
index 0000000..3794f63
--- /dev/null
+++ b/docs/html/resources/articles/images/photostream_portrait.png
Binary files differ
diff --git a/docs/html/resources/articles/images/qsb.png b/docs/html/resources/articles/images/qsb.png
new file mode 100644
index 0000000..4e40af1
--- /dev/null
+++ b/docs/html/resources/articles/images/qsb.png
Binary files differ
diff --git a/docs/html/resources/articles/images/qsb_002.png b/docs/html/resources/articles/images/qsb_002.png
new file mode 100644
index 0000000..8c2f772
--- /dev/null
+++ b/docs/html/resources/articles/images/qsb_002.png
Binary files differ
diff --git a/docs/html/resources/articles/images/qsb_003.png b/docs/html/resources/articles/images/qsb_003.png
new file mode 100644
index 0000000..069b6cd
--- /dev/null
+++ b/docs/html/resources/articles/images/qsb_003.png
Binary files differ
diff --git a/docs/html/resources/articles/images/relativelayout_1.png b/docs/html/resources/articles/images/relativelayout_1.png
new file mode 100644
index 0000000..3360ad8
--- /dev/null
+++ b/docs/html/resources/articles/images/relativelayout_1.png
Binary files differ
diff --git a/docs/html/resources/articles/images/relativelayout_2.png b/docs/html/resources/articles/images/relativelayout_2.png
new file mode 100644
index 0000000..8e71bb2
--- /dev/null
+++ b/docs/html/resources/articles/images/relativelayout_2.png
Binary files differ
diff --git a/docs/html/resources/articles/images/relativelayout_3.png b/docs/html/resources/articles/images/relativelayout_3.png
new file mode 100644
index 0000000..16a9767
--- /dev/null
+++ b/docs/html/resources/articles/images/relativelayout_3.png
Binary files differ
diff --git a/docs/html/resources/articles/images/relativelayout_wire_1.png b/docs/html/resources/articles/images/relativelayout_wire_1.png
new file mode 100644
index 0000000..9cb241d
--- /dev/null
+++ b/docs/html/resources/articles/images/relativelayout_wire_1.png
Binary files differ
diff --git a/docs/html/resources/articles/images/relativelayout_wire_2.png b/docs/html/resources/articles/images/relativelayout_wire_2.png
new file mode 100644
index 0000000..4243812
--- /dev/null
+++ b/docs/html/resources/articles/images/relativelayout_wire_2.png
Binary files differ
diff --git a/docs/html/resources/articles/images/relativelayout_wire_3.png b/docs/html/resources/articles/images/relativelayout_wire_3.png
new file mode 100644
index 0000000..04ce1ce
--- /dev/null
+++ b/docs/html/resources/articles/images/relativelayout_wire_3.png
Binary files differ
diff --git a/docs/html/resources/articles/images/search01.png b/docs/html/resources/articles/images/search01.png
new file mode 100644
index 0000000..4160a76
--- /dev/null
+++ b/docs/html/resources/articles/images/search01.png
Binary files differ
diff --git a/docs/html/resources/articles/images/search02.png b/docs/html/resources/articles/images/search02.png
new file mode 100644
index 0000000..6300018
--- /dev/null
+++ b/docs/html/resources/articles/images/search02.png
Binary files differ
diff --git a/docs/html/resources/articles/images/shared_states.png b/docs/html/resources/articles/images/shared_states.png
new file mode 100644
index 0000000..81bec09
--- /dev/null
+++ b/docs/html/resources/articles/images/shared_states.png
Binary files differ
diff --git a/docs/html/resources/articles/images/shelves2.png b/docs/html/resources/articles/images/shelves2.png
new file mode 100644
index 0000000..2de239f
--- /dev/null
+++ b/docs/html/resources/articles/images/shelves2.png
Binary files differ
diff --git a/docs/html/resources/articles/images/text_field.png b/docs/html/resources/articles/images/text_field.png
new file mode 100644
index 0000000..b9dedec
--- /dev/null
+++ b/docs/html/resources/articles/images/text_field.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ui-1.6.png b/docs/html/resources/articles/images/ui-1.6.png
new file mode 100644
index 0000000..bc5a2b8
--- /dev/null
+++ b/docs/html/resources/articles/images/ui-1.6.png
Binary files differ
diff --git a/docs/html/resources/articles/images/ui-1.6_002.png b/docs/html/resources/articles/images/ui-1.6_002.png
new file mode 100644
index 0000000..39254b30
--- /dev/null
+++ b/docs/html/resources/articles/images/ui-1.6_002.png
Binary files differ
diff --git a/docs/html/resources/articles/images/viewstub1.png b/docs/html/resources/articles/images/viewstub1.png
new file mode 100644
index 0000000..2de239f
--- /dev/null
+++ b/docs/html/resources/articles/images/viewstub1.png
Binary files differ
diff --git a/docs/html/resources/articles/images/viewstub2.png b/docs/html/resources/articles/images/viewstub2.png
new file mode 100644
index 0000000..6e6feb9
--- /dev/null
+++ b/docs/html/resources/articles/images/viewstub2.png
Binary files differ
diff --git a/docs/html/resources/articles/images/viewstub3.png b/docs/html/resources/articles/images/viewstub3.png
new file mode 100644
index 0000000..5e793e6
--- /dev/null
+++ b/docs/html/resources/articles/images/viewstub3.png
Binary files differ
diff --git a/docs/html/resources/articles/images/viewstub4.png b/docs/html/resources/articles/images/viewstub4.png
new file mode 100644
index 0000000..cffb9c6
--- /dev/null
+++ b/docs/html/resources/articles/images/viewstub4.png
Binary files differ
diff --git a/docs/html/resources/articles/images/webview.png b/docs/html/resources/articles/images/webview.png
new file mode 100644
index 0000000..92472af
--- /dev/null
+++ b/docs/html/resources/articles/images/webview.png
Binary files differ
diff --git a/docs/html/resources/articles/images/window_background.png b/docs/html/resources/articles/images/window_background.png
new file mode 100644
index 0000000..58f4f7e
--- /dev/null
+++ b/docs/html/resources/articles/images/window_background.png
Binary files differ
diff --git a/docs/html/resources/articles/images/window_background_null.png b/docs/html/resources/articles/images/window_background_null.png
new file mode 100644
index 0000000..83f7b45
--- /dev/null
+++ b/docs/html/resources/articles/images/window_background_null.png
Binary files differ
diff --git a/docs/html/resources/articles/images/window_background_root.png b/docs/html/resources/articles/images/window_background_root.png
new file mode 100644
index 0000000..95a47c0
--- /dev/null
+++ b/docs/html/resources/articles/images/window_background_root.png
Binary files differ
diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd
new file mode 100644
index 0000000..3080453
--- /dev/null
+++ b/docs/html/resources/articles/index.jd
@@ -0,0 +1,9 @@
+page.title=Technical Articles
+@jd:body
+
+
+<dl>
+ <dt><a href="{@docRoot}resources/articles/tts.html">Using Text-to-Speech</a></dt>
+ <dd>The text-to-speech API lets your application "speak" to users, in any of several languages. This article provides an overview of the TTS API and how you use to add speech capabilities to your application.</dd>
+</dl>
+
diff --git a/docs/html/resources/articles/layout-tricks-efficiency.jd b/docs/html/resources/articles/layout-tricks-efficiency.jd
new file mode 100644
index 0000000..b7b5761
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-efficiency.jd
@@ -0,0 +1,177 @@
+page.title=Layout Tricks: Creating Efficient Layouts
+@jd:body
+
+<p>The Android UI toolkit offers several layout managers that are
+rather easy to use and, most of the time, you only need the basic
+features of these layout managers to implement a user interface.</p>
+
+<p>Sticking to the basic features is unfortunately not the most efficient
+way to create user interfaces. A common example is the abuse of
+{@link android.widget.LinearLayout}, which leads to a proliferation of
+views in the view hierarchy. Every view &mdash; or worse, every layout
+manager &mdash; that you add to your application comes at a cost:
+initialization, layout and drawing become slower. The layout pass can be
+especially expensive when you nest several <code>LinearLayout</code>
+that use the {@link android.R.attr#layout_weight weight}
+parameter, which requires the child to be measured twice.</p>
+
+<p>Let's consider a very simple and common example of a layout: a list item
+with an icon on the left, a title at the top and an optional description
+underneath the title. Here is what such an item looks like:</p>
+
+<div style="text-align: center;"><img src="images/relativelayout_1.png" alt="Simple list item"></div>
+
+<p>To clearly understand how the views, one {@link android.widget.ImageView} and
+two {@link android.widget.TextView}, are positioned with respect to each other,
+here is the wireframe of the layout as captured by <a
+href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a
+>:</p>
+
+<div style="text-align: center;"><img src="images/relativelayout_wire_1.png" alt="Wireframe of the simple list item"></div>
+
+<p>Implementing this layout is straightforward with <code>LinearLayout</code>.
+The item itself is a horizontal <code>LinearLayout</code> with an
+<code>ImageView</code> and a vertical <code>LinearLayout</code>, which contains
+the two <code>TextView</code>. Here's the source code of this layout:</p>
+
+<pre class="prettyprint">&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+
+ android:padding="6dip"&gt;
+
+ &lt;ImageView
+ android:id="&#64;+id/icon"
+
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_marginRight="6dip"
+
+ android:src="&#64;drawable/icon" /&gt;
+
+ &lt;LinearLayout
+ android:orientation="vertical"
+
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:layout_height="fill_parent"&gt;
+
+ &lt;TextView
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+
+ android:gravity="center_vertical"
+ android:text="My Application" /&gt;
+
+ &lt;TextView
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:text="Simple application that shows how to use RelativeLayout" /&gt;
+
+ &lt;/LinearLayout&gt;
+
+&lt;/LinearLayout&gt;</pre>
+
+<p>This layout works but can be wasteful if you instantiate it for every list
+item of a {@link android.widget.ListView}. The same layout can be rewritten
+using a single {@link android.widget.RelativeLayout}, thus saving one view, and
+even better one level in view hierarchy, per list item. The implementation of
+the layout with a <code>RelativeLayout</code> remains simple:</p>
+
+<pre class="prettyprint">&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+
+ android:padding="6dip"&gt;
+
+ &lt;ImageView
+ android:id="&#64;+id/icon"
+
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+
+ android:layout_alignParentTop="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginRight="6dip"
+
+ android:src="&#64;drawable/icon" /&gt;
+
+ &lt;TextView
+ android:id="&#64;+id/secondLine"
+
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:layout_toRightOf="&#64;id/icon"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:text="Simple application that shows how to use RelativeLayout" /&gt;
+
+ &lt;TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+
+ android:layout_toRightOf="&#64;id/icon"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_above="&#64;id/secondLine"
+ android:layout_alignWithParentIfMissing="true"
+
+ android:gravity="center_vertical"
+ android:text="My Application" /&gt;
+
+&lt;/RelativeLayout&gt;</pre>
+
+<p>This new implementation behaves exactly the same way as the previous
+implementation, except in one case. The list item we want to display has two
+lines of text: the title and an <em>optional</em> description. When a
+description is not available for a given list item, the application would simply
+set the visibility of the second <code>TextView</code> to
+{@link android.view.View#GONE}. This works perfectly with the <code>LinearLayout</code>
+implementation but not with the <code>RelativeLayout</code> version:</p>
+
+<div style="text-align: center;"><img src="images/relativelayout_2.png" alt="RelativeLayout and description GONE"></div>
+<div style="text-align: center;"><img src="images/relativelayout_wire_2.png" alt="RelativeLayout and description GONE"></div>
+
+<p>In a <code>RelativeLayout</code>, views are aligned with their parent, with the
+<code>RelativeLayout</code> itself, or with other views. For instance, we declared that
+the description is aligned with the bottom of the <code>RelativeLayout</code> and
+that the title is positioned above the description and anchored to the
+parent's top. With the description GONE, RelativeLayout doesn't know
+where to position the title's bottom edge. To solve this problem, you
+can use a very special layout parameter called
+{@link android.R.attr#layout_alignWithParentIfMissing}.
+</p>
+
+<p>This boolean parameter simply tells RelativeLayout to use its own edges as
+anchors when a constraint target is missing. For instance, if you position a
+view to the right of a GONE view and set <code>alignWithParentIfMissing</code>
+to <code>true</code>, <code>RelativeLayout</code> will instead anchor the view
+to its left edge. In our case, using <code>alignWithParentIfMissing</code> will
+cause <code>RelativeLayout</code> to align the title's bottom with its own
+bottom. The result is the following:</p>
+
+<div style="text-align: center;"><img src="images/relativelayout_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing"></div>
+<div style="text-align: center;"><img src="images/relativelayout_wire_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing"></div>
+
+<p>The
+behavior of our layout is now perfect, even when the description is
+GONE. Even better, the hierarchy is simpler and because we are not
+using LinearLayout's weights it's also more efficient. The difference
+between the two implementations becomes obvious when comparing the view
+hierarchies in HierarchyViewer:</p>
+
+<div style="text-align: center;"><img src="images/layouts_comparison_small.png" alt="LinearLayout vs RelativeLayout"></div>
+
+<p>Again, the difference will be much more important when you use such a layout
+for every item in a ListView for instance. Hopefully this simple
+example showed you that getting to know your layouts is the best way to
+learn how to optimize your UI.</p>
diff --git a/docs/html/resources/articles/layout-tricks-merge.jd b/docs/html/resources/articles/layout-tricks-merge.jd
new file mode 100644
index 0000000..3e165d2
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-merge.jd
@@ -0,0 +1,198 @@
+page.title=Layout Tricks: Merging Layouts
+@jd:body
+
+<p>The <a href=""></a> articles showed you how to use the <code>&lt;include /&gt;</code> tag in XML layouts, to reuse and share your layout code. This article explains the <code>&lt;merge /&gt;</code> tag and how it complements the <code>&lt;include /&gt;</code> tag.</p>
+
+<p>The <code>&lt;merge /&gt;</code> tag was created for the purpose of
+optimizing Android layouts by reducing the number of levels in view trees. It's
+easier to understand the problem this tag solves by looking at an example. The
+following XML layout declares a layout that shows an image with its title on top
+of it. The structure is fairly simple; a {@link android.widget.FrameLayout} is
+used to stack a {@link android.widget.TextView} on top of an
+{@link android.widget.ImageView}:</p>
+
+<pre class="prettyprint">&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"&gt;
+
+ &lt;ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:scaleType="center"
+ android:src="&#64;drawable/golden_gate" /&gt;
+
+ &lt;TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="20dip"
+ android:layout_gravity="center_horizontal|bottom"
+
+ android:padding="12dip"
+
+ android:background="#AA000000"
+ android:textColor="#ffffffff"
+
+ android:text="Golden Gate" /&gt;
+
+&lt;/FrameLayout&gt;</pre>
+
+<p>This layout renders nicely and nothing seems wrong with it:</p>
+
+<div style="text-align: center;"><img src="images/merge1.jpg" alt="A FrameLayout is used to overlay a title on top of an image"></div>
+
+<p>Things get more interesting when you inspect the result with <a
+href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a>.
+If you look closely at the resulting tree, you will notice that the
+<code>FrameLayout</code> defined in our XML file (highlighted in blue below) is
+the sole child of another <code>FrameLayout</code>:</p>
+
+<div style="text-align: center;"><img src="images/merge2.png" alt="A layout with only one child of same dimensions can be removed"></div>
+
+<p>Since our <code>FrameLayout</code> has the same dimension as its parent, by
+the virtue of using the <code>fill_parent</code> constraints, and does not
+define any background, extra padding or a gravity, it is <em>totally
+useless</em>. We only made the UI more complex for no good reason. But how could
+we get rid of this <code>FrameLayout</code>? After all, XML documents require a
+root tag and tags in XML layouts always represent view instances.</p>
+
+<p>That's where the <code>&lt;merge /&gt;</code> tag comes in handy. When the
+{@link android.view.LayoutInflater} encounters this tag, it skips it and adds
+the <code>&lt;merge /&gt;</code> children to the <code>&lt;merge /&gt;</code>
+parent. Confused? Let's rewrite our previous XML layout by replacing the
+<code>FrameLayout</code> with <code>&lt;merge /&gt;</code>:</p>
+
+<pre class="prettyprint">&lt;merge xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+
+ &lt;ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:scaleType="center"
+ android:src="&#64;drawable/golden_gate" /&gt;
+
+ &lt;TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="20dip"
+ android:layout_gravity="center_horizontal|bottom"
+
+ android:padding="12dip"
+
+ android:background="#AA000000"
+ android:textColor="#ffffffff"
+
+ android:text="Golden Gate" /&gt;
+
+&lt;/merge&gt;</pre>
+
+<p>With this new version, both the <code>TextView</code> and the
+<code>ImageView</code> will be added directly to the top-level
+<code>FrameLayout</code>. The result will be visually the same but the view
+hierarchy is simpler:</p>
+
+<div style="text-align: center;"><img src="images/merge3.png" alt="Optimized view hierarchy using the merge tag"></div>
+
+<p>Obviously, using <code>&lt;merge /&gt;</code> works in this case because the
+parent of an activity's content view is always a <code>FrameLayout</code>. You
+could not apply this trick if your layout was using a <code>LinearLayout</code>
+as its root tag for instance. The <code>&lt;merge /&gt;</code> can be useful in
+other situations though. For instance, it works perfectly when combined with the
+<code>&lt;include /&gt;</code> tag. You can also use <code>&lt;merge
+/&gt;</code> when you create a custom composite view. Let's see how we can use
+this tag to create a new view called <code>OkCancelBar</code> which simply shows
+two buttons with customizable labels. You can also <a
+href="http://progx.org/users/Gfx/android/MergeLayout.zip">download the complete
+source code of this example</a>. Here is the XML used to display this custom
+view on top of an image:</p>
+
+<pre class="prettyprint">&lt;merge
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge"&gt;
+
+ &lt;ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:scaleType="center"
+ android:src="&#64;drawable/golden_gate" /&gt;
+
+ &lt;com.example.android.merge.OkCancelBar
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+
+ android:paddingTop="8dip"
+ android:gravity="center_horizontal"
+
+ android:background="#AA000000"
+
+ okCancelBar:okLabel="Save"
+ okCancelBar:cancelLabel="Don't save" /&gt;
+
+&lt;/merge&gt;</pre>
+
+<p>This new layout produces the following result on a device:</p>
+
+<div style="text-align: center;"><img src="images/merge4.jpg" alt="Creating a custom view with the merge tag"></div>
+
+<p>The source code of <code>OkCancelBar</code> is very simple because the two
+buttons are defined in an external XML file, loaded using a
+<code>LayoutInflate</code>. As you can see in the following snippet, the XML
+layout <code>R.layout.okcancelbar</code> is inflated with the
+<code>OkCancelBar</code> as the parent:</p>
+
+<pre class="prettyprint">public class OkCancelBar extends LinearLayout {
+ public OkCancelBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOrientation(HORIZONTAL);
+ setGravity(Gravity.CENTER);
+ setWeightSum(1.0f);
+
+ LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true);
+
+ TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0);
+
+ String text = array.getString(R.styleable.OkCancelBar_okLabel);
+ if (text == null) text = "Ok";
+ ((Button) findViewById(R.id.okcancelbar_ok)).setText(text);
+
+ text = array.getString(R.styleable.OkCancelBar_cancelLabel);
+ if (text == null) text = "Cancel";
+ ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text);
+
+ array.recycle();
+ }
+}</pre>
+
+<p>The two buttons are defined in the following XML layout. As you can see, we
+use the <code>&lt;merge /&gt;</code> tag to add the two buttons directly to the
+<code>OkCancelBar</code>. Each button is included from the same external XML
+layout file to make them easier to maintain; we simply override their id:</p>
+
+<pre class="prettyprint">&lt;merge xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+ &lt;include
+ layout="&#64;layout/okcancelbar_button"
+ android:id="&#64;+id/okcancelbar_ok" /&gt;
+
+ &lt;include
+ layout="&#64;layout/okcancelbar_button"
+ android:id="&#64;+id/okcancelbar_cancel" /&gt;
+&lt;/merge&gt;</pre>
+
+<p>We have created a flexible and easy to maintain custom view that generates
+an efficient view hierarchy:</p>
+
+<div style="text-align: center;"><img src="images/merge5.png" alt="The resulting hierarchy is simple and efficient"></div>
+
+<p>The <code>&lt;merge /&gt;</code> tag is extremely useful and can do wonders
+in your code. However, it suffers from a couple of limitations:</p>
+
+<ul>
+<li><code>&lt;merge /&gt;</code> can only be used as the root tag of an XML layout</li>
+<li>When inflating a layout starting with a <code>&lt;merge /&gt;</code>, you <strong>must</strong>
+specify a parent <code>ViewGroup</code> and you must set <code>attachToRoot</code> to
+<code>true</code> (see the documentation for
+{@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} method)</li>
+</ul>
+
diff --git a/docs/html/resources/articles/layout-tricks-reuse.jd b/docs/html/resources/articles/layout-tricks-reuse.jd
new file mode 100644
index 0000000..072ba89
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-reuse.jd
@@ -0,0 +1,67 @@
+page.title=Layout Tricks: Creating Reusable UI Components
+@jd:body
+
+<p>The Android platform offers a wide variety of UI <em>widgets</em>, small
+visual construction blocks that you can glue together to present users with
+complex and useful interfaces. However applications often need higher-level
+visual <em>components</em>. To meet that need, and to do so efficiently, you can
+combine multiple standard widgets into a single, reusable component. </p>
+
+<p>For example, you could create a reusable component that contains a progress
+bar and a cancel button, a panel containing two buttons (positive and negative
+actions), a panel with an icon, a title and a description, and so on. You can
+create UI components easily by writing a custom <code>View</code>, but you can
+do it even more easily using only XML.</p>
+
+<p>In Android XML layout files, each tag is mapped to an actual class instance
+(the class is always a subclass of {@link android.view.View} The UI toolkit lets
+you also use three special tags that are not mapped to a <code>View</code>
+instance: <code>&lt;requestFocus /&gt;</code>, <code>&lt;merge /&gt;</code> and
+<code>&lt;include /&gt;</code>. This article shows how to use <code>&lt;include
+/&gt;</code> to create pure XML visual components. For information about how to
+use <code>&lt;merge /&gt;</code>, which can be particularly powerful when
+combined with <code>&lt;include /&gt;</code>see the <a
+href="{@docRoot}resources/articles/layout-tricks-merge.html">Merging Layouts</a>
+article. </p>
+
+<p>The <code>&lt;include /&gt;</code> element does exactly what its name
+suggests; it includes another XML layout. Using this tag is straightforward as
+shown in the following example, taken straight from <a
+href="http://android.git.kernel.org/?p=platform/packages/apps/Launcher.git;a=
+tree;h=refs/heads/master;hb=master">the source code of the Home application</a>
+that ships with Android:</p>
+
+<pre class="prettyprint">&lt;com.android.launcher.Workspace
+ android:id="&#64;+id/workspace"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ launcher:defaultScreen="1"&gt;
+
+ &lt;include android:id="&#64;+id/cell1" layout="@layout/workspace_screen" /&gt;
+ &lt;include android:id="&#64;+id/cell2" layout="@layout/workspace_screen" /&gt;
+ &lt;include android:id="&#64;+id/cell3" layout="@layout/workspace_screen" /&gt;
+
+&lt;/com.android.launcher.Workspace&gt;</pre>
+
+<p>In the <code>&lt;include /&gt;</code> only the <code>layout</code> attribute
+is required. This attribute, without the <code>android</code> namespace prefix,
+is a reference to the layout file you wish to include. In this example, the same
+layout is included three times in a row. This tag also lets you override a few
+attributes of the included layout. The above example shows that you can use
+<code>android:id</code> to specify the id of the root view of the included
+layout; it will also override the id of the included layout if one is defined.
+Similarly, you can override all the layout parameters. This means that any
+<code>android:layout_*</code> attribute can be used with the <code>&lt;include
+/&gt;</code> tag. Here is an example:</p>
+
+<pre class="prettyprint">&lt;include android:layout_width="fill_parent" layout="@layout/image_holder" /&gt;
+&lt;include android:layout_width="256dip" layout="@layout/image_holder" /&gt;
+</pre>
+
+<p>This tag is particularly useful when you need to customize only part of your
+UI depending on the device's configuration. For instance, the main layout of
+your activity can be placed in the <code>layout/</code> directory and can
+include another layout which exists in two flavors, in <code>layout-land/</code>
+and <code>layout-port/</code>. This allows you to share most of the UI in
+portrait and landscape.</p> \ No newline at end of file
diff --git a/docs/html/resources/articles/layout-tricks-stubs.jd b/docs/html/resources/articles/layout-tricks-stubs.jd
new file mode 100644
index 0000000..e494a54
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-stubs.jd
@@ -0,0 +1,84 @@
+page.title=Layout Tricks: Using ViewStubs
+@jd:body
+
+<p>Sharing and reusing UI components is very easy with Android, thanks to the <a
+href="layout-tricks-include.html">&lt;include /&gt;</a> tag. Sometimes it's so
+easy to create complex UI constructs that your UI ends up with a large number of
+views, some of which are rarely used. Thankfully, Android offers a very special
+widget called {@link android.view.ViewStub}, which brings you all the benefits
+of the <code>&lt;include /&gt;</code> without polluting your user interface with
+rarely used views.</p>
+
+<p>A <code>ViewStub</code> is a dumb and lightweight view. It has no dimension,
+it does not draw anything and does not participate in the layout in any way.
+This means that a <code>ViewStub</code> is very cheap to inflate and very cheap
+to keep in a view hierarchy. A <code>ViewStub</code> can be best described as a
+<em>lazy include</em>. The layout referenced by a <code>ViewStub</code> is
+inflated and added to the user interface only when you decide so.</p>
+
+<p>The following screenshot comes from the <a
+href="http://code.google/p/shelves">Shelves</a> application. The main purpose of
+the activity shown in the screenshot is to present the user with a browsable
+list of books:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center;" src="images/viewstub1.png" alt="" id="BLOGGER_PHOTO_ID_5314039375336055346" border="0">
+
+<p>The same activity is also used when the user adds or imports new books.
+During such an operation, Shelves shows extra bits of user interface.
+The screenshot below shows the progress bar and cancel button that
+appear at the bottom of the screen during an import:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center;" src="images/viewstub2.png" alt="" id="BLOGGER_PHOTO_ID_5314039800002559378" border="0">
+
+<p>Because importing books is not a common operation, at least when compared to
+browsing the list of books, the import panel is originally represented
+by a <code>ViewStub</code>:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center;" src="images/viewstub3.png" alt="" id="BLOGGER_PHOTO_ID_5314040334008167378" border="0">
+
+<p>When the user initiates the import process, the <code>ViewStub</code> is
+inflated and replaced by the content of the layout file it references:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center;" src="images/viewstub4.png" alt="" id="BLOGGER_PHOTO_ID_5314040638747834450" border="0">
+
+<p>To use a <code>ViewStub</code>, all you need is to specify an
+<code>android:id</code> attribute, to later inflate the stub, and an
+<code>android:layout</code> attribute, to reference what layout file
+to include and inflate. A stub lets you use a third attribute,
+<code>android:inflatedId</code>, which can be used to override the
+<code>id</code> of the root of the included file. Finally, the layout
+parameters specified on the stub will be applied to the roof of the
+included layout. Here is an example:</p>
+
+<pre class="prettyprint">&lt;ViewStub
+ android:id="&#64;+id/stub_import"
+ android:inflatedId="&#64;+id/panel_import"
+
+ android:layout="&#64;layout/progress_overlay"
+
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom" /&gt;</pre>
+
+<p>When you are ready to inflate the stub, simply invoke the
+{@link android.view.ViewStub#inflate()} method. You can also simply change the
+visibility of the stub to {@link android.view.View#VISIBLE} or
+{@link android.view.View#INVISIBLE} and the stub will inflate. Note however that the
+<code>inflate()</code> method has the benefit of returning the root
+<code>View</code> of the inflate layout:</p>
+
+<pre class="prettyprint">((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
+// or
+View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();</pre>
+
+<p>It is very important to remember that after the stub is inflated, the stub is
+<em>removed</em> from the view hierarchy. As such, it is unnecessary to keep a
+long-lived reference, for instance in an class instance field, to a
+<code>ViewStub</code>.</p>
+
+<p>A <code>ViewStub</code> is a great compromise between ease of programming and
+efficiency. Instead of inflating views manually and adding them at runtime to
+your view hierarchy, simply use a <code>ViewStub</code>. It's cheap and easy.
+The only drawback of <code>ViewStub</code> is that it currently does
+<em>not</em> support the <a href="layout-tricks-merge.html">&lt;merge /&gt;
+tag</a>.</p>
diff --git a/docs/html/resources/articles/listview-backgrounds.jd b/docs/html/resources/articles/listview-backgrounds.jd
new file mode 100644
index 0000000..f4c6998
--- /dev/null
+++ b/docs/html/resources/articles/listview-backgrounds.jd
@@ -0,0 +1,86 @@
+page.title=ListView Backgrounds: An Optimization
+@jd:body
+
+<p>{@link android.widget.ListView} is one of Android's most widely used widgets.
+It is rather easy to use, very flexible, and incredibly powerful.
+<code>ListView</code> can also be difficult to understand at times.</p>
+
+<p>One of the most common issues with <code>ListView</code> happens when you try
+to use a custom background. By default, like many Android widgets,
+<code>ListView</code> has a transparent background which means that you can see
+through the default window's background, a very dark gray
+(<code>#FF191919</code> with the current <code>dark</code> theme.) Additionally,
+<code>ListView</code> enables the <em>fading edges</em> by default, as you can
+see at the top of the following screenshot &mdash; the first text item gradually
+fades to black. This technique is used throughout the system to indicate that
+the container can be scrolled.</p>
+
+<div style="text-align: center;"><img src="images/list_fade_1.png" alt="Android's default ListView"></div>
+
+<p>The fade effect is implemented using a combination of
+{@link android.graphics.Canvas#saveLayerAlpha(float, float, float, float, int, int) Canvas.saveLayerAlpha()}
+and the {@link android.graphics.PorterDuff.Mode#DST_OUT Porter-Duff Destination Out blending mode}. </p>
+
+<p>Unfortunately, things start to get ugly when you try to use a custom
+background on the <code>ListView</code> or when you change the window's
+background. The following two screenshots show what happens in an application
+when you change the window's background. The left image shows what the list
+looks like by default and the right image shows what the list looks like during
+a scroll initiated with a touch gesture:</p>
+
+<div style="text-align: center;">
+<img style="margin-right: 12px;" src="images/list_fade_2.png" alt="Dark fade">
+<img src="images/list_fade_3.png" alt="Dark list"></div>
+
+<p>This rendering issue is caused by an optimization of the Android framework
+enabled by default on all instances of <code>ListView</code>. I mentioned
+earlier that the fade effect is implemented using a Porter-Duff blending mode.
+This implementation works really well but is unfortunately very costly and can
+bring down drawing performance by quite a bit as it requires to capture a
+portion of the rendering in an offscreen bitmap and then requires extra blending
+(which implies readbacks from memory.)</p>
+
+<p>Since <code>ListView</code> is most of the time displayed on a solid
+background, there is no reason to go down that expensive route. That's why we
+introduced an optimization called the "cache color hint." The cache color hint
+is an RGB color set by default to the window's background color, that is #191919
+in Android's dark theme. When this hint is set, <code>ListView</code> (actually,
+its base class <code>View</code>) knows it will draw on a solid background and
+therefore replaces th expensive <code>saveLayerAlpha()/Porter-Duff</code>
+rendering with a simple gradient. This gradient goes from fully transparent to
+the cache color hint value and this is exactly what you see on the image above,
+with the dark gradient at the bottom of the list. However, this still does not
+explain why the entire list turns black during a scroll.</p>
+
+<p>As mentioned before, <code>ListView</code> has a transparent/translucent
+background by default, and so all default widgets in the Android UI toolkit.
+This implies that when <code>ListView</code> redraws its children, it has to
+blend the children with the window's background. Once again, this requires
+costly readbacks from memory that are particularly painful during a scroll or a
+fling when drawing happens dozen of times per second. </p>
+
+<p>To improve drawing performance during scrolling operations, the Android
+framework reuses the cache color hint. When this hint is set, the framework
+copies each child of the list in a <code>Bitmap</code> filled with the hint
+value (assuming that another optimization, called <em>scrolling cache</em>, is
+not turned off). <code>ListView</code> then blits these bitmaps directly on
+screen and because these bitmaps are known to be opaque, no blending is
+required. Also, since the default cache color hint is <code>#191919</code>, you
+get a dark background behind each item during a scroll.</p>
+
+<p>To fix this issue, all you have to do is either disable the cache color hint
+optimization, if you use a non-solid color background, or set the hint to the
+appropriate solid color value. You can do this from code (see
+{@link android.widget.AbsListView#setCacheColorHint(int)}) or preferably from
+XML, by using the <code>android:cacheColorHint</code> attribute. To disable the
+optimization, simply use the transparent color <code>#00000000</code>. The
+following screenshot shows a list with
+<code>android:cacheColorHint="#00000000"</code> set in the XML layout file:</p>
+
+<div style="text-align: center;"><img src="images/list_fade_4.png" alt="Fade on a custom background"></div>
+
+<p>As you can see, the fade works perfectly against the custom wooden
+background. The cache color hint feature is interesting because it
+shows how optimizations can make your life more difficult in
+some situations. In this particular case, however, the benefit of the
+default behavior outweighs the added complexity..</p>
diff --git a/docs/html/resources/articles/live-folders.jd b/docs/html/resources/articles/live-folders.jd
new file mode 100644
index 0000000..be974f4
--- /dev/null
+++ b/docs/html/resources/articles/live-folders.jd
@@ -0,0 +1,168 @@
+page.title=Live Folders
+@jd:body
+
+<p>Live folders, introduced in Android 1.5 (API Level 3), let you display any source of data
+on the Home screen without forcing the user to launch an application. A live
+folder is simply a real-time view of a {@link android.content.ContentProvider}.
+As such, a live folder can be used to display all of the user's contacts or
+bookmarks, email, playlists, an RSS feed, and so on. The possibilities are
+endless! </p>
+
+<p>The platform includes several standard folders for displaying contacts. For
+instance, the screenshot below shows the content of the live folders that
+displays all contacts with a phone number:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 267px; height: 400px;" src="images/contacts.png" alt="" id="BLOGGER_PHOTO_ID_5323287788220889218" border="0">
+
+<p>If a contacts sync happens in the background while the user is browsing this live
+folder, the user will see the change happen in real-time. Live folders are not
+only useful, but they are also easy to add to to your application and data.
+
+This articles shows how to add a live folder to an example application called
+Shelves. To better understand how live folders work, you can <a
+href="http://code.google.com/p/shelves">download the source code of the
+application</a> and modify it by following the instructions below.</p>
+
+<p>To give the user the option to create a new live folder for an application,
+you first need to create a new activity with an intent filter whose action is
+<code>android.intent.action.CREATE_LIVE_FOLDER</code>. To do so, simply open
+<code>AndroidManifest.xml</code> and add something similar to this:</p>
+
+<pre>&lt;activity
+ android:name=".activity.BookShelfLiveFolder"
+ android:label="BookShelf"&gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="android.intent.action.CREATE_LIVE_FOLDER" /&gt;
+ &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+ &lt;/intent-filter&gt;
+&lt;/activity&gt;</pre>
+
+<p>The label and icon of this activity are what the user will see on the Home
+screen when choosing a live folder to create:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 267px; height: 400px;" src="images/device_002.png" alt="" id="BLOGGER_PHOTO_ID_5323289217773103922" border="0">
+
+<p>Since you just need an intent filter, it is possible, and sometimes advised,
+to reuse an existing activity. In the case of Shelves, we will create a new
+activity, <code>org.curiouscreature.android.shelves.activity.BookShelfLiveFolder</code>.
+The role of this activity is to send an <code>Intent</code> result to Home
+containing the description of the live folder: its name, icon, display mode and
+content URI. The content URI is very important as it describes what
+<code>ContentProvider</code> will be used to populate the live folder. The code
+of the activity is very simple as you can see here:</p>
+
+<pre>public class BookShelfLiveFolder extends Activity {
+ public static final Uri CONTENT_URI = Uri.parse("content://shelves/live_folders/books");
+
+ &#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Intent intent = getIntent();
+ final String action = intent.getAction();
+
+ if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
+ setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
+ "Books", R.drawable.ic_live_folder));
+ } else {
+ setResult(RESULT_CANCELED);
+ }
+
+ finish();
+ }
+
+ private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) {
+ final Intent intent = new Intent();
+
+ intent.setData(uri);
+ intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
+ intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
+ Intent.ShortcutIconResource.fromContext(context, icon));
+ intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);
+
+ return intent;
+ }
+}</pre>
+
+<p>This activity, when invoked with the<code>ACTION_CREATE_LIVE_FOLDER</code>
+intent, returns an intent with a URI,
+<code>content://shelves/live_folders/books</code>, and three extras to describe
+the live folder. There are other extras and constants you can use and you should
+refer to the documentation of <code>android.provider.LiveFolders</code> for more
+details. When Home receives this intent, a new live folder is created on the
+user's desktop, with the name and icon you provided. Then, when the user clicks
+on the live folder to open it, Home queries the content provider referenced by
+the provided URI.</p>
+
+<p>Live folders' content providers must obey specific naming rules. The
+<code>Cursor</code> returned by the <code>query()</code> method must have at
+least two columns named <code>LiveFolders._ID</code> and
+<code>LiveFolders.NAME</code>. The first one is the unique identifier of each
+item in the live folder and the second one is the name of the item. There are
+other column names you can use to specify an icon, a description, the intent to
+associate with the item (fired when the user clicks that item), etc. Again,
+refer to the documentation of <code>android.provider.LiveFolders</code> for more
+details.</p><p>In our example, all we need to do is modify the existing provider
+in Shelves called
+<code>org.curiouscreature.android.shelves.provider.BooksProvider</code>. First,
+we need to modify the <code>URI_MATCHER</code> to recognize our
+<code>content://shelves/live_folders/books</code> content URI:</p>
+
+<pre>private static final int LIVE_FOLDER_BOOKS = 4;
+// ...
+URI_MATCHER.addURI(AUTHORITY, "live_folders/books", LIVE_FOLDER_BOOKS);</pre>
+
+<p>Then we need to create a new projection map for the cursor. A projection map
+can be used to "rename" columns. In our case, we will replace
+<code>BooksStore.Book._ID</code>, <code>BooksStore.Book.TITLE</code> and
+<code>BooksStore.Book.AUTHORS</code> with <code>LiveFolders._ID</code>,
+<code>LiveFolders.TITLE</code> and <code>LiveFolders.DESCRIPTION</code>:</p>
+
+<pre>private static final HashMap&lt;string, string=""&gt; LIVE_FOLDER_PROJECTION_MAP;
+static {
+ LIVE_FOLDER_PROJECTION_MAP = new HashMap&lt;string, string=""&gt;();
+ LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders._ID, BooksStore.Book._ID +
+ " AS " + LiveFolders._ID);
+ LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.NAME, BooksStore.Book.TITLE +
+ " AS " + LiveFolders.NAME);
+ LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.DESCRIPTION, BooksStore.Book.AUTHORS +
+ " AS " + LiveFolders.DESCRIPTION);
+}</pre>
+
+<p>Because we are providing a title and a description for each row, Home will
+automatically display each item of the live folder with two lines of text.
+Finally, we implement the <code>query()</code> method by supplying our
+projection map to the SQL query builder:</p>
+
+<pre>public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+ switch (URI_MATCHER.match(uri)) {
+ // ...
+ case LIVE_FOLDER_BOOKS:
+ qb.setTables("books");
+ qb.setProjectionMap(LIVE_FOLDER_PROJECTION_MAP);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, BooksStore.Book.DEFAULT_SORT_ORDER);
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+
+ return c;
+}</pre>
+
+<p>You can now compile and deploy the application, go to the Home screen and
+try to add a live folder. You can add a books live folder to your Home screen
+and when you open it, see the list of all of your books, with their
+titles and authors, and all it took was a few lines of code:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 267px; height: 400px;" src="images/device.png" alt="" id="BLOGGER_PHOTO_ID_5323293545495859234" border="0"></p>
+
+<p>The live folders API is extremely simple and relies only on intents and
+content URI. If you want to see more examples of live folders
+implementation, you can read the source code of the <a href="http://android.git.kernel.org/?p=platform/packages/apps/Contacts.git;a=tree;h=refs/heads/cupcake;hb=cupcake">Contacts application</a> and of the <a href="http://android.git.kernel.org/?p=platform/packages/providers/ContactsProvider.git;a=tree;h=refs/heads/cupcake;hb=cupcake">Contacts provider</a>.</p><p>You can also download the result of our exercise, the <a href="http://jext.free.fr/CupcakeShelves.zip">modified version of Shelves with live folders support</a>.</p> \ No newline at end of file
diff --git a/docs/html/resources/articles/on-screen-inputs.jd b/docs/html/resources/articles/on-screen-inputs.jd
new file mode 100644
index 0000000..057325a
--- /dev/null
+++ b/docs/html/resources/articles/on-screen-inputs.jd
@@ -0,0 +1,249 @@
+page.title=Onscreen Input Methods
+@jd:body
+
+
+<p>Starting from Android 1.5, the Android platform offers an Input Method
+Framework (IMF) that lets you create on-screen input methods such as software
+keyboards. This article provide an overview of what Android input method editors
+(IMEs) are and what an application needs to do to work well with them. The IMF
+is designed to support new classes of Android devices, such as those without
+hardware keyboards, so it is important that your application works well with the
+IMF and offers a great experience for users.</p>
+
+<h3>What is an input method?</h3>
+
+<p>The Android IMF is designed to support a variety of IMEs, including soft
+keyboard, hand-writing recognizers, and hard keyboard translators. Our focus,
+however, will be on soft keyboards, since this is the kind of input method that
+is currently part of the platform.</p>
+
+<p>A user will usually access the current IME by tapping on a text view to
+edit, as shown here in the home screen:</p>
+
+<img style="width: 320px; height: 480px; margin-right: 10px;" src="images/on-screen-inputs_004.png">
+<img style="width: 320px; height: 480px;" src="images/on-screen-inputs.png">
+
+<p>The soft keyboard is positioned at the bottom of the screen over the
+application's window. To organize the available space between the application
+and IME, we use a few approaches; the one shown here is called <em>pan and
+scan</em>, and simply involves scrolling the application window around so that
+the currently focused view is visible. This is the default mode, since it is the
+safest for existing applications.</p>
+
+<p>Most often the preferred screen layout is a <em>resize</em>, where the
+application's window is resized to be entirely visible. An example is shown
+here, when composing an e-mail message:</p>
+
+<img style="width: 320px; height: 480px; margin-right: 10px;" src="images/on-screen-inputs_005.png">
+<img style="width: 320px; height: 480px;" src="images/on-screen-inputs_003.png">
+
+<p>The size of the application window is changed so that none of it is hidden by
+the IME, allowing full access to both the application and IME. This of course
+only works for applications that have a resizeable area that can be reduced to
+make enough space, but the vertical space in this mode is actually no less than
+what is available in landscape orientation, so very often an application can
+already accommodate it.</p>
+
+<p>The final major mode is <em>fullscreen</em> or <em>extract</em>
+mode. This is used when the IME is too large to reasonably share space
+with the underlying application. With the standard IMEs, you will only
+encounter this situation when the screen is in a landscape orientation,
+although other IMEs are free to use it whenever they desire. In this
+case the application window is left as-is, and the IME simply displays
+fullscreen on top of it, as shown here:</p>
+
+<img style="width: 480px; height: 320px; margin-right: 10px; margin-bottom: 10px;" src="images/on-screen-inputs_006.png">
+<img style="width: 480px; height: 320px;" src="images/on-screen-inputs_002.png">
+
+<p>Because the IME is covering the application, it has its own editing area,
+which shows the text actually contained in the application. There are also some
+limited opportunities the application has to customize parts of the IME (the
+"done" button at the top and enter key label at the bottom) to improve the user
+experience.</p>
+
+<h3>Basic XML attributes for controlling IMEs</h3>
+
+<p>There are a number of things the system does to try to help existing
+applications work with IMEs as well as possible, such as:</p>
+
+<ul>
+<li>Use pan and scan mode by default, unless it can reasonably guess that
+resize mode will work by the existence of lists, scroll views, etc.</li>
+<li>Analyze the various existing TextView attributes to guess at the kind of
+content (numbers, plain text, etc) to help the soft keyboard display an
+appropriate key layout.</li>
+<li>Assign a few default actions to the fullscreen IME, such as "next field"
+and "done".</li>
+</ul>
+
+<p>There are also some simple things you can do in your application that will
+often greatly improve its user experience. Except where explicitly mentioned,
+these will work in any Android platform version, even those previous to Android
+1.5 (since they will simply ignore these new options).</p>
+
+<h4>Specifying each EditText control's input type</h4>
+
+<p>The most important thing for an application to do is to use the new
+<code>android:inputType</code>
+attribute on each <code>EditText</code>. The attribute provides much richer
+information
+about the text content. This attribute actually replaces many existing
+attributes (<code>android:</code><code>password</code>,
+<code>android:</code><code>singleLine</code>,
+<code>android:</code><code>numeric</code>,
+<code>android:</code><code>phoneNumber</code>,
+<code>android:</code><code>capitalize</code>,
+<code>android:</code><code>autoText</code>, and
+<code>android:</code><code>editable</code>). If you specify the older attributes
+and the new <code>android:inputType</code> attribute, the system uses
+<code>android:inputType</code> and ignores the others. </p>
+
+<p>The <code>android:inputType</code> attribute has three pieces:</p>
+
+<ul>
+<li>The <em>class</em> is the overall interpretation of characters. The
+currently supported classes are <code>text</code> (plain text),
+<code>number</code> (decimal number), <code>phone</code> (phone number), and
+<code>datetime</code> (a date or time).</li>
+<li>The <em>variation</em> is a further refinement on the class. In the
+attribute you will normally specify the class and variant together, with the
+class as a prefix. For example, <code>textEmailAddress</code> is a text field
+where the user will enter something that is an e-mail address (foo@bar.com) so
+the key layout will have an '@' character in easy access, and
+<code>numberSigned</code> is a numeric field with a sign. If only the class is
+specified, then you get the default/generic variant.</li>
+<li>Additional <em>flags</em> can be specified that supply further refinement.
+These flags are specific to a class. For example, some flags for the
+<code>text</code> class are <code>textCapSentences</code>,
+<code>textAutoCorrect</code>, and <code>textMultiline</code>.</li>
+</ul>
+
+<p>As an example, here is the new EditText for the IM application's message text view:</p>
+
+<pre> &lt;EditText android:id="@+id/edtInput"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine"
+ android:imeOptions="actionSend|flagNoEnterAction"
+ android:maxLines="4"
+ android:maxLength="2000"
+ android:hint="@string/compose_hint"/&gt;</pre>
+
+<p>A full description of all of the input types can be found in the
+documentation. It is important to make use of the correct input types that are
+available, so that the soft keyboard can use the optimal keyboard layout for the
+text the user will be entering.</p>
+
+<h4>Enabling resize mode and other window features</h4>
+
+<p>The second most important thing for your app to do is to specify the overall
+behavior of your window in relation to the input method. The most visible aspect
+of this is controlling resize vs. pan and scan mode, but there are other things
+you can do as well to improve your user experience.</p>
+
+<p>You will usually control this behavior through the
+<code>android:windowSoftInputMode</code> attribute on each
+<code>&lt;activity&gt;</code> definition in your
+<code>AndroidManifest.xml</code>. Like the input type, there are a couple
+different pieces of data that can be specified here by combining them
+together:</p>
+
+<ul>
+<li>The window adjustment mode is specified with either
+<code>adjustResize</code> or <code>adjustPan</code>. It is highly recommended
+that you always specify one or the other.</li>
+<li>You can further control whether the IME will be shown automatically when
+your activity is displayed and other situations where the user moves to it. The
+system won't automatically show an IME by default, but in some cases it can be
+convenient for the user if an application enables this behavior. You can request
+this with <code>stateVisible</code>. There are also a number of other state
+options for finer-grained control that you can find in the documentation.</li>
+</ul>
+
+<p>A typical example of this field can be see in the edit contact activity,
+which ensures it is resized and automatically displays the IME for the user:</p>
+
+<pre> &lt;activity name="EditContactActivity"
+ android:windowSoftInputMode="stateVisible|adjustResize"&gt;
+ ...
+ &lt;/activity&gt;</pre>
+
+<p class="note"><strong>Note:</strong>Starting from Android 1.5 (API Level 3),
+the platform offers a new method,
+{@link android.view.Window#setSoftInputMode(int mode)},
+that non-Activity windows can use to control their behavior. Calling this method
+in your will make your application incompatible with previous versions of the
+Android platform.</p>
+
+<h4>Controlling the action buttons</h4>
+
+<p>The final customization we will look at is the "action" buttons in the IME.
+There are currently two types of actions:</p>
+
+<ul>
+<li>The enter key on a soft keyboard is typically bound to an action when not
+operating on a mult-line edit text. For example, on the G1 pressing the hard
+enter key will typically move to the next field or the application will
+intercept it to execute an action; with a soft keyboard, this overloading of the
+enter key remains, since the enter button just sends an enter key event.</li>
+<li>When in fullscreen mode, an IME may also put an additional action button to
+the right of the text being edited, giving the user quick access to a common
+application operation.</li>
+</ul>
+
+<p>These options are controlled with the <code>android:imeOptions</code>
+attribute on <code>TextView</code>. The value you supply here can be any
+combination of:</p>
+
+<ul>
+<li>One of the pre-defined action constants (<code>actionGo</code>,
+<code>actionSearch</code>, <code>actionSend</code>, <code>actionNext</code>,
+<code>actionDone</code>). If none of these are specified, the system will infer
+either <code>actionNext</code> or <code>actionDone</code> depending on whether
+there is a focusable field after this one; you can explicitly force no action
+with <code>actionNone</code>.</li>
+<li>The <code>flagNoEnterAction</code> option tells the IME that the action
+should <em>not</em> be available on the enter key, even if the text itself is
+not multi-line. This avoids having unrecoverable actions like (send) that can be
+accidentally touched by the user while typing.</li>
+<li>The <code>flagNoAccessoryAction</code> removes the action button from the
+text area, leaving more room for text.</li><li>The <code>flagNoExtractUi</code>
+completely removes the text area, allowing the application to be seen behind
+it.</li>
+</ul>
+
+<p>The previous IM application message view also provides an example of an
+interesting use of <code>imeOptions</code>, to specify the send action but not
+let it be shown on the enter key:</p>
+
+<pre>android:imeOptions="actionSend|flagNoEnterAction"</pre>
+
+<h3>APIs for controlling IMEs</h3>
+
+<p>For more advanced control over the IME, there are a variety of new APIs you
+can use. Unless special care is taken (such as by using reflection), using these
+APIs will cause your application to be incompatible with previous versions of
+Android, and you should make sure you specify
+<code>android:minSdkVersion="3"</code> in your manifest. For more information,
+see the documentation for the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a
+> manifest element.</p>
+
+<p>The primary API is the new <code>android.view.inputmethod.InputMethodManager</code> class, which you can retrieve with <code>Context.getSystemService()</code>.
+It allows you to interact with the global input method state, such as
+explicitly hiding or showing the current IME's input area.</p>
+
+<p>There are also new window flags controlling input method interaction, which you can control through the existing <code>Window.addFlags()</code> method and new <code>Window.setSoftInputMode()</code> method. The <code>PopupWindow</code>
+class has grown corresponding methods to control these options on its
+window. One thing in particular to be aware of is the new <code>WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM</code> constant, which is used to control whether a window is on top of or behind the current IME.</p>
+
+<p>Most of the interaction between an active IME and application is done through the <code>android.view.inputmethod.InputConnection</code>
+class. This is the API an application implement, which an IME calls to
+perform the appropriate edit operations on the application. You won't
+normally need to worry about this, since <code>TextView</code> provides its own implementation for itself.</p>
+
+<p>There are also a handful of new <code>View</code> APIs, the most important of these being<code> onCreateInputConnection()</code> which creates a new <code>InputConnection</code> for an IME (and fills in an <code>android.view.inputmethod.EditorInfo</code>
+structure with your input type, IME options, and other data); again,
+most developers won't need to worry about this, since TextView takes
+care of it for you.</p> \ No newline at end of file
diff --git a/docs/html/resources/articles/painless-threading.jd b/docs/html/resources/articles/painless-threading.jd
new file mode 100644
index 0000000..921f4df
--- /dev/null
+++ b/docs/html/resources/articles/painless-threading.jd
@@ -0,0 +1,147 @@
+page.title=Painless Threading
+@jd:body
+
+<p>This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads. </p>
+
+<h3>The UI thread</h3>
+
+<p>When an application is launched, the system creates a thread called
+"main" for the application. The main thread, also called the <em>UI
+thread</em>, is very important because it is in charge of dispatching the
+events to the appropriate widgets, including drawing events.
+It is also the thread where your application interacts with running
+components of the Android UI toolkit. </p>
+
+<p>For instance, if you touch the a button on screen, the UI thread dispatches
+the touch event to the widget, which in turn sets its pressed state and
+posts an invalidate request to the event queue. The UI thread dequeues
+the request and notifies the widget to redraw itself.</p>
+
+<p>This single-thread model can yield poor performance unless your application
+is implemented properly. Specifically, if everything is happening in a single
+thread, performing long operations such as network access or database
+queries on the UI thread will block the whole user interface. No event
+can be dispatched, including drawing events, while the long operation
+is underway. From the user's perspective, the application appears hung.
+Even worse, if the UI thread is blocked for more than a few seconds
+(about 5 seconds currently) the user is presented with the infamous "<a href="http://developer.android.com/guide/practices/design/responsiveness.html">application not responding</a>" (ANR) dialog.</p>
+
+<p>If you want to see how bad this can look, write a simple application
+with a button that invokes <code>Thread.sleep(2000)</code> in its
+<a href="http://developer.android.com/reference/android/view/View.OnClickListener.html">OnClickListener</a>.
+The button will remain in its pressed state for about 2 seconds before
+going back to its normal state. When this happens, it is very easy for
+the user to <em>perceive</em> the application as slow.</p>
+
+<p>To summarize, it's vital to the responsiveness of your application's UI to
+keep the UI thread unblocked. If you have long operations to perform, you should
+make sure to do them in extra threads (<em>background</em> or <em>worker</em>
+threads). </p>
+
+<p>Here's an example of a click listener downloading an image over the
+network and displaying it in an <a href="http://developer.android.com/reference/android/widget/ImageView.html">ImageView</a>:</p>
+
+<pre class="prettyprint">public void onClick(View v) {
+ new Thread(new Runnable() {
+ public void run() {
+ Bitmap b = loadImageFromNetwork();
+ mImageView.setImageBitmap(b);
+ }
+ }).start();
+}</pre>
+
+<p>At first, this code seems to be a good solution to your problem, as it does
+not block the UI thread. Unfortunately, it violates the single-threaded model
+for the UI: the Android UI toolkit is <em>not thread-safe</em> and must always
+be manipulated on the UI thread. In this piece of code above, the
+<code>ImageView</code> is manipulated on a worker thread, which can cause really
+weird problems. Tracking down and fixing such bugs can be difficult and
+time-consuming.</p>
+
+<p>Android offers several ways to access the UI
+thread from other threads. You may already be familiar with some of
+them but here is a comprehensive list:</p>
+
+<ul>
+<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable) Activity.runOnUiThread(Runnable)}</li>
+<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li>
+<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable, long)}</li>
+<li>{@link android.os.Handler}</li>
+</ul>
+
+<p>You can use any of these classes and methods to correct the previous code example:</p>
+
+<pre class="prettyprint">public void onClick(View v) {
+ new Thread(new Runnable() {
+ public void run() {
+ final Bitmap b = loadImageFromNetwork();
+ mImageView.post(new Runnable() {
+ public void run() {
+ mImageView.setImageBitmap(b);
+ }
+ });
+ }
+ }).start();
+}</pre>
+
+<p>Unfortunately,
+these classes and methods could also tend to make your code more complicated
+and more difficult to read. It becomes even worse when your implement
+complex operations that require frequent UI updates. </p>
+
+<p>To remedy this problem, Android 1.5 and later platforms offer a utility class
+called {@link android.os.AsyncTask}, that simplifies the creation of
+long-running tasks that need to communicate with the user interface.</p>
+
+<p>An <code>AsyncTask</code> equivalent is also available for applications that
+will run on Android 1.0 and 1.1. The name of the class is <a
+href="http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/
+curiouscreature/android/shelves/util/UserTask.java">UserTask</a>. It offers the
+exact same API and all you have to do is copy its source code in your
+application.</p>
+
+<p>The goal of <code>AsyncTask</code> is to take care of thread management for
+you. Our previous example can easily be rewritten with
+<code>AsyncTask</code>:</p>
+
+<pre class="prettyprint">public void onClick(View v) {
+ new DownloadImageTask().execute("http://example.com/image.png");
+}
+
+private class DownloadImageTask extends AsyncTask&lt;string, void,="" bitmap=""&gt; {
+ protected Bitmap doInBackground(String... urls) {
+ return loadImageFromNetwork(urls[0]);
+ }
+
+ protected void onPostExecute(Bitmap result) {
+ mImageView.setImageBitmap(result);
+ }
+ }</pre>
+
+<p>As you can see, <code>AsyncTask</code> <em>must</em> be used by subclassing
+it. It is also very important to remember that an <code>AsyncTask</code>
+instance has to be created on the UI thread and can be executed only once. You
+can read the <a
+href="http://developer.android.com/reference/android/os/AsyncTask.html">
+AsyncTask documentation</a> for a full understanding on how to use this class,
+but here is a quick overview of how it works:</p>
+
+<ul>
+<li>You can specify the type, using generics, of the parameters, the progress values and the final value of the task</li>
+<li>The method <a href="http://developer.android.com/reference/android/os/AsyncTask.html#doInBackground%28Params...%29">doInBackground()</a> executes automatically on a worker thread</li>
+<li><a href="http://developer.android.com/reference/android/os/AsyncTask.html#onPreExecute%28%29">onPreExecute()</a>, <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute%28Result%29">onPostExecute()</a> and <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate%28Progress...%29">onProgressUpdate()</a> are all invoked on the UI thread</li>
+<li>The value returned by <a href="http://developer.android.com/reference/android/os/AsyncTask.html#doInBackground%28Params...%29">doInBackground()</a> is sent to <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute%28Result%29">onPostExecute()</a></li>
+<li>You can call <a href="http://developer.android.com/reference/android/os/AsyncTask.html#publishProgress%28Progress...%29">publishProgress()</a> at anytime in <a href="http://developer.android.com/reference/android/os/AsyncTask.html#doInBackground%28Params...%29">doInBackground()</a> to execute <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate%28Progress...%29">onProgressUpdate()</a> on the UI thread</li><li>You can cancel the task at any time, from any thread</li>
+</ul>
+
+<p>In addition to the official documentation, you can read several complex examples in the source code of Shelves (<a href="http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/activity/ShelvesActivity.java">ShelvesActivity.java</a> and <a href="http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/activity/AddBookActivity.java">AddBookActivity.java</a>) and Photostream (<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/LoginActivity.java">LoginActivity.java</a>, <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java">PhotostreamActivity.java</a> and <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/ViewPhotoActivity.java">ViewPhotoActivity.java</a>). We highly recommend reading the source code of <a href="http://code.google.com/p/shelves/">Shelves</a> to see how to persist tasks across configuration changes and how to cancel them properly when the activity is destroyed.</p>
+
+<p>Regardless of whether or not you use <a href="http://developer.android.com/reference/android/os/AsyncTask.html">AsyncTask</a>,
+always remember these two rules about the single thread model: </p>
+
+<ol>
+<li>Do not block the UI thread, and
+<li>Make sure that you access the Android UI toolkit <em>only</em> on the UI thread.
+</ol>
+
+<p><code>AsyncTask</code> just makes it easier to do both of these things.</p>
diff --git a/docs/html/resources/articles/qsb.jd b/docs/html/resources/articles/qsb.jd
new file mode 100644
index 0000000..1249f21
--- /dev/null
+++ b/docs/html/resources/articles/qsb.jd
@@ -0,0 +1,151 @@
+page.title=Quick Search Box
+@jd:body
+
+<img src="images/qsb_002.png" style="float: right; margin-left: 2em; margin-bottom: 1em; width: 233px; height: 349.5px;"></p>
+
+<p>Starting with Android 1.6, the platform includes support for Quick Search
+Box (QSB), a powerful, system-wide search framework. Quick Search Box makes it
+possible for users to quickly and easily find what they're looking for, both on
+their devices and on the web. It suggests content on your device as you type,
+like apps, contacts, browser history, and music. It also offers results from the
+web search suggestions, local business listings, and other info from
+Google, such as stock quotes, weather, and flight status. All of this is
+available right from the home screen, by tapping on Quick Search Box.</p>
+
+<p>What
+we're most excited about with this new feature is the ability for you,
+the developers, to leverage the QSB framework to provide quicker and
+easier access to the content inside your apps. Your apps can provide
+search suggestions that will surface to users in QSB alongside other
+search results and suggestions. This makes it possible for users to
+access your application's content from outside your application—for
+example, from the home screen.</p>
+
+<p class="note"><strong>Note:</strong> The code fragments in this document are
+related to a sample app called <a
+href="http://developer.android.com/guide/samples/SearchableDictionary/index.
+html" title="Searchable Dictionary">Searchable Dictionary</a>. The app is
+available for Android 1.6 and later platforms.</p>
+
+<h3>The story before now: searching within your app</h3>
+
+<p>Platform releases versions previous to Android 1.6 already provided a mechanism
+that let you expose search and search suggestions in your app, as described in
+the docs for {@link android.app.SearchManager}. That mechanism has not changed
+and requires the following two things in your
+<code>AndroidManifest.xml</code>:</p>
+
+<p>1) In your <code>&lt;activity&gt;</code>, an intent filter, and a reference
+to a <code>searchable.xml</code> file (described below):</p>
+
+<pre class="prettyprint">&lt;intent-filter&gt;
+ &lt;action android:name="android.intent.action.SEARCH" /&gt;
+ &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+&lt;/intent-filter&gt;
+
+&lt;meta-data android:name="android.app.searchable"
+ android:resource="@xml/searchable" /&gt;</pre>
+
+<p>2) A content provider that can provide search suggestions according to the
+URIs and column formats specified by the
+<a href="{@docRoot}reference/android/app/SearchManager.html#Suggestions">Search Suggestions</a>
+section of the SearchManager docs:</p>
+
+<pre class="prettyprint">&lt;!-- Provides search suggestions for words and their definitions. --&gt;
+&lt;provider android:name="DictionaryProvider"
+ android:authorities="dictionary"
+ android:syncable="false" /&gt;</pre>
+
+<p>In the <code>searchable.xml</code> file, you specify a few things about how
+you want the search system to present search for your app, including the
+authority of the content provider that provides suggestions for the user as they
+type. Here's an example of the <code>searchable.xml</code> of an Android app
+that provides search suggestions within its own activities:</p>
+
+<pre class="prettyprint">&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+ android:label="@string/search_label"
+ android:searchSuggestAuthority="dictionary"
+ android:searchSuggestIntentAction="android.intent.action.VIEW"&gt;
+&lt;/searchable&gt;</pre>
+
+<p>Note that the <code>android:searchSuggestAuthority</code> attribute refers to
+the authority of the content provider we declared in
+<code>AndroidManifest.xml</code>.</p>
+
+<p>For more details on this, see the
+<a href="{@docRoot}reference/android/app/SearchManager.html#SearchabilityMetadata">Searchability Metadata
+section</a> of the of the SearchManager docs.</p>
+
+<h3>Including your app in Quick Search Box</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Searchable Dictionary Sample App</h2>
+<p>Quick Search Box provides a really cool way to make it easier and faster for
+users to access your app's content. To help you get your app started with it,
+we've created a sample app that simply provides access to a small dictionary of
+words in QSB. The app is called Searchable Dictionary, and we encourage you to
+<a href="{@docRoot}resources/samples/SearchableDictionary/index.html">check it
+out</a>.</p>
+</div>
+</div>
+
+<p>In Android 1.6, we added a new attribute to the metadata for searchables:
+<code>android:includeInGlobalSearch</code>. By specifying this as
+<code>"true"</code> in your <code>searchable.xml</code>, you allow QSB to pick
+up your search suggestion content provider and include its suggestions along
+with the rest (if the user enables your suggestions from the system search
+settings).</p>
+
+<p>You should also specify a string value for
+<code>android:searchSettingsDescription</code>, which describes to users what
+sorts of suggestions your app provides in the system settings for search.</p>
+
+<pre class="prettyprint">&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
+ android:label="@string/search_label"
+ <span style="background: rgb(255, 255, 0) none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">android:searchSettingsDescription="@string/settings_description"</span>
+ <span style="background: rgb(255, 255, 0) none repeat scroll 0% 0%; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;">android:includeInGlobalSearch="true"</span>
+ android:searchSuggestAuthority="dictionary"
+ android:searchSuggestIntentAction="android.intent.action.VIEW"&gt;
+&lt;/searchable&gt;</pre>
+
+<p>These new attributes are supported only in Android 1.6 and later.</p>
+
+<h3>What to expect</h3>
+
+<p>The
+first and most important thing to note is that when a user installs an
+app with a suggestion provider that participates in QSB, this new app
+will <em>not</em> be enabled for QSB by default. The user can choose
+to enable particular suggestion sources from the system settings for
+search (by going to "Search" &gt; "Searchable items" in settings).</p>
+
+<p>You
+should consider how to handle this in your app. Perhaps show a notice
+that instructs the user to visit system settings and enable your app's
+suggestions.</p>
+
+<p>Once the user enables your searchable item, the
+app's suggestions will have a chance to show up in QSB, most likely
+under the "more results" section to begin with. As your app's
+suggestions are chosen more frequently, they can move up in the list.</p>
+
+<img src="images/qsb.png" style="width: 233px; height: 349.5px;">
+<img id="k0vw" src="images/qsb_003.png" style="width: 233px; height: 349.5px;">
+
+<h3>Shortcuts</h3>
+
+<p>One
+of our objectives with QSB is to make it faster for users to access the
+things they access most often. One way we've done this is by
+'shortcutting' some of the previously chosen search suggestions, so
+they will be shown immediately as the user starts typing, instead of
+waiting to query the content providers. Suggestions from your app may
+be chosen as shortcuts when the user clicks on them.</p>
+
+<p>For dynamic suggestions that may wish to change their content (or become invalid)
+in the future, you can provide a 'shortcut id'. This tells QSB to query
+your suggestion provider for up-to-date content for a suggestion after
+it has been displayed. For more details on how to manage shortcuts, see
+the Shortcuts section
+<a href="{@docRoot}reference/android/app/SearchManager.html#ExposingSearchSuggestionsToQuickSearchBox">within the SearchManager docs</a>.</p>
diff --git a/docs/html/resources/articles/timed-ui-updates.jd b/docs/html/resources/articles/timed-ui-updates.jd
new file mode 100644
index 0000000..863387c
--- /dev/null
+++ b/docs/html/resources/articles/timed-ui-updates.jd
@@ -0,0 +1,149 @@
+page.title=Updating the UI from a Timer
+@jd:body
+
+<img style="margin: 1.5em; float: right;" src="images/JFlubber.png" alt="" id="BLOGGER_PHOTO_ID_5135098660116808706" border="0">
+
+<p><strong>Background</strong>: While developing my first useful
+(though small) application for Android, which was a port of an existing
+utility I use when podcasting, I needed a way of updating a clock
+displayed on the UI at regular intervals, but in a lightweight and CPU
+efficient way.</p>
+
+<p><strong>Problem</strong>: In the original application I used
+java.util.Timer to update the clock, but that class is not such a good
+choice on Android. Using a Timer introduces a new thread into the
+application for a relatively minor reason. Thinking in terms of mobile
+applications often means re-considering choices that you might make
+differently for a desktop application with relatively richer resources
+at its disposal. We would like to find a more efficient way of updating
+that clock.</p>
+
+<p><strong>The Application</strong>: The original application is a
+Java Swing and SE application. It is like a stopwatch with a lap timer
+that we use when recording podcasts; when you start the recording, you
+start the stopwatch. Then for every mistake that someone makes, you hit
+the flub button. At the end you can save out the bookmarked mistakes
+which can be loaded into the wonderful
+<a href="http://audacity.sourceforge.net/" title="Audacity">Audacity</a>
+audio editor as a labels track. You can then see where all of the mistakes
+are in the recording and edit them out.</p>
+
+<p>The article describing it is: <a href="http://www.developer.com/java/ent/print.php/3589961" title="http://www.developer.com/java/ent/print.php/3589961">http://www.developer.com/java/ent/print.php/3589961</a></p>
+
+<p>In the original version, the timer code looked like this:</p>
+
+<pre>class UpdateTimeTask extends TimerTask {
+ public void run() {
+ long millis = System.currentTimeMillis() - startTime;
+ int seconds = (int) (millis / 1000);
+ int minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ timeLabel.setText(String.format("%d:%02d", minutes, seconds));
+ }
+}</pre><p>And in the event listener to start this update, the following Timer() instance is used:
+</p><pre>if(startTime == 0L) {
+ startTime = evt.getWhen();
+ timer = new Timer();
+ timer.schedule(new UpdateTimeTask(), 100, 200);
+}</pre>
+
+<p>In particular, note the 100, 200 parameters. The first parameter
+means wait 100 ms before running the clock update task the first time.
+The second means repeat every 200ms after that, until stopped. 200 ms
+should not be too noticeable if the second resolution happens to fall
+close to or on the update. If the resolution was a second, you could
+find the clock sometimes not updating for close to 2 seconds, or
+possibly skipping a second in the counting, it would look odd).</p>
+
+<p>When I ported the application to use the Android SDKs, this code
+actually compiled in Eclipse, but failed with a runtime error because
+the Timer() class was not available at runtime (fortunately, this was
+easy to figure out from the error messages). On a related note, the
+String.format method was also not available, so the eventual solution
+uses a quick hack to format the seconds nicely as you will see.</p>
+
+<p>Fortunately, the role of Timer can be replaced by the
+android.os.Handler class, with a few tweaks. To set it up from an event
+listener:</p>
+
+<pre>private Handler mHandler = new Handler();
+
+...
+
+OnClickListener mStartListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (mStartTime == 0L) {
+ mStartTime = System.currentTimeMillis();
+ mHandler.removeCallbacks(mUpdateTimeTask);
+ mHandler.postDelayed(mUpdateTimeTask, 100);
+ }
+ }
+};</pre>
+
+<p>A couple of things to take note of here. First, the event doesn't
+have a .getWhen() method on it, which we handily used to set the start
+time for the timer. Instead, we grab the System.currentTimeMillis().
+Also, the Handler.postDelayed() method only takes one time parameter,
+it doesn't have a "repeating" field. In this case we are saying to the
+Handler "call mUpdateTimeTask() after 100ms", a sort of fire and forget
+one time shot. We also remove any existing callbacks to the handler
+before adding the new handler, to make absolutely sure we don't get
+more callback events than we want.</p>
+
+<p>But we want it to repeat, until we tell it to stop. To do this, just
+put another postDelayed at the tail of the mUpdateTimeTask run()
+method. Note also that Handler requires an implementation of Runnable,
+so we change mUpdateTimeTask to implement that rather than extending
+TimerTask. The new clock updater, with all these changes, looks like
+this:</p>
+
+<pre>private Runnable mUpdateTimeTask = new Runnable() {
+ public void run() {
+ final long start = mStartTime;
+ long millis = SystemClock.uptimeMillis() - start;
+ int seconds = (int) (millis / 1000);
+ int minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ if (seconds &lt; 10) {
+ mTimeLabel.setText("" + minutes + ":0" + seconds);
+ } else {
+ mTimeLabel.setText("" + minutes + ":" + seconds);
+ }
+
+ mHandler.postAtTime(this,
+ start + (((minutes * 60) + seconds + 1) * 1000));
+ }
+};</pre>
+
+<p>and can be defined as a class member field.</p>
+
+<p>The if statement is just a way to make sure the label is set to
+10:06 instead of 10:6 when the seconds modulo 60 are less than 10
+(hopefully String.format() will eventually be available). At the end of
+the clock update, the task sets up another call to itself from the
+Handler, but instead of a hand-wavy 200ms before the update, we can
+schedule it to happen at a particular wall-clock time — the line: start
++ (((minutes * 60) + seconds + 1) * 1000) does this.</p>
+
+<p>All we need now is a way to stop the timer when the stop button
+is pressed. Another button listener defined like this:</p>
+
+<pre>OnClickListener mStopListener = new OnClickListener() {
+ public void onClick(View v) {
+ mHandler.removeCallbacks(mUpdateTimeTask);
+ }
+};</pre>
+
+<p>will make sure that the next callback is removed when the stop button
+is pressed, thus interrupting the tail iteration.</p>
+
+<p>Handler is actually a better choice than Timer for another reason
+too. The Handler runs the update code as a part of your main thread,
+avoiding the overhead of a second thread and also making for easy
+access to the View hierarchy used for the user interface. Just remember
+to keep such tasks small and light to avoid slowing down the user
+experience.</p>
+
+
diff --git a/docs/html/resources/articles/touch-mode.jd b/docs/html/resources/articles/touch-mode.jd
new file mode 100644
index 0000000..e340062
--- /dev/null
+++ b/docs/html/resources/articles/touch-mode.jd
@@ -0,0 +1,138 @@
+page.title=Touch Mode
+@jd:body
+
+<p>This article explains the <em>touch mode</em>, one of the most
+important principles of Android's UI toolkit.</p>
+
+<p>The touch mode is a state of the view hierarchy that depends solely on the
+user interaction with the phone. By itself, the touch mode is something very
+easy to understand as it simply indicates whether the last user interaction was
+performed with the touch screen. For example, if you are using an
+Android-powered device, selecting a widget with the trackball will take you out
+of touch mode; however, if you touch a button on the screen with your finger,
+you will enter touch mode. When the user is not in touch mode, we talk about the
+trackball mode, navigation mode or keyboard navigation, so do not be surprised
+if you encounter these terms. </p>
+
+<p>There is only one API directly related to touch mode,
+{@link android.view.View#isInTouchMode() View.isInTouchMode()}.</p>
+
+<p>Sounds easy enough, right? Oddly enough, touch mode is deceivingly simple and
+the consequences of entering touch mode are far greater than you might
+think. Let's look at some of the reasons why.</p>
+
+<h4>Touch Mode, Selection, and Focus</h4>
+
+<p>Designing a UI toolkit for mobile devices is difficult because of the various
+interaction mechanisms they provide. Some devices offer only 12 keys, some have
+a touch screen, some require a stylus, some have both a touch screen and a
+keyboard. Based on the hardware capabilities of the he user can interact with
+your application using different mechanisms, so we had to think very hard about
+all the possible issues that could arise. One issue led us to create the touch
+mode.</p>
+
+<p>Imagine a simple application, <a href="{@docRoot}resources/samples/index.html">ApiDemos</a>
+for example, that shows a list of text items. The user can freely
+navigate through the list using the trackball but also, alternatively, scroll
+and fling the list using the touch screen. The issue in this scenario is
+how to handle the selection properly when the user manipulates the list
+through the touch screen. </p>
+
+<p>In this case, if the user selects an item at the top of the list and then
+flings the list towards the bottom, what should happen to the selection? Should
+it remain on the item and scroll off the screen? What should happen if the user
+then decided to move the selection with the trackball? Or worse, what should
+happen if the user presses the trackball to act upon the currently selected
+item, which is not shown on screen anymore? </p>
+
+<p>After careful consideration, we decided to remove the selection altogether,
+when the user manipulates the UI through the touch screen.</p>
+
+<p>In touch mode, there is no focus and no selection. Any selected item in a
+list of in a grid becomes unselected as soon as the user enters touch
+mode. Similarly, any focused widgets become unfocused when the user
+enters touch mode. The image below illustrates what happens when the
+user touches a list after selecting an item with the trackball.</p>
+
+<img style="margin: 0px 7px;" src="images/list02.png" alt="" id="BLOGGER_PHOTO_ID_5272753165743060962" border="0">
+<img style="margin: 0px 7px;" src="images/list01.png" alt="" id="BLOGGER_PHOTO_ID_5272753357441963442" border="0">
+
+<p>To
+make things more natural for the user, the framework knows how to
+resurrect the selection/focus whenever the user leaves touch mode. For
+instance, in the example above, if the user were to use the trackball
+again, the selection would reappear on the previously-selected item.
+This is why some developers are confused when they create a custom view
+and start receiving key events only after moving the trackball once:
+their application is in touch mode, and they need to use the trackball
+to exit touch mode and resurrect the focus.</p>
+
+<p>The relationship between touch mode, selection, and focus means you must not
+rely on selection and/or focus to exist in your application. A very common
+problem with new Android developers is to rely on
+{@link android.widget.AdapterView#getSelectedItemPosition() ListView.getSelectedItemPosition()}.
+In touch mode, this method will return
+{@link android.widget.AdapterView#INVALID_POSITION INVALID_POSITION}.
+ You should instead use click listeners (see
+{@link android.widget.AdapterView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)})
+or the choice mode (see
+{@link android.widget.ListView#setChoiceMode(int)}).</p>
+
+<h4>Focusable in Touch Mode</h4>
+
+<p>In general, focus doesn't exist in touch mode. However, focus can exist in
+touch mode in a very special way called <em>focusable</em>. This special mode
+was created for widgets that receive text input, such as
+{@link android.widget.EditText} or, when filtering is enabled,
+{@link android.widget.ListView}. The focusable mode is what lets the user enter text
+inside a text field on the screen, without first selecting it with the trackball
+or their finger.</p>
+
+<p>When a user
+touches the screen, the application will enter touch mode if it wasn't
+in touch mode already. What happens during the transition to
+touch mode depends on what the user touched, and what currently has
+focus. If the user touches a widget that is focusable in touch
+mode, that widget will receive focus. Otherwise, any currently
+focused widget will not retain focus unless it is focusable in touch
+mode. For instance, in the picture below, when the user touches
+the screen, the input text field receives the focus.</p>
+
+<img style="margin: 0px 7px;" src="images/text_field.png" alt="" id="BLOGGER_PHOTO_ID_5272755475757779154" border="0">
+
+<p>Fousable in touch mode (see
+{@link android.view.View#setFocusableInTouchMode(boolean) View.setFocusableInTouchMode})
+ is a property that you can set yourself, either from code or from XML.
+However, you should use it sparingly and only in very specific situations,
+because it breaks consistency with the normal behavior of the Android UI. A game
+is a good example of an application that could make good use of the focusable in
+touch mode property. MapView, if used in fullscreen as in Google Maps, is
+another good example of where you can use focusable in touch mode correctly.</p>
+
+<p>Below is another example of a focusable in touch mode widget. When the user
+taps an <code>AutoCompleteTextView</code> suggestion with his finger, the focus
+remains on the input text field:</p>
+
+<img style="margin: 0px 7px;" src="images/search01.png" alt="" id="BLOGGER_PHOTO_ID_5272756689821626962" border="0">
+<img style="margin: 0px 7px;" src="images/search02.png" alt="" id="BLOGGER_PHOTO_ID_5272756246104676754" border="0">
+
+<p>Developers new to Android often think that focusable in touch mode is the
+solution they need to "fix" the problem of "disappearing" selection/focus. We
+really encourage you to think very hard before using it. If used incorrectly, it
+can make your application behave differently from the rest of the system and
+simply throw off the user's habits. The Android framework contains all the tools
+you need to handle user interactions without using focusable in touch mode. For
+example, instead of trying to make <code>ListView</code> always keep its
+selection, simply use the appropriate choice mode, as shown in
+{@link android.widget.ListView#setChoiceMode(int)}.
+
+<h4>Touch Mode Cheat Sheet</h4>
+
+<p>Do:</p>
+<ul>
+<li>Remain consistent with the core applications</li><li>Use the appropriate feature if you need persistent selection (radio button, check box, the <code>ListView</code> choice mode, etc.)</li>
+<li>Use focusable in touch mode if you write a game</li>
+</ul>
+
+<p>Don't:</p>
+<ul><li>Do not try to keep the focus or selection in touch mode</li></ul>
diff --git a/docs/html/resources/articles/track-mem.jd b/docs/html/resources/articles/track-mem.jd
new file mode 100644
index 0000000..d580e82
--- /dev/null
+++ b/docs/html/resources/articles/track-mem.jd
@@ -0,0 +1,62 @@
+page.title=Tracking Memory Allocations
+@jd:body
+
+<p>Writing efficient mobile applications is not always straightforward. In
+particular, Android applications rely on automatic memory management handled by
+Dalvik's garbage collector, which can sometimes cause performance issues if you
+are not careful with memory allocations.</p>
+
+<p>In a performance-sensitive code path, such as the layout or drawing method of
+a view or the logic code of a game, any allocation comes at a price. After too
+many allocations, the garbage collector will kick in and stop your application
+to let it free some memory. Most of the time, garbage collections happen fast
+enough for you not to notice. However, if a collection happens while you are
+scrolling through a list of items or while you are trying to defeat a foe in a
+game, you may suddenly see a drop in performance/responsiveness of the
+application. It's not unusual for a garbage collection to take 100 to 200 ms.
+For comparison, a smooth animation needs to draw each frame in 16 to 33 ms. If
+the animation is suddenly interrupted for 10 frames, you can be certain that
+your users will notice.</p>
+
+<p>Most of the time, garbage collection occurs because of tons of small,
+short-lived objects and some garbage collectors, like generational garbage
+collectors, can optimize the collection of these objects so that the application
+does not get interrupted too often. The Android garbage collector is
+unfortunately not able to perform such optimizations and the creation of
+short-lived objects in performance critical code paths is thus very costly for
+your application.</p>
+
+<p>To help you avoid frequent garbage collections, the Android SDK ships with a
+very useful tool called <em>allocation tracker</em>. This tool is part of DDMS,
+which you must have already used for debugging purposes. To start using the
+allocation tracker, you must first launch the standalone version of DDMS, which
+can be found in the <code>tools/</code> directory of the SDK. The version of
+DDMS included in the Eclipse plugin does not offer you ability to use the
+allocation tracker yet.</p>
+
+<p>Once DDMS is running, simply select your application process and then click
+the <em>Allocation Tracker</em> tab. In the new view, click <em>Start
+Tracking</em> and then use your application to make it execute the code paths
+you want to analyze. When you are ready, click <em>Get Allocations</em>. A list
+of allocated objects will be shown in the first table. By clicking on a line you
+can see, in the second table, the stack trace that led to the allocation. Not
+only you will know what type of object was allocated, but also in which thread,
+in which class, in which file and at which line. The following screenshot shows
+the allocations performed by <a
+href="http://code.google.com/p/shelves">Shelves</a> while scrolling a
+ListView.</p>
+
+<a href="images/ddms_allocation_trackerl.png">
+
+<img style="cursor:hand;width: 320px; height: 250px;" src="images/ddms_allocation_tracker.png" border="0" alt="" />
+</a>
+
+<p>Even though it is not necessary &mdash; and sometimes not possible &mdash; to
+remove all allocations for your performance critical code paths. the allocation
+tracker will help you identify important issues in your code. For instance, a
+common mistake I have seen in many applications is to create a new
+<code>Paint</code> object on every draw. Moving the paint into an instance field
+is a simple fix that helps performance a lot. I highly encourage you to peruse
+the <a href="http://source.android.com/">Android source code</a> to see how we
+reduce allocations in performance-critical code paths. You will also thus
+discover the APIs Android provide to help you reuse objects.</p>
diff --git a/docs/html/resources/articles/tts.jd b/docs/html/resources/articles/tts.jd
new file mode 100644
index 0000000..e3fad91
--- /dev/null
+++ b/docs/html/resources/articles/tts.jd
@@ -0,0 +1,241 @@
+page.title=Using Text-to-Speech
+@jd:body
+
+<p>Starting with Android 1.6 (API Level 4), the Android platform includes a new
+Text-to-Speech (TTS) capability. Also known as "speech synthesis", TTS enables
+your Android device to "speak" text of different languages.</p>
+
+<p>Before we explain how to use the TTS API itself, let's first review a few
+aspects of the engine that will be important to your TTS-enabled application. We
+will then show how to make your Android application talk and how to configure
+the way it speaks.</p>
+
+<h3>Languages and resources</h3>
+
+<p>The TTS engine that ships with the Android platform supports a number of
+languages: English, French, German, Italian and Spanish. Also, depending on
+which side of the Atlantic you are on, American and British accents for English
+are both supported.</p>
+
+<p>The TTS engine needs to know which language to speak, as a word like "Paris",
+for example, is pronounced differently in French and English. So the voice and
+dictionary are language-specific resources that need to be loaded before the
+engine can start to speak.</p>
+
+<p>Although all Android-powered devices that support the TTS functionality ship
+with the engine, some devices have limited storage and may lack the
+language-specific resource files. If a user wants to install those resources,
+the TTS API enables an application to query the platform for the availability of
+language files and can initiate their download and installation. So upon
+creating your activity, a good first step is to check for the presence of the
+TTS resources with the corresponding intent:</p>
+
+<pre>Intent checkIntent = new Intent();
+checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
+startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);</pre>
+
+<p>A successful check will be marked by a <code>CHECK_VOICE_DATA_PASS</code>
+result code, indicating this device is ready to speak, after the creation of
+our
+{@link android.speech.tts.TextToSpeech} object. If not, we need to let the user
+know to install the data that's required for the device to become a
+multi-lingual talking machine! Downloading and installing the data is
+accomplished by firing off the ACTION_INSTALL_TTS_DATA intent, which will take
+the user to Android Market, and will let her/him initiate the download.
+Installation of the data will happen automatically once the download completes.
+Here is an example of what your implementation of
+<code>onActivityResult()</code> would look like:</p>
+
+<pre>private TextToSpeech mTts;
+protected void onActivityResult(
+ int requestCode, int resultCode, Intent data) {
+ if (requestCode == MY_DATA_CHECK_CODE) {
+ if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
+ // success, create the TTS instance
+ mTts = new TextToSpeech(this, this);
+ } else {
+ // missing data, install it
+ Intent installIntent = new Intent();
+ installIntent.setAction(
+ TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
+ startActivity(installIntent);
+ }
+ }
+}</pre>
+
+<p>In the constructor of the <code>TextToSpeech</code> instance we pass a
+reference to the <code>Context</code> to be used (here the current Activity),
+and to an <code>OnInitListener</code> (here our Activity as well). This listener
+enables our application to be notified when the Text-To-Speech engine is fully
+loaded, so we can start configuring it and using it.</p>
+
+<h4>Languages and Locale</h4>
+
+<p>At Google I/O 2009, we showed an <a title="Google I/O 2009, TTS
+demonstration" href="http://www.youtube.com/watch?v=uX9nt8Cpdqg#t=6m17s"
+id="rnfd">example of TTS</a> where it was used to speak the result of a
+translation from and to one of the 5 languages the Android TTS engine currently
+supports. Loading a language is as simple as calling for instance:</p>
+
+<pre>mTts.setLanguage(Locale.US);</pre><p>to load and set the language to
+English, as spoken in the country "US". A locale is the preferred way to specify
+a language because it accounts for the fact that the same language can vary from
+one country to another. To query whether a specific Locale is supported, you can
+use <code>isLanguageAvailable()</code>, which returns the level of support for
+the given Locale. For instance the calls:</p>
+
+<pre>mTts.isLanguageAvailable(Locale.UK))
+mTts.isLanguageAvailable(Locale.FRANCE))
+mTts.isLanguageAvailable(new Locale("spa", "ESP")))</pre>
+
+<p>will return TextToSpeech.LANG_COUNTRY_AVAILABLE to indicate that the language
+AND country as described by the Locale parameter are supported (and the data is
+correctly installed). But the calls:</p>
+
+<pre>mTts.isLanguageAvailable(Locale.CANADA_FRENCH))
+mTts.isLanguageAvailable(new Locale("spa"))</pre>
+
+<p>will return <code>TextToSpeech.LANG_AVAILABLE</code>. In the first example,
+French is supported, but not the given country. And in the second, only the
+language was specified for the Locale, so that's what the match was made on.</p>
+
+<p>Also note that besides the <code>ACTION_CHECK_TTS_DATA</code> intent to check
+the availability of the TTS data, you can also use
+<code>isLanguageAvailable()</code> once you have created your
+<code>TextToSpeech</code> instance, which will return
+<code>TextToSpeech.LANG_MISSING_DATA</code> if the required resources are not
+installed for the queried language.</p>
+
+<p>Making the engine speak an Italian string while the engine is set to the
+French language will produce some pretty <i>interesting </i>results, but it will
+not exactly be something your user would understand So try to match the
+language of your application's content and the language that you loaded in your
+<code>TextToSpeech</code> instance. Also if you are using
+<code>Locale.getDefault()</code> to query the current Locale, make sure that at
+least the default language is supported.</p>
+
+<h3>Making your application speak</h3>
+
+<p>Now that our <code>TextToSpeech</code> instance is properly initialized and
+configured, we can start to make your application speak. The simplest way to do
+so is to use the <code>speak()</code> method. Let's iterate on the following
+example to make a talking alarm clock:</p>
+
+<pre>String myText1 = "Did you sleep well?";
+String myText2 = "I hope so, because it's time to wake up.";
+mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, null);
+mTts.speak(myText2, TextToSpeech.QUEUE_ADD, null);</pre>
+
+<p>The TTS engine manages a global queue of all the entries to synthesize, which
+are also known as "utterances". Each <code>TextToSpeech</code> instance can
+manage its own queue in order to control which utterance will interrupt the
+current one and which one is simply queued. Here the first <code>speak()</code>
+request would interrupt whatever was currently being synthesized: the queue is
+flushed and the new utterance is queued, which places it at the head of the
+queue. The second utterance is queued and will be played after
+<code>myText1</code> has completed.</p>
+
+<h4>Using optional parameters to change the playback stream type</h4>
+
+<p>On Android, each audio stream that is played is associated with one stream
+type, as defined in
+{@link android.media.AudioManager android.media.AudioManager}. For a talking
+alarm clock, we would like our text to be played on the
+<code>AudioManager.STREAM_ALARM</code> stream type so that it respects the alarm
+settings the user has chosen on the device. The last parameter of the speak()
+method allows you to pass to the TTS engine optional parameters, specified as
+key/value pairs in a HashMap. Let's use that mechanism to change the stream type
+of our utterances:</p>
+
+<pre>HashMap&lt;String, String&gt; myHashAlarm = new HashMap();
+myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
+ String.valueOf(AudioManager.STREAM_ALARM));
+mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
+mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);</pre>
+
+<h4>Using optional parameters for playback completion callbacks</h4>
+
+<p>Note that <code>speak()</code> calls are asynchronous, so they will return
+well before the text is done being synthesized and played by Android, regardless
+of the use of <code>QUEUE_FLUSH</code> or <code>QUEUE_ADD</code>. But you might
+need to know when a particular utterance is done playing. For instance you might
+want to start playing an annoying music after <code>myText2</code> has finished
+synthesizing (remember, we're trying to wake up the user). We will again use an
+optional parameter, this time to tag our utterance as one we want to identify.
+We also need to make sure our activity implements the
+<code>TextToSpeech.OnUtteranceCompletedListener</code> interface:</p>
+
+<pre>mTts.setOnUtteranceCompletedListener(this);
+myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
+ String.valueOf(AudioManager.STREAM_ALARM));
+mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
+myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
+ "end of wakeup message ID");
+// myHashAlarm now contains two optional parameters
+mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);</pre>
+
+<p>And the Activity gets notified of the completion in the implementation
+of the listener:</p>
+
+<pre>public void onUtteranceCompleted(String uttId) {
+ if (uttId == "end of wakeup message ID") {
+ playAnnoyingMusic();
+ }
+}</pre>
+
+<h4>File rendering and playback</h4>
+
+<p>While the <code>speak()</code> method is used to make Android speak the text
+right away, there are cases where you would want the result of the synthesis to
+be recorded in an audio file instead. This would be the case if, for instance,
+there is text your application will speak often; you could avoid the synthesis
+CPU-overhead by rendering only once to a file, and then playing back that audio
+file whenever needed. Just like for <code>speak()</code>, you can use an
+optional utterance identifier to be notified on the completion of the synthesis
+to the file:</p>
+
+<pre>HashMap&lt;String, String&gt; myHashRender = new HashMap();
+String wakeUpText = "Are you up yet?";
+String destFileName = "/sdcard/myAppCache/wakeUp.wav";
+myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, wakeUpText);
+mTts.synthesizeToFile(wakuUpText, myHashRender, destFileName);</pre>
+
+<p>Once you are notified of the synthesis completion, you can play the output
+file just like any other audio resource with
+{@link android.media.MediaPlayer android.media.MediaPlayer}.</p>
+
+<p>But the <code>TextToSpeech</code> class offers other ways of associating
+audio resources with speech. So at this point we have a WAV file that contains
+the result of the synthesis of "Wake up" in the previously selected language. We
+can tell our TTS instance to associate the contents of the string "Wake up" with
+an audio resource, which can be accessed through its path, or through the
+package it's in, and its resource ID, using one of the two
+<code>addSpeech()</code> methods:</p>
+
+<pre>mTts.addSpeech(wakeUpText, destFileName);</pre>
+
+<p>This way any call to speak() for the same string content as
+<code>wakeUpText</code> will result in the playback of
+<code>destFileName</code>. If the file is missing, then speak will behave as if
+the audio file wasn't there, and will synthesize and play the given string. But
+you can also take advantage of that feature to provide an option to the user to
+customize how "Wake up" sounds, by recording their own version if they choose
+to. Regardless of where that audio file comes from, you can still use the same
+line in your Activity code to ask repeatedly "Are you up yet?":</p>
+
+<pre>mTts.speak(wakeUpText, TextToSpeech.QUEUE_ADD, myHashAlarm);</pre>
+
+<h4>When not in use...</h4><p>The text-to-speech functionality relies on a
+dedicated service shared across all applications that use that feature. When you
+are done using TTS, be a good citizen and tell it "you won't be needing its
+services anymore" by calling <code>mTts.shutdown()</code>, in your Activity
+<code>onDestroy()</code> method for instance.</p>
+
+<h3>Conclusion</h3>
+
+<p>Android now talks, and so can your apps. Remember that in order for
+synthesized speech to be intelligible, you need to match the language you select
+to that of the text to synthesize. Text-to-speech can help you push your app in
+new directions. Whether you use TTS to help users with disabilities, to enable
+the use of your application while looking away from the screen, or simply to
+make it cool, we hope you'll enjoy this new feature.</p> \ No newline at end of file
diff --git a/docs/html/resources/articles/ui-1.5.jd b/docs/html/resources/articles/ui-1.5.jd
new file mode 100644
index 0000000..c10cf52
--- /dev/null
+++ b/docs/html/resources/articles/ui-1.5.jd
@@ -0,0 +1,48 @@
+page.title=UI Framework Changes in Android 1.5
+@jd:body
+
+
+<p>Android 1.5 offers a different default look for
+the Android UI framework, in relation to Android 1.0 and 1.1. The
+screenshots below show the same activity (creating a new contact) on
+Android 1.1 and Android 1.5:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 277px;" src="images/android.png" alt="" id="BLOGGER_PHOTO_ID_5323141124169754690" border="0">
+
+<p>You
+can see in this example that the buttons and checkboxes have a new
+appearance. Even though these changes do not affect binary nor source
+compatibility, they might still break the UI of your apps. As part of
+the UI refresh, the minimum size of some of the widgets has changed.
+For instance, Android 1.1 buttons have a minimum size of 44x48 pixels
+whereas Android 1.5 buttons now have a minimum size of 24x48 pixels.
+The image below compares the sizes of Android 1.1 buttons with Android
+1.5 buttons:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 100px; height: 130px;" src="images/buttons.png" alt="" border="0">
+
+<p>If you rely on the button's minimum size, then the layout of your application
+may not be the same in Android 1.5 as it was in Android 1.1 because of this
+change. This would happen for instance if you created a grid of buttons using
+<code>LinearLayout</code> and relying on the minimum size yielded by
+<code>wrap_content</code> to align the buttons properly:</p>
+
+<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 277px;" src="images/grid.png" alt="" id="BLOGGER_PHOTO_ID_5323147943613255250" border="0">
+
+<p>This layout could easily be fixed by using the
+<code>android:layout_weight</code> attribute or by replacing the
+<code>LinearLayout</code> containers with a <code>TableLayout</code>.</p>
+
+<p>This example is probably the worst-case UI issue you may encounter when
+running your application on Android 1.5. Other changes introduced in Android
+1.5, especially bug fixes in the layout views, may also impact your
+application—especially if it is relying on faulty/buggy behavior of the UI
+framework.</p>
+
+<p>If you encounter issues when running your application on Android 1.5, please
+join us on the <a href="{@docRoot}resources/community-groups.html">Android
+developer groups</a> or <a
+href="{@docRoot}resources/community-more.html">IRC</a> so that we and the
+Android community can help you fix your application.</p>
+
+<p>Happy coding!</p>
diff --git a/docs/html/resources/articles/ui-1.6.jd b/docs/html/resources/articles/ui-1.6.jd
new file mode 100644
index 0000000..10cb524
--- /dev/null
+++ b/docs/html/resources/articles/ui-1.6.jd
@@ -0,0 +1,130 @@
+page.title=UI Framework Changes in Android 1.6
+@jd:body
+
+<p>Android 1.6 introduces numerous enhancements and bug fixes in the UI
+framework. This article highlights two improvements in particular: more flexible
+and robust RelativeLayout and easier click listeners. </p>
+
+<h3>More flexible, more robust RelativeLayout</h3>
+
+<p>RelativeLayout is the most versatile layout offered by the Android UI toolkit
+and can be successfully used to reduce the number of views created by your
+applications. This layout used to suffer from various bugs and limitations,
+sometimes making it difficult to use without having some knowledge of its
+implementation. To make your life easier, Android 1.6 comes with a revamped
+RelativeLayout. </p>
+
+<p>This new implementation not only fixes all known bugs in
+RelativeLayout but also addresses its major limitation: the
+fact that views had to be declared in a particular order. Consider the following
+XML layout:</p>
+
+<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
+
+&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="64dip"
+ android:padding="6dip"&gt;
+
+ &lt;TextView
+ android:id="@+id/band"
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:layout_below="@+id/track"
+ android:layout_alignLeft="@id/track"
+ android:layout_alignParentBottom="true"
+
+ android:gravity="top"
+ android:text="The Airborne Toxic Event" /&gt;
+
+ &lt;TextView
+ android:id="@id/track"
+ android:layout_marginLeft="6dip"
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:layout_toRightOf="@+id/artwork"
+
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="bottom"
+ android:text="Sometime Around Midnight" /&gt;
+
+ &lt;ImageView
+ android:id="@id/artwork"
+ android:layout_width="56dip"
+ android:layout_height="56dip"
+ android:layout_gravity="center_vertical"
+
+ android:src="@drawable/artwork" /&gt;
+
+&lt;/RelativeLayout&gt;</pre>
+
+<p>This code builds a very simple layout—an image on the left with two lines of
+text stacked vertically. This XML layout is perfectly fine and contains no
+errors. Unfortunately, Android 1.5's RelativeLayout is incapable of rendering it
+correctly, as shown in the screenshot below.</p>
+
+<img src="images/ui-1.6_002.png" style="width: 320px; height: 480px;">
+
+<p>The problem is that this layout uses forward references. For instance, the
+"band" TextView is positioned below the "track" TextView but "track" is declared
+after "band" and, in Android 1.5, RelativeLayout does not know how to handle
+this case. Now look at the exact same layout running on Android 1.6:</p>
+
+<img src="images/ui-1.6.png" style="width: 320px; height: 480px;">
+
+<p>As you can see Android 1.6 is now better able to handle forward reference.
+The result on screen is exactly what you would expect when writing the
+layout.</p>
+
+<h3>Easier click listeners</h3>
+
+<p>Setting up a click listener on a button is very common task, but
+it requires quite a bit of boilerplate code:</p>
+
+<pre>findViewById(R.id.myButton).setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ // Do stuff
+ }
+});</pre>
+
+<p>One way to reduce the amount of boilerplate is to share a single click
+listener between several buttons. While this technique reduces the
+number of classes, it still requires a fair amount of code and it still
+requires giving each button an id in your XML layout file:</p>
+
+<pre>View.OnClickListener handler = View.OnClickListener() {
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.myButton: // doStuff
+ break;
+ case R.id.myOtherButton: // doStuff
+ break;
+ }
+ }
+}
+
+findViewById(R.id.myButton).setOnClickListener(handler);
+findViewById(R.id.myOtherButton).setOnClickListener(handler);</pre>
+
+<p>With Android 1.6, none of this is necessary. All you have to do is
+declare a public method in your Activity to handle the click
+(the method <i>must</i> have one View argument):</p>
+
+<pre>class MyActivity extends Activity {
+ public void myClickHandler(View target) {
+ // Do stuff
+ }
+}</pre>
+
+<p>And then reference this method from your XML layout:</p>
+
+<pre>&lt;Button android:onClick="myClickHandler" /&gt;</pre>
+
+<p>This new feature reduces both the amount of Java and XML you have to write,
+leaving you more time to concentrate on your application.</p>
+
+<p>The Android team is committed to helping you write applications in the
+easiest and most efficient way possible. We hope you find these improvements
+useful and we're excited to see your applications on Android Market.</p>
diff --git a/docs/html/resources/articles/using-webviews.jd b/docs/html/resources/articles/using-webviews.jd
new file mode 100644
index 0000000..3a1f34c
--- /dev/null
+++ b/docs/html/resources/articles/using-webviews.jd
@@ -0,0 +1,61 @@
+page.title=Using WebViews
+@jd:body
+
+<p>A small application called <a title="WebViewDemo"
+href="http://code.google.com/p/apps-for-android/source/browse/#svn/trunk/Samples
+/WebViewDemo">WebViewDemo</a> shows how you can add web content to your
+application. You can find it in the <a title="apps-for-android"
+href="http://code.google.com/p/apps-for-android/">apps-for-android</a> project.
+This application demonstrates how you can embed a {@link android.webkit.WebView}
+into an activity and also how you can have two way communication between your
+application and the web content. </p>
+
+<p>A
+WebView uses the same rendering and JavaScript engine as the browser,
+but it runs under the control of your application. The WebView can be
+full screen or you can mix it with other Views. The content for your
+WebView can come from anywhere. The WebView can download content from
+the web, or it can come from local files stored in your assets
+directory. The content can even be dynamically generated by your
+application code. For this example, the HTML comes from a local file
+called <a title="demo.html" href="http://code.google.com/p/apps-for-android/source/browse/trunk/Samples/WebViewDemo/assets/demo.html">demo.html</a>.</p>
+
+<p>This application does not do very much: when you click on the
+android, he raises his arm.</p>
+
+<div style="text-align: center;"><img style="width: 322px; height: 482px;" src="images/webview.png"></div>
+
+<p>This
+could, of course, easily be accomplished with a little bit of
+JavaScript. Instead, though, WebViewDemo takes a slightly more
+complicated path to illustrate two very powerful features of WebView.</p>
+
+<p>First,
+JavaScript running inside the WebView can call out to code in your
+Activity. You can use this to have your JavaScript trigger actions like
+starting a new activity, or it can be used to fetch data from a
+database or {@link android.content.ContentProvider}. The API for this
+is very simple: just call the
+{@link android.webkit.WebView#addJavascriptInterface(java.lang.Object, java.lang.String) addJavascriptInterface()}
+method on your WebView. You pass an object whose methods you want to
+expose to JavaScript and the name to use when making calls. You can see
+the exact syntax in <a title="WebViewDemo.java"
+href="http://code.google.com/p/apps-for-android/source/browse/trunk/Samples/
+WebViewDemo/src/com/google/android/webviewdemo/WebViewDemo.java">WebViewDemo.
+java</a>. Here we are making our DemoJavascriptInterface object available to
+JavaScript where it will be called "window.demo".</p>
+
+<p>Second, your Activity can invoke JavaScript methods. All you have to do
+is call the {@link android.webkit.WebView#loadUrl(java.lang.String) loadUrl}
+method with the appropriate JavaScript call:</p>
+
+<p><code style="padding-left: 25px;">mWebView.loadUrl("javascript:wave()");</code></p>
+
+<p>Our <a title="WebViewDemo"
+href="http://code.google.com/p/apps-for-android/source/browse/#svn/trunk/Samples
+/WebViewDemo">WebViewDemo</a> uses both techniques: when you click on the
+android, it calls out to the activity, which then turns around and calls back
+into the JavaScript. WebViews are very powerful, and they may be a valuable tool
+to help you build your application – especially if you already have a lot of
+HTML content. As it happens, we've used exactly this approach in some of the
+applications we've written.</p>
diff --git a/docs/html/resources/articles/wikinotes-intents.jd b/docs/html/resources/articles/wikinotes-intents.jd
new file mode 100644
index 0000000..bc64544
--- /dev/null
+++ b/docs/html/resources/articles/wikinotes-intents.jd
@@ -0,0 +1,255 @@
+page.title=WikiNotes: Routing Intents
+@jd:body
+
+
+<p>In <a href="wikinotes-linkify.html">the Linkify! article</a>, we talked about
+using Linkify to turn wiki words (those that match a regular expression that we
+have defined) into a <code>content:</code> URI and defining a path to data that
+matched a note belonging to that wiki word. As an example, a matching word like
+<code>ToDoList</code> would be turned into a URI such as
+<code>content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList
+</code> and then acted upon using the VIEW action from the Linkify class.</p>
+
+<p>This article examines how the Android system takes this combination of
+<code>VIEW</code> action and <code>content:</code> URI and finds the correct
+activity to fire in order to do something with the data. It will also explain
+how the other default links created by Linkify, such as web URLs and telephone
+numbers, also result in the correct activity to handle that data type being
+fired. Finally, this article will start to examine the custom
+<code>ContentProvider</code> that has been created to handle WikiNotes data. The
+full description of the ContentProvider and what it does will span a couple more
+articles as well, because there is a lot to cover.</p>
+
+<h3>The Linkify-calls-intent Workflow</h3>
+
+<p>At a high level, the steps for Linkify to invoke an intent, and for the
+resulting activity (if any) to handle it, look like this:</p>
+
+<ol>
+ <li>Linkify is invoked on a TextView to turn matching text patterns into Intent links.</li>
+ <li>Linkify takes over monitoring for those Intent links being selected by the user.</li>
+ <li>When the user selects a link, Linkify calls the VIEW action using the content: URI associated with the link.</li>
+ <li>Android takes the content: URI that represents the data, and looks for a
+ContentProvider registered in the system that matches the URI.</li>
+ <li>If a match is found, Android queries the ContentProvider using the URI,
+and asks what MIME type the data that will be returned from the URI is.</li>
+ <li>Android then looks for an activity registered in the system with an
+intent-filter that matches both the VIEW action, and the MIME type for
+the data represented by the content: URI.</li>
+ <li>Assuming a match is found, Linkify then invokes the intent for
+the URI, at which point the activity takes over, and is handed
+the content: URI.</li>
+ <li>The activity can then use the URI to retrieve the data and act on
+it.</li>
+</ol>
+
+<p>This is actually a simpler process than it
+sounds, and it is quite lightweight as well. Perhaps a more
+understandable statement about how it works might be:</p>
+
+<p>Linkify is used to turn matching text into hot-links. When the user
+selects a hot-link, Android takes the data locator represented by the
+hot-link and looks for a data handler for that data locator. If it
+finds one, it asks for what type of data is returned for that locator.
+It then looks for something registered with the system that handles
+that type of data for the VIEW action, and starts it, including the
+data locator in the request.</p>
+
+<p>The real key here is the MIME type. MIME stands for <a
+href="http://en.wikipedia.org/wiki/MIME">Multipurpose Internet Mail
+Extensions</a> &mdash; a standard for sending attachments over email. The MIME
+type (which is the part Android uses) is a way of describing certain kinds of
+data. That type is then used to look for an Activity that can do something with
+that data type. In this way, ContentProviders and Activities (or other
+IntentReceivers) are decoupled, meaning that a given Content URI might have a
+different ContentProvider to handle it, but could still use the same MIME type
+meaning that the same activity could be called upon to handle the resulting
+data.</p>
+
+<h3>Linkify on a wiki word</h3>
+
+<p>Using the above workflow, let's take a look at exactly how the process
+works in WikiNotes for Android:</p>
+
+<p>First, Linkify is used to turn text matching the wiki word regular expression
+into a link that provides a Content URI for that wiki word, for example
+<code>content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList</code>.</p>
+
+<p>When the user clicks on the wiki word link, Linkify invokes the VIEW
+action on the Content URI. At this point, the Android system takes over
+getting the Intent request to the correct activity.</p>
+
+<p>Next, Android looks for a ContentProvider that has been registered
+with the system to handle URIs matching our Content URI format.</p>
+
+<p>In our case, we have a definition inside
+<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/WikiNotes/AndroidManifest.xml">our application's AndroidManifest.xml</a>
+file that reads:</p>
+
+<pre>&lt;provider name="com.google.android.wikinotes.db.WikiNotesProvider"
+ android:authorities="com.google.android.wikinotes.db.wikinotes" /&gt;</pre>
+
+<p>This establishes that we have a ContentProvider defined in our application
+that provides the "root authority":
+<code>com.google.android.wikinotes.db.wikinotes</code>. This is the first part
+of the Content URI that we create for a wiki word link. Root Authority is just
+another way of thinking about a descriptor that is registered with Android to
+allow requests for certain URLs to be routed to the correct class.</p>
+
+<p>So, the whole definition is that a class called
+<code>com.google.android.wikinotes.db.WikiNotesProvider</code> is registered
+with the system as able to handle the
+<code>com.google.android.wikinotes.db.wikinotes</code> root authority (i.e. URIs
+starting with that identifier).</p>
+
+<p>From here, Android takes the rest of the URI and presents it to that
+ContentProvider. If you look at the
+<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/WikiNotes/src/com/google/android/wikinotes/db/WikiNotesProvider.java">WikiNotesProvider
+class</a> and scroll to the very bottom, in the static block there, you can see
+the pattern definitions to match the rest of the URL.</p>
+
+<p>In particular, take a look at the two lines:</p>
+
+<pre>URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes", NOTES);
+URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes/*", NOTE_NAME);</pre>
+
+<p>These are the definitions of URIs that our ContentProvider recognizes and can
+handle. The first recognizes a full URI of
+<code>content://com.google.android.wikinotes.db.wikinotes/wikinotes</code> and
+associates that with a constant called NOTES. This is used elsewhere in the
+ContentProvider to provide a list of all of the wiki notes in the database when
+the URI is requested.</p>
+
+<p>The second line uses a wildcard &mdash; '*' &mdash; to match a request of the
+form that Linkify will create, e.g.
+<code>content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList
+</code>. In this example, the * matches the ToDoList part of the URI and is
+available to the handler of the request, so that it can fish out the matching
+note for ToDoList and return it as the data. This also associates that match
+with a constant called NOTE_NAME, which again is used as an identifier elsewhere
+in the ContentProvider.</p>
+
+<p>The other matches in this static block are related to forms of
+searching that have been implemented in the WikiNotes for Android
+application, and will be covered in later articles. Likewise, how the
+data is obtained from this matching pattern will be the subject of the
+next article.</p>
+
+<p>For right now we are concerned with the MIME type for the URI. This is
+defined in the <code>getType()</code> method also in the
+<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/WikiNotes/src/com/google/android/wikinotes/db/WikiNotesProvider.java">WikiNotesProvider
+class</a> (about halfway through the file). Take a quick look at this. The key
+parts for now are:</p>
+
+<pre>case NOTES:
+ return "vnd.android.cursor.<b>dir</b>/vnd.google.wikinote";</pre>
+
+<p>and</p>
+
+<pre>case NOTE_NAME:
+ return "vnd.android.cursor.<b>item</b>/vnd.google.wikinote";</pre>
+
+<p>These are the same constant names we defined in our pattern
+matchers. In the first case, that of the all notes URI, the MIME type
+returned is <code>vnd.android.cursor.dir/vnd.google.wikinote</code>
+which is like saying an Android list (dir) of Google wiki notes (the
+vnd bit is MIME-speak for "vendor specific definition"). Likewise, in
+the case of a NOTE_NAME match, the MIME type returned is
+<code>vnd.android.cursor.item/vnd.google.wikinote</code> which is
+like saying an Android item of Google wiki notes.</p>
+
+<p>Note that if you define your own MIME data types like this, the
+<code>vnd.android.cursor.dir</code> and <code>vnd.android.cursor.item</code>
+categories should be retained, since they have meaning to the Android
+system, but the actual item types should be changed to reflect your
+particular data type.</p>
+
+<p>So far Android has been able to find a ContentProvider that handles
+the Content URI supplied by the Linkify Intent call, and has queried
+the ContentProvider to find out the MIME types for that URI. The final
+step is to find an activity that can handle the VIEW action for that
+MIME type. Take a look in the the
+<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/WikiNotes/AndroidManifest.xml">AndroidManifest.xml file</a>
+again. Inside the WikiNotes activity definition, you will see:</p>
+
+<pre>&lt;intent-filter&gt;
+ &lt;action name="android.intent.action.VIEW"/&gt;
+ &lt;category name="android.intent.category.DEFAULT"/&gt;
+ &lt;category name="android.intent.category.BROWSABLE"/&gt;
+ &lt;data mimetype="vnd.android.cursor.item/vnd.google.wikinote"/&gt;
+&lt;/intent-filter&gt;</pre>
+
+<p>This is the correct combination of matches for the VIEW action on a
+WikiNote type that is requested from the LINKIFY class. The DEFAULT
+category indicates that the WikiNotes activity should be treated as a
+default handler (a primary choice) for this kind of data, and the
+BROWSABLE category means it can be invoked from a "browser", in this
+case the marked-up Linkified text.</p>
+
+<p>Using this information, Android can match up the VIEW action request
+for the WikiNotes data type with the WikiNotes activity, and can then
+use the WikiNotes activity to handle the request.</p>
+
+<h3>Why do it like this?</h3>
+
+<p>It's quite a trip through the system, and there is a lot to absorb
+here, but this is one of the main reasons I wanted to write WikiNotes
+in the first place. If you follow and understand the steps here, you'll
+have a good grasp of the whole Intents mechanism in Android, and how it
+helps loosely coupled activities cooperate to get things done.</p>
+
+<p>In this case, we could have found another way to detect wiki words
+based on a regular expression, and maybe written our own handler to
+intercept clicks within the TextView and dig out the right data and
+display it. This would seem to accomplish the same functionality just
+as easily as using intents, so what is the advantage to using the full
+Intents mechanism?</p>
+
+<p>In fact there are several advantages:</p>
+
+<p>The most obvious is that because we are using the standard Intent
+based approach, we are not limited to just linking and navigating to
+other wiki notes. We get similar behavior to a number of other data
+types as well. For example, a telephone number or web URL in a wiki
+note will be marked up by Linkify, and using this same mechanism (VIEW
+action on the linked data type) the browser or dialer activities will
+be automatically fired.</p>
+
+<p>It also means that each operation on a wiki note can be treated as a
+separate life cycle by our activity. We are not dealing with swapping
+data in and out of an existing activity - each activity works on a
+particular wiki note and that's all you have to worry about.</p>
+
+<p>Another advantage is that we now have a public activity to handle
+VIEW actions in WikiNotes no matter where the request comes from.
+Another application could request to view a wiki note (perhaps without
+even knowing what kind of data it is) and our activity could start up
+and handle it.</p>
+
+<p>The backstack is automatically maintained for you too. As you
+forward navigate through WikiNotes, Android maintains the history of
+notes visited, and so when you hit the back button you go back to the
+last note you were on. All this is free because we rely on the Android
+intents mechanism.</p>
+
+<p>Finally, if you run WikiNotes for Android and then start DDMS to
+take a look at the Activity threads in the WikiNotes application while
+it is running, you can see that despite what you might think, letting
+Android manage the navigation is very efficient. Create a few linked
+notes, as many links deep as you like, and then follow them. If you
+follow links hundreds of notes deep, you will still only see a handful
+of WikiNotes activities. Android is managing the activities, closing
+the older ones as necessary and using the life cycle to swap data in
+and out.</p>
+
+<h3>Next Time</h3>
+
+<p>This was a long article, but necessarily so. It demonstrates the
+importance of the Intents mechanism and to reinforce the notion that it
+should be used whenever possible for forward navigation, even within a
+single application. Illustrating this is one of the primary reasons I
+wrote WikiNotes for Android in the first place.</p>
+
+<p>In the next article we will look deeper into the ContentProvider and
+examine how it turns a Content URI into a row (or several rows) of data
+that can be used by an activity.</p>
diff --git a/docs/html/resources/articles/wikinotes-linkify.jd b/docs/html/resources/articles/wikinotes-linkify.jd
new file mode 100644
index 0000000..21b1f13
--- /dev/null
+++ b/docs/html/resources/articles/wikinotes-linkify.jd
@@ -0,0 +1,113 @@
+page.title=WikiNotes: Linkify your Text!
+@jd:body
+
+<img style="margin-left: 1.5em; margin-bottom:1.5em; float: right;"
+src="images/WikiNotes.png" alt="Linkify example" border="0">
+
+<p>This article introduces <a
+href="http://android-developers.blogspot.com/2008/03/announcing-apps-for-android
+.html">WikiNotes for Android</a>, part of the <a
+href="http://code.google.com/p/apps-for-android/">Apps for Android</a>
+project. It covers the use of Linkify to turn ordinary text views
+into richer, link-oriented content that causes Android intents to fire
+when a link is selected.</p>
+
+<p><strong>Linkify</strong>: The {@link android.text.util.Linkify} class in the
+framework is perfect for creating a wiki note pad. It lets you specify a <a
+title="regular expression"
+href="http://en.wikipedia.org/wiki/Regular_expression">regular expression
+&raquo;</a>
+to match, and a scheme to prepend. The scheme is a string that, when
+the matched text is added, forms a Content URI to allow the correct
+data to be looked up.</p>
+
+<p>For example, in our case we want to look for a regular expression match for a
+WikiWord (that is, a word with <a title="word with camel case"
+href="http://en.wikipedia.org/wiki/CamelCase">camel case &raquo;</a> and no
+spaces). Linkify can then turn this into a Content URI &mdash; something like
+<code>content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord</code>,
+which can then be used to locate the correct wiki page from a
+{@link android.content.ContentProvider}.</p>
+
+<p>As a bonus, the Linkify class also defines several default matches,
+in particular it is able to turn web URLs, email addresses and
+telephone numbers into active links which fire Android intents
+automatically.</p>
+
+<p>Linkify can be passed any TextView in your application, and will
+take care of creating the links and enabling their "clickability" for
+you.</p>
+
+<p><strong>Default Linkify</strong>: Using the set of default active
+link options is very straightforward. Simply pass it a handle to a
+TextView with content in it, and the <code>Linkify.ALL</code> flag:</p>
+
+<pre>TextView noteView = (TextView) findViewById(R.id.noteview);
+noteView.setText(someContent);
+Linkify.addLinks(noteView, Linkify.ALL);</pre>
+
+<p>and that's it. The <code>Linkify.ALL</code> flag applies all of the predefined
+link actions, and the TextView will be immediately updated with a set
+of active links which, if you select them, fire default intents for the
+actions (e.g. a web URL will start the browser with that URL, a
+telephone number will bring up the phone dialer with that number ready
+to call, etc.).</p>
+
+<p><strong>Custom Linkify</strong>: So what about our WikiWord? There is no
+pre-defined action for that, so it needs to be defined and associated with a
+scheme.</p>
+
+<p>The first task is to define a regular expression that matches the kind of
+WikiWords we want to find. The regex in this case is:</p>
+
+<pre>\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\b</pre>
+
+<p>Obvious, no? Well actually this is equivalent to the following
+description: "Starting with a word boundary (the \b) find at least one
+upper case letter, followed by at least one lower case letter or a
+numeric digit, followed by another upper case letter, and then any mix
+of upper case, lower case or numeric until the next word boundary (the
+final \b)". Regular expressions are not very pretty, but they are an
+extremely concise and accurate way of specifying a search pattern.</p>
+
+<p>We also need to tell Linkify what to do with a match to the
+WikiWord. Linkify will automatically append whatever is matched to a
+scheme that is supplied to it, so for the sake of argument let's assume
+we have a {@link android.content.ContentProvider} that matches the
+following content URI:</p>
+
+<pre>content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord</pre>
+
+<p>The WikiWord part will be appended by Linkify when it finds a match, so we
+just need the part before that as our scheme.</p>
+
+<p>Now that we have these two things, we use Linkify to connect them up:</p>
+
+<pre>Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
+String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
+Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);</pre>
+
+<p>Note that the \b's had to be escaped with double backslashes for the Java
+Pattern.compile line.</p>
+
+<p>Linkify can be used multiple times on the same view to add more
+links, so using this after the Default Linkify call means that the
+existing active links will be maintained and the new WikiWords will be
+added. You could define more Linkify actions and keep applying them to
+the same TextView if you wanted to.</p>
+
+<p>Now, if we have a WikiWord in the TextView, let's say
+<code>MyToDoList</code>, Linkify will turn it into an active link with the
+content URI:</p>
+
+<pre>content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList</pre>
+
+<p>and if you click on it, Android will fire the default intent for that content
+URI.</p>
+
+<p>For this to all work, you will need a ContentProvider that
+understands that Content URI, and you will need a default activity
+capable of doing something with the resulting data. I plan to cover
+these in future blog entries (and soon). In fact, the whole Wiki Note
+Pad application is currently undergoing some clean up and review, and
+will then hopefully be released as a sample application.</p>
diff --git a/docs/html/resources/articles/window-bg-speed.jd b/docs/html/resources/articles/window-bg-speed.jd
new file mode 100644
index 0000000..bd7a303
--- /dev/null
+++ b/docs/html/resources/articles/window-bg-speed.jd
@@ -0,0 +1,125 @@
+page.title=Window Backgrounds &amp; UI Speed
+@jd:body
+
+<p>Some Android applications require to squeeze every bit of performance out of
+the UI toolkit and there are many ways to do so. In this article, you will
+discover how to speed up the drawing and the <em>perceived</em> startup time of
+your activities. Both these techniques rely on a single feature, the window's
+background drawable.</p>
+
+<p>The term <em>window background</em> is a bit misleading, however. When you
+setup your user interface by calling <code>setContentView()</code> on an
+{@link android.app.Activity}, Android adds your views to the <code>Activity</code>'s
+window. The window however does not contain only your views, but a few others
+created for you. The most important one is, in the current implementation used
+on the T-Mobile G1, the <code>DecorView</code>, highlighted in the view
+hierarchy below:</p>
+
+<div style="text-align: center;"><img src="images/window_background_root.png" alt="A typical Android view hierarchy"></div>
+
+<p>The <code>DecorView</code> is the view that actually holds the
+window's background drawable. Calling
+{@link android.view.Window#setBackgroundDrawable(android.graphics.drawable.Drawable) getWindow().setBackgroundDrawable()}
+from your <code>Activity</code> changes the background of the window by changing
+the <code>DecorView</code>'s background drawable. As mentioned before, this
+setup is very specific to the current implementation of Android and can change
+in a future version or even on another device.</p>
+
+<p>If you are using the standard Android themes, a default background drawable
+is set on your activities. The standard theme currently used on the T-Mobile G1
+uses for instance a {@link android.graphics.drawable.ColorDrawable}. For most
+applications, this background drawable works just fine and can be left alone. It
+can however impacts your application's drawing performance. Let's take the
+example of an application that always draws a full screen opaque picture:</p>
+
+<div style="text-align: center;"><img src="images/window_background.png" alt="An opaque user interface doesn't need a window background"></div>
+
+<p>You can see on this screenshot that the window's background is invisible,
+entirely covered by an <code>ImageView</code>. This application is setup to
+redraw as fast as it can and draws at about 44 frames per second, or 22
+milliseconds per frame (<strong>note:</strong> the number of frames per second
+used in this article were obtained on a T-Mobile G1 with my finger on the screen
+so as to reduce the drawing speed which would otherwise be capped at 60 fps.) An
+easy way to make such an application draw faster is to <em>remove</em> the
+background drawable. Since the user interface is entirely opaque, drawing the
+background is simply wasteful. Removing the background improves the performance
+quite nicely:</p>
+
+<div style="text-align: center;"><img src="images/window_background_null.png" alt="Remove the background for faster drawing"></div>
+
+<p>In this new version of the application, the drawing speed went up to 51
+frames per second, or 19 milliseconds per frame. The difference of 3
+milliseconds per is easily explained by the speed of the memory bus on the
+T-Mobile G1: it is exactly the time it takes to move the equivalent of a
+screenful of pixels on the bus. The difference could be even greater if the
+default background was using a more expensive drawable.</p>
+
+<p>Removing the window's background can be achieved very easily by using
+a custom theme. To do so, first create a file called
+<code>res/values/theme.xml</code> containing the following:</p>
+
+<pre class="prettyprint">&lt;resources&gt;
+ &lt;style name="Theme.NoBackground" parent="android:Theme"&gt;
+ &lt;item name="android:windowBackground"&gt;@null&lt;/item&gt;
+ &lt;/style&gt;
+&lt;/resources&gt;</pre>
+
+<p>You then need to apply the theme to your activity by adding the attribute
+<code>android:theme="@style/Theme.NoBackground"</code> to your
+<code>&lt;activity /&gt;</code> or <code>&lt;application /&gt;</code> tag. This
+trick comes in very handy for any app that uses a <code>MapView</code>, a
+<code>WebView</code> or any other full screen opaque view.</p>
+
+<p><strong>Opaque views and Android</strong>: this optimization is currently
+necessary because the Android UI toolkit is not smart enough to prevent the
+drawing of views hidden by opaque children. The main reason why this
+optimization was not implemented is simply because there are usually very few
+opaque views in Android applications. This is however something that I
+definitely plan on implementing as soon as possible and I can only apologize for
+not having been able to do this earlier.</p><p>Using a theme to change the
+window's background is also a fantastic way to improve the <em>perceived</em>
+startup performance of some of your activities. This particular trick can only
+be applied to activities that use a custom background, like a texture or a logo.
+The <a href="http://code.google.com/p/shelves">Shelves</a> application is a good
+example:</p>
+
+<div style="text-align: center;"><img src="images/shelves2.png" alt="Textured backgrounds are good candidates for window's background"></div>
+
+<p>If this application simply set the wooden background in the XML layout or in
+<code>onCreate()</code> the user would see the application startup with the
+default theme and its dark background. The wooden texture would only appear
+after the inflation of the content view and the first layout/drawing pass. This
+causes a jarring effect and gives the user the impression that the application
+takes time to load (which can actually be the case.) Instead, the application
+defines the wooden background in a theme, picked up by the system as soon as the
+application starts. The user never sees the default theme and gets the
+impression that the application is up and running right away. To limit the
+memory and disk usage, the background is a tiled texture defined in
+<code>res/drawable/background_shelf.xml</code>:</p>
+
+<pre class="prettyprint">&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/shelf_panel"
+ android:tileMode="repeat" /&gt;</pre><p>This drawable is simply referenced by the theme:</p>
+
+<pre class="prettyprint">&lt;resources&gt;
+ &lt;style name="Theme.Shelves" parent="android:Theme"&gt;
+ &lt;item name="android:windowBackground"&gt;@drawable/background_shelf&lt;/item&gt;
+ &lt;item name="android:windowNoTitle"&gt;true&lt;/item&gt;
+ &lt;/style&gt;
+&lt;/resources&gt;</pre>
+
+<p>The same exact trick is used in the <em>Google Maps application that ships
+with the T-Mobile G1. When the application is launched, the user immediately
+sees the loading tiles of <code>MapView</code>. This is only a trick, the theme
+is simply using a tiled background that looks exactly like the loading tiles of
+<code>MapView</code>.</em></p>
+
+<p>Sometimes the best tricks are also the simplest, so the next time you create
+an activity with an opaque UI or a custom background, remember to change the
+window's background.</p>
+
+<p><a href="http://progx.org/users/Gfx/android/WindowBackground">Download the source code of the first example</a>.</p>
+
+<p><a href="http://code.google.com/p/shelves/">Download the source code of Shelves</a>.</p>
+
+
diff --git a/docs/html/resources/articles/zipalign.jd b/docs/html/resources/articles/zipalign.jd
new file mode 100644
index 0000000..013d0fe
--- /dev/null
+++ b/docs/html/resources/articles/zipalign.jd
@@ -0,0 +1,98 @@
+page.title=Zipalign: an Easy Optimization
+@jd:body
+
+<p>The Android SDK includes a tool called <a
+href="{@docRoot}guide/developing/tools/zipalign.html"><code>zipalign</code></a>
+that optimizes the way an application is packaged. Running zipalign against your
+application enables Android to interact it more efficiently at run time and thus
+has the potential to make it and the overall system run faster. We strongly
+encourage you to use <code>zipalign</code> on both new and already published
+applications and to make the optimized version available &mdash; even if your
+application targets a previous version of Android. This article describes how
+<code>zipalign</code> helps performance and how to use it to optimize your
+app.</p>
+
+<p>In Android, data files stored in each application's apk are accessed by
+multiple processes: the installer reads the manifest to handle the
+permissions associated with that application; the Home application
+reads resources to get the application's name and icon; the system
+server reads resources for a variety of reasons (e.g. to display that
+application's notifications); and last but not least, the resource
+files are obviously used by the application itself.</p>
+
+<p>The resource-handling code in Android can efficiently access resources when
+they're aligned on 4-byte boundaries by memory-mapping them. But for resources
+that are not aligned (that is, when <code>zipalign</code> hasn't been run on an
+apk), it has to fall back to explicitly reading them &mdash; which is slower and
+consumes additional memory.</p>
+
+<p>For an application developer, this fallback mechanism is very
+convenient. It provides a lot of flexibility by allowing for several
+different development methods, including those that don't include
+aligning resources as part of their normal flow.</p>
+
+<p>Unfortunately, for users the situation is reversed &mdash; reading resources
+from unaligned apks is slow and takes a lot of memory. In the best case, the
+only visible result is that both the Home application and the unaligned
+application launch slower than they otherwise should. In the worst case,
+installing several applications with unaligned resources increases memory
+pressure, thus causing the system to thrash around by having to constantly start
+and kill processes. The user ends up with a slow device with a poor battery
+life.</p>
+
+<p>Luckily, it's very easy for you to align the resources in your application:</p>
+
+<ul>
+<li>Using ADT:</li>
+<li style="list-style-type: none; list-style-image: none; list-style-position: outside;">
+<ul>
+<li>The ADT plugin for Eclipse (starting from version 0.9.3) will automatically
+align release application packages if the export wizard is used to create them.
+To use the wizard, right click the project and choose "Android Tools" &gt;
+"Export Signed Application Package..." It can also be accessed from the first
+page of the <code>AndroidManifest.xml</code> editor.</li>
+</ul>
+</li>
+<li>Using Ant:</li><li style="list-style-type: none; list-style-image: none; list-style-position: outside;">
+
+<ul>
+<li>The <em>Ant</em> build script (starting from Android 1.6) can align
+application packages. Targets for older versions of the Android platform are not
+aligned by the <em>Ant</em> build script and need to be manually aligned.</li>
+<li>Starting from the Android 1.6 SDK, Ant aligns and signs packages automatically,
+when building in debug mode.</li>
+<li>In release mode, Ant aligns packages only if it has enough
+information to sign the packages, since aligning has to happen after signing. In
+order to be able to sign packages, and therefore to align them, <em>Ant</em>
+needs to know the location of the keystore and the name of the key in
+<code>build.properties</code>. The name of the properties are
+<code>key.store</code> and <code>key.alias</code> respectively. If those
+properties are present, the signing tool will prompt to enter the store/key
+passwords during the build, and the script will sign and then align the apk
+file. If the properties are missing, the release package will not be signed, and
+therefore will not get aligned either.</li>
+</ul>
+</li>
+<li>Manually:</li>
+<li style="list-style-type: none; list-style-image: none; list-style-position: outside;">
+<ul>
+<li>In order to manually align a package, <code>zipalign</code>
+is in the <code>tools/</code> folder of Android 1.6 and later SDKs. You can use
+it to align application packages targeting any version of Android. You should run
+it only after signing the apk file, using the following command:
+<br><code>zipalign -v 4 source.apk destination.apk</code></li>
+</ul>
+</li>
+<li>Verifying alignment:</li>
+<li style="list-style-type: none; list-style-image: none; list-style-position: outside;">
+<ul>
+<li>The following command verifies that a package is aligned:<br><code>zipalign -c -v 4 application.apk</code>
+</li>
+</ul>
+</li>
+</ul>
+
+<p>We encourage you manually run <code>zipalign</code>
+on your currently published applications and to make the newly aligned
+versions available to users. Also, don't forget to align any new
+applications going forward!</p>