summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/practices
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/guide/practices')
-rw-r--r--docs/html/guide/practices/design/jni.jd711
-rw-r--r--docs/html/guide/practices/design/performance.jd3
-rw-r--r--docs/html/guide/practices/screen-compat-mode.jd257
-rw-r--r--docs/html/guide/practices/screens-distribution.jd30
-rw-r--r--docs/html/guide/practices/screens-support-1.5.jd47
-rw-r--r--docs/html/guide/practices/screens_support.jd395
6 files changed, 1384 insertions, 59 deletions
diff --git a/docs/html/guide/practices/design/jni.jd b/docs/html/guide/practices/design/jni.jd
new file mode 100644
index 0000000..1d0e26e
--- /dev/null
+++ b/docs/html/guide/practices/design/jni.jd
@@ -0,0 +1,711 @@
+page.title=JNI Tips
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+ <li><a href="#JavaVM_and_JNIEnv">JavaVM and JNIEnv</a></li>
+ <li><a href="#threads">Threads</a></li>
+ <li><a href="#jclass_jmethodID_and_jfieldID">jclass, jmethodID, and jfieldID</a></li>
+ <li><a href="#local_and_global_references">Local and Global References</a></li>
+ <li><a href="#UTF_8_and_UTF_16_strings">UTF-8 and UTF-16 Strings</a></li>
+ <li><a href="#arrays">Primitive Arrays</a></li>
+ <li><a href="#region_calls">Region Calls</a></li>
+ <li><a href="#exceptions">Exceptions</a></li>
+ <li><a href="#extended_checking">Extended Checking</a> </li>
+ <li><a href="#native_libraries">Native Libraries</a></li>
+ <li><a href="#64_bit">64-bit Considerations</a></li>
+ <li><a href="#unsupported">Unsupported Features</a></li>
+ <li><a href="#faq_ULE">FAQ: UnsatisfiedLinkError</a></li>
+ <li><a href="#faq_FindClass">FAQ: FindClass didn't find my class</a></li>
+ <li><a href="#faq_sharing">FAQ: Sharing raw data with native code</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>JNI is the Java Native Interface. It defines a way for code written in the
+Java programming language to interact with native
+code, e.g. functions written in C/C++. It's VM-neutral, has support for loading code from
+dynamic shared libraries, and while cumbersome at times is reasonably efficient.</p>
+
+<p>You really should read through the
+<a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html">JNI spec for J2SE 6</a>
+to get a sense for how JNI works and what features are available. Some
+aspects of the interface aren't immediately obvious on
+first reading, so you may find the next few sections handy.
+The more detailed <i>JNI Programmer's Guide and Specification</i> can be found
+<a href="http://java.sun.com/docs/books/jni/html/jniTOC.html">here</a>.</p>
+
+
+<a name="JavaVM_and_JNIEnv" id="JavaVM_and_JNIEnv"></a>
+<h2>JavaVM and JNIEnv</h2>
+
+<p>JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially
+pointers to pointers to function tables. (In the C++ version, they're classes with a
+pointer to a function table and a member function for each JNI function that indirects through
+the table.) The JavaVM provides the "invocation interface" functions,
+which allow you to create and destroy the VM. In theory you can have multiple VMs per process,
+but Android's VM only allows one.</p>
+
+<p>The JNIEnv provides most of the JNI functions. Your native functions all receive a JNIEnv as
+the first argument.</p>
+
+<p>On some VMs, the JNIEnv is used for thread-local storage. For this reason, <strong>you cannot share a JNIEnv between threads</strong>.
+If a piece of code has no other way to get its JNIEnv, you should share
+the JavaVM, and use JavaVM-&gt;GetEnv to discover the thread's JNIEnv. (Assuming it has one; see <code>AttachCurrentThread</code> below.)</p>
+
+<p>The C declarations of JNIEnv and JavaVM are different from the C++
+declarations. "jni.h" provides different typedefs
+depending on whether it's included into ".c" or ".cpp". For this reason it's a bad idea to
+include JNIEnv arguments in header files included by both languages. (Put another way: if your
+header file requires "#ifdef __cplusplus", you may have to do some extra work if anything in
+that header refers to JNIEnv.)</p>
+
+<a name="threads" id="threads"></a>
+<h2>Threads</h2>
+
+<p>All VM threads are Linux threads, scheduled by the kernel. They're usually
+started using Java language features (notably <code>Thread.start()</code>),
+but they can also be created elsewhere and then attached to the VM. For
+example, a thread started with <code>pthread_create</code> can be attached
+with the JNI <code>AttachCurrentThread</code> or
+<code>AttachCurrentThreadAsDaemon</code> functions. Until a thread is
+attached to the VM, it has no JNIEnv, and
+<strong>cannot make JNI calls</strong>.</p>
+
+<p>Attaching a natively-created thread causes the VM to allocate and initialize
+a <code>Thread</code> object, add it to the "main" <code>ThreadGroup</code>,
+and add the thread to the set that is visible to the debugger. Calling
+<code>AttachCurrentThread</code> on an already-attached thread is a no-op.</p>
+
+<p>The Dalvik VM does not suspend threads executing native code. If
+garbage collection is in progress, or the debugger has issued a suspend
+request, the VM will pause the thread the next time it makes a JNI call.</p>
+
+<p>Threads attached through JNI <strong>must call
+<code>DetachCurrentThread</code> before they exit</strong>.
+If coding this directly is awkward, in Android &gt;= 2.0 ("Eclair") you
+can use <code>pthread_key_create</code> to define a destructor
+function that will be called before the thread exits, and
+call <code>DetachCurrentThread</code> from there. (Use that
+key with <code>pthread_setspecific</code> to store the JNIEnv in
+thread-local-storage; that way it'll be passed into your destructor as
+the argument.)</p>
+
+
+<a name="jclass_jmethodID_and_jfieldID" id="jclass_jmethodID_and_jfieldID"></a>
+<h2>jclass, jmethodID, and jfieldID</h2>
+
+<p>If you want to access an object's field from native code, you would do the following:</p>
+
+<ul>
+<li> Get the class object reference for the class with <code>FindClass</code></li>
+<li> Get the field ID for the field with <code>GetFieldID</code></li>
+<li> Get the contents of the field with something appropriate, e.g.
+<code>GetIntField</code></li>
+</ul>
+
+<p>Similarly, to call a method, you'd first get a class object reference and then a method ID. The IDs are often just
+pointers to internal VM data structures. Looking them up may require several string
+comparisons, but once you have them the actual call to get the field or invoke the method
+is very quick.</p>
+
+<p>If performance is important, it's useful to look the values up once and cache the results
+in your native code. Because we are limiting ourselves to one VM per process, it's reasonable
+to store this data in a static local structure.</p>
+
+<p>The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded. Classes
+are only unloaded if all classes associated with a ClassLoader can be garbage collected,
+which is rare but will not be impossible in our system. Note however that
+the <code>jclass</code>
+is a class reference and <strong>must be protected</strong> with a call
+to <code>NewGlobalRef</code> (see the next section).</p>
+
+<p>If you would like to cache the IDs when a class is loaded, and automatically re-cache them
+if the class is ever unloaded and reloaded, the correct way to initialize
+the IDs is to add a piece of code that looks like this to the appropriate class:</p>
+
+<pre> /*
+ * We use a class initializer to allow the native code to cache some
+ * field offsets.
+ */
+
+ /*
+ * A native function that looks up and caches interesting
+ * class/field/method IDs for this class. Returns false on failure.
+ */
+ native private static boolean nativeClassInit();
+
+ /*
+ * Invoke the native initializer when the class is loaded.
+ */
+ static {
+ if (!nativeClassInit())
+ throw new RuntimeException("native init failed");
+ }</pre>
+
+<p>Create a nativeClassInit method in your C/C++ code that performs the ID lookups. The code
+will be executed once, when the class is initialized. If the class is ever unloaded and
+then reloaded, it will be executed again. (See the implementation of java.io.FileDescriptor
+for an example in our source tree.)</p>
+
+<a name="local_and_global_references" id="local_and_global_references"></a>
+<h2>Local and Global References</h2>
+
+<p>Every object that JNI returns is a "local reference". This means that it's valid for the
+duration of the current native method in the current thread.
+<strong>Even if the object itself continues to live on after the native method returns, the reference is not valid.</strong>
+This applies to all sub-classes of <code>jobject</code>, including
+<code>jclass</code>, <code>jstring</code>, and <code>jarray</code>.
+(Dalvik VM will warn you about most reference mis-uses when extended JNI
+checks are enabled.)</p>
+
+<p>If you want to hold on to a reference for a longer period, you must use
+a "global" reference. The <code>NewGlobalRef</code> function takes the
+local reference as an argument and returns a global one.
+The global reference is guaranteed to be valid until you call
+<code>DeleteGlobalRef</code>.</p>
+
+<p>This pattern is commonly used when caching copies of class objects obtained
+from <code>FindClass</code>, e.g.:</p>
+<pre>jclass localClass = env-&gt;FindClass("MyClass");
+jclass globalClass = reinterpret_cast&lt;jclass&gt;(env-&gt;NewGlobalRef(localClass));</pre>
+
+<p>All JNI methods accept both local and global references as arguments.
+It's possible for references to the same object to have different values;
+for example, the return values from consecutive calls to
+<code>NewGlobalRef</code> on the same object may be different.
+<strong>To see if two references refer to the same object,
+you must use the <code>IsSameObject</code> function.</strong> Never compare
+references with "==" in native code.</p>
+
+<p>One consequence of this is that you
+<strong>must not assume object references are constant or unique</strong>
+in native code. The 32-bit value representing an object may be different
+from one invocation of a method to the next, and it's possible that two
+different objects could have the same 32-bit value on consecutive calls. Do
+not use <code>jobject</code> values as keys.</p>
+
+<p>Programmers are required to "not excessively allocate" local references. In practical terms this means
+that if you're creating large numbers of local references, perhaps while running through an array of
+Objects, you should free them manually with
+<code>DeleteLocalRef</code> instead of letting JNI do it for you. The
+VM is only required to reserve slots for
+16 local references, so if you need more than that you should either delete as you go or use
+<code>EnsureLocalCapacity</code> to reserve more.</p>
+
+<p>Note: method and field IDs are just 32-bit identifiers, not object
+references, and should not be passed to <code>NewGlobalRef</code>. The raw data
+pointers returned by functions like <code>GetStringUTFChars</code>
+and <code>GetByteArrayElements</code> are also not objects.</p>
+
+<p>One unusual case deserves separate mention. If you attach a native
+thread to the VM with AttachCurrentThread, the code you are running will
+never "return" to the VM until the thread detaches from the VM. Any local
+references you create will have to be deleted manually unless you're going
+to detach the thread soon.</p>
+
+<a name="UTF_8_and_UTF_16_strings" id="UTF_8_and_UTF_16_strings"></a>
+<h2>UTF-8 and UTF-16 Strings</h2>
+
+<p>The Java programming language uses UTF-16. For convenience, JNI provides methods that work with <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> as well. The
+modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00.
+The nice thing about this is that you can count on having C-style zero-terminated strings,
+suitable for use with standard libc string functions. The down side is that you cannot pass
+arbitrary UTF-8 data into the VM and expect it to work correctly.</p>
+
+<p>It's usually best to operate with UTF-16 strings. With our current VMs, the
+<code>GetStringChars</code> method
+does not require a copy, whereas <code>GetStringUTFChars</code> requires a malloc and a UTF conversion. Note that
+<strong>UTF-16 strings are not zero-terminated</strong>, and \u0000 is allowed,
+so you need to hang on to the string length as well as
+the string pointer.</p>
+
+<p><strong>Don't forget to Release the strings you Get</strong>. The
+string functions return <code>jchar*</code> or <code>jbyte*</code>, which
+are C-style pointers to primitive data rather than local references. They
+are guaranteed valid until Release is called, which means they are not
+released when the native method returns.</p>
+
+<p><strong>Data passed to NewStringUTF must be in Modified UTF-8 format</strong>. A
+common mistake is reading character data from a file or network stream
+and handing it to <code>NewStringUTF</code> without filtering it.
+Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII
+characters or convert them to proper Modified UTF-8 form. If you don't,
+the UTF-16 conversion will likely not be what you expect. The extended
+JNI checks will scan strings and warn you about invalid data, but they
+won't catch everything.</p>
+
+<a name="arrays" id="arrays"></a>
+<h2>Primitive Arrays</h2>
+
+<p>JNI provides functions for accessing the contents of array objects.
+While arrays of objects must be accessed one entry at a time, arrays of
+primitives can be read and written directly as if they were declared in C.</p>
+
+<p>To make the interface as efficient as possible without constraining
+the VM implementation,
+the <code>Get&lt;PrimitiveType&gt;ArrayElements</code> family of calls
+allows the VM to either return a pointer to the actual elements, or
+allocate some memory and make a copy. Either way, the raw pointer returned
+is guaranteed to be valid until the corresponding <code>Release</code> call
+is issued (which implies that, if the data wasn't copied, the array object
+will be pinned down and can't be relocated as part of compacting the heap).
+<strong>You must Release every array you Get.</strong> Also, if the Get
+call fails, you must ensure that your code doesn't try to Release a NULL
+pointer later.</p>
+
+<p>You can determine whether or not the data was copied by passing in a
+non-NULL pointer for the <code>isCopy</code> argument. This is rarely
+useful.</p>
+
+<p>The <code>Release</code> call takes a <code>mode</code> argument that can
+have one of three values. The actions performed by the VM depend upon
+whether it returned a pointer to the actual data or a copy of it:</p>
+
+<ul>
+ <li><code>0</code>
+ <ul>
+ <li>Actual: the array object is un-pinned.
+ <li>Copy: data is copied back. The buffer with the copy is freed.
+ </ul>
+ <li><code>JNI_COMMIT</code>
+ <ul>
+ <li>Actual: does nothing.
+ <li>Copy: data is copied back. The buffer with the copy
+ <strong>is not freed</strong>.
+ </ul>
+ <li><code>JNI_ABORT</code>
+ <ul>
+ <li>Actual: the array object is un-pinned. Earlier
+ writes are <strong>not</strong> aborted.
+ <li>Copy: the buffer with the copy is freed; any changes to it are lost.
+ </ul>
+</ul>
+
+<p>One reason for checking the <code>isCopy</code> flag is to know if
+you need to call <code>Release</code> with <code>JNI_COMMIT</code>
+after making changes to an array &mdash; if you're alternating between making
+changes and executing code that uses the contents of the array, you may be
+able to
+skip the no-op commit. Another possible reason for checking the flag is for
+efficient handling of <code>JNI_ABORT</code>. For example, you might want
+to get an array, modify it in place, pass pieces to other functions, and
+then discard the changes. If you know that JNI is making a new copy for
+you, there's no need to create another "editable" copy. If JNI is passing
+you the original, then you do need to make your own copy.</p>
+
+<p>Some have asserted that you can skip the <code>Release</code> call if
+<code>*isCopy</code> is false. This is not the case. If no copy buffer was
+allocated, then the original memory must be pinned down and can't be moved by
+the garbage collector.</p>
+
+<p>Also note that the <code>JNI_COMMIT</code> flag does NOT release the array,
+and you will need to call <code>Release</code> again with a different flag
+eventually.</p>
+
+
+<a name="region_calls" id="region_calls"></a>
+<h2>Region Calls</h2>
+
+<p>There is an alternative to calls like <code>Get&lt;Type&gt;ArrayElements</code>
+and <code>GetStringChars</code> that may be very helpful when all you want
+to do is copy data in or out. Consider the following:</p>
+
+<pre>
+ jbyte* data = env-&gt;GetByteArrayElements(array, NULL);
+ if (data != NULL) {
+ memcpy(buffer, data, len);
+ env-&gt;ReleaseByteArrayElements(array, data, JNI_ABORT);
+ }</pre>
+
+<p>This grabs the array, copies the first <code>len</code> byte
+elements out of it, and then releases the array. Depending upon the VM
+policies the <code>Get</code> call will either pin or copy the array contents.
+We copy the data (for perhaps a second time), then call Release; in this case
+we use <code>JNI_ABORT</code> so there's no chance of a third copy.</p>
+
+<p>We can accomplish the same thing with this:</p>
+<pre>
+ env-&gt;GetByteArrayRegion(array, 0, len, buffer);</pre>
+
+<p>This has several advantages:</p>
+<ul>
+ <li>Requires one JNI call instead of 2, reducing overhead.
+ <li>Doesn't require pinning or extra data copies.
+ <li>Reduces the risk of programmer error &mdash; no risk of forgetting
+ to call <code>Release</code> after something fails.
+</ul>
+
+<p>Similarly, you can use the <code>Set&lt;Type&gt;ArrayRegion</code> call
+to copy data into an array, and <code>GetStringRegion</code> or
+<code>GetStringUTFRegion</code> to copy characters out of a
+<code>String</code>.
+
+
+<a name="exceptions" id="exceptions"></a>
+<h2>Exception</h2>
+
+<p><strong>You may not call most JNI functions while an exception is pending.</strong>
+Your code is expected to notice the exception (via the function's return value,
+<code>ExceptionCheck()</code>, or <code>ExceptionOccurred()</code>) and return,
+or clear the exception and handle it.</p>
+
+<p>The only JNI functions that you are allowed to call while an exception is
+pending are:</p>
+<ul>
+ <li>DeleteGlobalRef
+ <li>DeleteLocalRef
+ <li>DeleteWeakGlobalRef
+ <li>ExceptionCheck
+ <li>ExceptionClear
+ <li>ExceptionDescribe
+ <li>ExceptionOccurred
+ <li>MonitorExit
+ <li>PopLocalFrame
+ <li>PushLocalFrame
+ <li>Release&lt;PrimitiveType&gt;ArrayElements
+ <li>ReleasePrimitiveArrayCritical
+ <li>ReleaseStringChars
+ <li>ReleaseStringCritical
+ <li>ReleaseStringUTFChars
+</ul>
+
+<p>Many JNI calls can throw an exception, but often provide a simpler way
+of checking for failure. For example, if <code>NewString</code> returns
+a non-NULL value, you don't need to check for an exception. However, if
+you call a method (using a function like <code>CallObjectMethod</code>),
+you must always check for an exception, because the return value is not
+going to be valid if an exception was thrown.</p>
+
+<p>Note that exceptions thrown by interpreted code do not "leap over" native code,
+and C++ exceptions thrown by native code are not handled by Dalvik.
+The JNI <code>Throw</code> and <code>ThrowNew</code> instructions just
+set an exception pointer in the current thread. Upon returning to the VM from
+native code, the exception will be noted and handled appropriately.</p>
+
+<p>Native code can "catch" an exception by calling <code>ExceptionCheck</code> or
+<code>ExceptionOccurred</code>, and clear it with
+<code>ExceptionClear</code>. As usual,
+discarding exceptions without handling them can lead to problems.</p>
+
+<p>There are no built-in functions for manipulating the Throwable object
+itself, so if you want to (say) get the exception string you will need to
+find the Throwable class, look up the method ID for
+<code>getMessage "()Ljava/lang/String;"</code>, invoke it, and if the result
+is non-NULL use <code>GetStringUTFChars</code> to get something you can
+hand to printf or a LOG macro.</p>
+
+
+<a name="extended_checking" id="extended_checking"></a>
+<h2>Extended Checking</h2>
+
+<p>JNI does very little error checking. Calling <code>SetIntField</code>
+on an Object field will succeed, even if the field is marked
+<code>private</code> and <code>final</code>. The
+goal is to minimize the overhead on the assumption that, if you've written it in native code,
+you probably did it for performance reasons.</p>
+
+<p>In Dalvik, you can enable additional checks by setting the
+"<code>-Xcheck:jni</code>" flag. If the flag is set, the VM directs
+the JavaVM and JNIEnv pointers to a different table of functions.
+These functions perform an extended series of checks before calling the
+standard implementation.</p>
+
+<p>The additional tests include:</p>
+
+<ul>
+<li> Check for null pointers where not allowed.</li>
+<li> Verify argument type correctness (jclass is a class object,
+jfieldID points to field data, jstring is a java.lang.String).</li>
+<li> Field type correctness, e.g. don't store a HashMap in a String field.</li>
+<li> Ensure jmethodID is appropriate when making a static or virtual
+method call.</li>
+<li> Check to see if an exception is pending on calls where pending exceptions are not legal.</li>
+<li> Check for calls to inappropriate functions between Critical get/release calls.</li>
+<li> Check that JNIEnv structs aren't being shared between threads.</li>
+<li> Make sure local references aren't used outside their allowed lifespan.</li>
+<li> UTF-8 strings contain only valid <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> data.</li>
+</ul>
+
+<p>Accessibility of methods and fields (i.e. public vs. private) is not
+checked.</p>
+
+<p>For a description of how to enable CheckJNI for Android apps, see
+<a href="embedded-vm-control.html">Controlling the Embedded VM</a>.
+It's currently enabled by default in the Android emulator and on
+"engineering" device builds.</p>
+
+<p>JNI checks can be modified with the <code>-Xjniopts</code> command-line
+flag. Currently supported values include:</p>
+
+<dl>
+<dt>forcecopy
+<dd>When set, any function that can return a copy of the original data
+(array of primitive values, UTF-16 chars) will always do so. The buffers
+are over-allocated and surrounded with a guard pattern to help identify
+code writing outside the buffer, and the contents are erased before the
+storage is freed to trip up code that uses the data after calling Release.
+This will have a noticeable performance impact on some applications.
+<dt>warnonly
+<dd>By default, JNI "warnings" cause the VM to abort. With this flag
+it continues on.
+</dl>
+
+
+<a name="native_libraries" id="native_libraries"></a>
+<h2>Native Libraries</h2>
+
+<p>You can load native code from shared libraries with the standard
+<code>System.loadLibrary()</code> call. The
+preferred way to get at your native code is:</p>
+
+<ul>
+<li> Call <code>System.loadLibrary()</code> from a static class
+initializer. (See the earlier example, where one is used to call
+<code>nativeClassInit()</code>.) The argument is the "undecorated"
+library name, e.g. to load "libfubar.so" you would pass in "fubar".</li>
+<li> Provide a native function: <code><strong>jint JNI_OnLoad(JavaVM* vm, void* reserved)</strong></code></li>
+<li>In <code>JNI_OnLoad</code>, register all of your native methods. You
+should declare
+the functions <code>static</code> so the names don't take up space in the symbol table
+on the device.</li>
+</ul>
+
+<p>The <code>JNI_OnLoad</code> function should look something like this if
+written in C++:</p>
+<pre>jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ JNIEnv* env;
+ if (vm-&gt;GetEnv(reinterpret_cast&lt;void**&gt;(&env), JNI_VERSION_1_6) != JNI_OK) {
+ return -1;
+ }
+
+ // Get jclass with env-&gt;FindClass.
+ // Register methods with env-&gt;RegisterNatives.
+
+ return JNI_VERSION_1_6;
+}</pre>
+
+<p>You can also call <code>System.load()</code> with the full path name of the
+shared library. For Android apps, you may find it useful to get the full
+path to the application's private data storage area from the context object.</p>
+
+<p>This is the recommended approach, but not the only approach. The VM does
+not require explicit registration, nor that you provide a
+<code>JNI_OnLoad</code> function.
+You can instead use "discovery" of native methods that are named in a
+specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615">
+ the JNI spec</a> for details), though this is less desirable.
+It requires more space in the shared object symbol table,
+loading is slower because it requires string searches through all of the
+loaded shared libraries, and if a method signature is wrong you won't know
+about it until the first time the method is actually used.</p>
+
+<p>One other note about <code>JNI_OnLoad</code>: any <code>FindClass</code>
+calls you make from there will happen in the context of the class loader
+that was used to load the shared library. Normally <code>FindClass</code>
+uses the loader associated with the method at the top of the interpreted
+stack, or if there isn't one (because the thread was just attached to
+the VM) it uses the "system" class loader. This makes
+<code>JNI_OnLoad</code> a convenient place to look up and cache class
+object references.</p>
+
+
+<a name="64_bit" id="64_bit"></a>
+<h2>64-bit Considerations</h2>
+
+<p>Android is currently expected to run on 32-bit platforms. In theory it
+could be built for a 64-bit system, but that is not a goal at this time.
+For the most part this isn't something that you will need to worry about
+when interacting with native code,
+but it becomes significant if you plan to store pointers to native
+structures in integer fields in an object. To support architectures
+that use 64-bit pointers, <strong>you need to stash your native pointers in a
+<code>long</code> field rather than an <code>int</code></strong>.
+
+
+<a name="unsupported" id="unsupported"></a>
+<h2>Unsupported Features</h2>
+
+<p>All JNI 1.6 features are supported, with the following exceptions:</p>
+<ul>
+ <li><code>DefineClass</code> is not implemented. Dalvik does not use
+ Java bytecodes or class files, so passing in binary class data
+ doesn't work. Translation facilities may be added in a future
+ version of the VM.</li>
+ <li>"Weak global" references are implemented, but may only be passed
+ to <code>NewLocalRef</code>, <code>NewGlobalRef</code>, and
+ <code>DeleteWeakGlobalRef</code>. (The spec strongly encourages
+ programmers to create hard references to weak globals before doing
+ anything with them, so this should not be at all limiting.)</li>
+ <li><code>GetObjectRefType</code> (new in JNI 1.6) is implemented but not fully
+ functional &mdash; it can't always tell the difference between "local" and
+ "global" references.</li>
+</ul>
+
+<p>For backward compatibility, you may need to be aware of:</p>
+<ul>
+ <li>Until Android 2.0 ("Eclair"), the '$' character was not properly
+ converted to "_00024" during searches for method names. Working
+ around this requires using explicit registration or moving the
+ native methods out of inner classes.
+ <li>Until Android 2.0 ("Eclair"), it was not possible to use a <code>pthread_key_create</code>
+ destructor function to avoid the VM's "thread must be detached before
+ exit" check. (The VM also uses a pthread key destructor function,
+ so it'd be a race to see which gets called first.)
+ <li>"Weak global" references were not implemented until Android 2.2 ("Froyo").
+ Older VMs will vigorously reject attempts to use them. You can use
+ the Android platform version constants to test for support.
+</ul>
+
+
+<a name="faq_ULE" id="faq_ULE"></a>
+<h2>FAQ: UnsatisfiedLinkError</h2>
+
+<p>When working on native code it's not uncommon to see a failure like this:</p>
+<pre>java.lang.UnsatisfiedLinkError: Library foo not found</pre>
+
+<p>In some cases it means what it says &mdash; the library wasn't found. In
+other cases the library exists but couldn't be opened by dlopen(), and
+the details of the failure can be found in the exception's detail message.</p>
+
+<p>Common reasons why you might encounter "library not found" exceptions:</p>
+<ul>
+ <li>The library doesn't exist or isn't accessible to the app. Use
+ <code>adb shell ls -l &lt;path&gt;</code> to check its presence
+ and permissions.
+ <li>The library wasn't built with the NDK. This can result in
+ dependencies on functions or libraries that don't exist on the device.
+</ul>
+
+<p>Another class of <code>UnsatisfiedLinkError</code> failures looks like:</p>
+<pre>java.lang.UnsatisfiedLinkError: myfunc
+ at Foo.myfunc(Native Method)
+ at Foo.main(Foo.java:10)</pre>
+
+<p>In logcat, you'll see:</p>
+<pre>W/dalvikvm( 880): No implementation found for native LFoo;.myfunc ()V</pre>
+
+<p>This means that the VM tried to find a matching method but was unsuccessful.
+Some common reasons for this are:</p>
+<ul>
+ <li>The library isn't getting loaded. Check the logcat output for
+ messages about library loading.
+ <li>The method isn't being found due to a name or signature mismatch. This
+ is commonly caused by:
+ <ul>
+ <li>For lazy method lookup, failing to declare C++ functions
+ with <code>extern "C"</code>. You can use <code>arm-eabi-nm</code>
+ to see the symbols as they appear in the library; if they look
+ mangled (e.g. <code>_Z15Java_Foo_myfuncP7_JNIEnvP7_jclass</code>
+ rather than <code>Java_Foo_myfunc</code>) then you need to
+ adjust the declaration.
+ <li>For explicit registration, minor errors when entering the
+ method signature. Make sure that what you're passing to the
+ registration call matches the signature in the log file.
+ Remember that 'B' is <code>byte</code> and 'Z' is <code>boolean</code>.
+ Class name components in signatures start with 'L', end with ';',
+ use '/' to separate package/class names, and use '$' to separate
+ inner-class names
+ (e.g. <code>Ljava/util/Map$Entry;</code>).
+ </ul>
+</ul>
+
+<p>Using <code>javah</code> to automatically generate JNI headers may help
+avoid some problems.
+
+
+<a name="faq_FindClass" id="faq_FindClass"></a>
+<h2>FAQ: FindClass didn't find my class</h2>
+
+<p>Make sure that the class name string has the correct format. JNI class
+names start with the package name and are separated with slashes,
+e.g. <code>java/lang/String</code>. If you're looking up an array class,
+you need to start with the appropriate number of square brackets and
+must also wrap the class with 'L' and ';', so a one-dimensional array of
+<code>String</code> would be <code>[Ljava/lang/String;</code>.</p>
+
+<p>If the class name looks right, you could be running into a class loader
+issue. <code>FindClass</code> wants to start the class search in the
+class loader associated with your code. It examines the VM call stack,
+which will look something like:
+<pre> Foo.myfunc(Native Method)
+ Foo.main(Foo.java:10)
+ dalvik.system.NativeStart.main(Native Method)</pre>
+
+<p>The topmost method is <code>Foo.myfunc</code>. <code>FindClass</code>
+finds the <code>ClassLoader</code> object associated with the <code>Foo</code>
+class and uses that.</p>
+
+<p>This usually does what you want. You can get into trouble if you
+create a thread outside the VM (perhaps by calling <code>pthread_create</code>
+and then attaching it to the VM with <code>AttachCurrentThread</code>).
+Now the stack trace looks like this:</p>
+<pre> dalvik.system.NativeStart.run(Native Method)</pre>
+
+<p>The topmost method is <code>NativeStart.run</code>, which isn't part of
+your application. If you call <code>FindClass</code> from this thread, the
+VM will start in the "system" class loader instead of the one associated
+with your application, so attempts to find app-specific classes will fail.</p>
+
+<p>There are a few ways to work around this:</p>
+<ul>
+ <li>Do your <code>FindClass</code> lookups once, in
+ <code>JNI_OnLoad</code>, and cache the class references for later
+ use. Any <code>FindClass</code> calls made as part of executing
+ <code>JNI_OnLoad</code> will use the class loader associated with
+ the function that called <code>System.loadLibrary</code> (this is a
+ special rule, provided to make library initialization more convenient).
+ If your app code is loading the library, <code>FindClass</code>
+ will use the correct class loader.
+ <li>Pass an instance of the class into the functions that need
+ it, e.g. declare your native method to take a Class argument and
+ then pass <code>Foo.class</code> in.
+ <li>Cache a reference to the <code>ClassLoader</code> object somewhere
+ handy, and issue <code>loadClass</code> calls directly. This requires
+ some effort.
+</ul>
+
+
+<a name="faq_sharing" id="faq_sharing"></a>
+<h2>FAQ: Sharing raw data with native code</h2>
+
+<p>You may find yourself in a situation where you need to access a large
+buffer of raw data from code written in Java and C/C++. Common examples
+include manipulation of bitmaps or sound samples. There are two
+basic approaches.</p>
+
+<p>You can store the data in a <code>byte[]</code>. This allows very fast
+access from code written in Java. On the native side, however, you're
+not guaranteed to be able to access the data without having to copy it. In
+some implementations, <code>GetByteArrayElements</code> and
+<code>GetPrimitiveArrayCritical</code> will return actual pointers to the
+raw data in the managed heap, but in others it will allocate a buffer
+on the native heap and copy the data over.</p>
+
+<p>The alternative is to store the data in a direct byte buffer. These
+can be created with <code>java.nio.ByteBuffer.allocateDirect</code>, or
+the JNI <code>NewDirectByteBuffer</code> function. Unlike regular
+byte buffers, the storage is not allocated on the managed heap, and can
+always be accessed directly from native code (get the address
+with <code>GetDirectBufferAddress</code>). Depending on how direct
+byte buffer access is implemented in the VM, accessing the data from code
+written in Java can be very slow.</p>
+
+<p>The choice of which to use depends on two factors:</p>
+<ol>
+ <li>Will most of the data accesses happen from code written in Java
+ or in C/C++?
+ <li>If the data is eventually being passed to a system API, what form
+ must it be in? (For example, if the data is eventually passed to a
+ function that takes a byte[], doing processing in a direct
+ <code>ByteBuffer</code> might be unwise.)
+</ol>
+
+<p>If there's no clear winner, use a direct byte buffer. Support for them
+is built directly into JNI, and access to them from code written in
+Java can be made faster with VM improvements.</p>
diff --git a/docs/html/guide/practices/design/performance.jd b/docs/html/guide/practices/design/performance.jd
index fe69d7d..c41f971 100644
--- a/docs/html/guide/practices/design/performance.jd
+++ b/docs/html/guide/practices/design/performance.jd
@@ -375,6 +375,9 @@ code compiled for the ARM in the Nexus One won't run on the ARM in the G1.</p>
<p>Native code is primarily useful when you have an existing native codebase
that you want to port to Android, not for "speeding up" parts of a Java app.</p>
+<p>If you do need to use native code, you should read our
+<a href="{@docRoot}guide/practices/design/jni.html">JNI Tips</a>.</p>
+
<p>(See also <em>Effective Java</em> item 54.)</p>
<a name="closing_notes" id="closing_notes"></a>
diff --git a/docs/html/guide/practices/screen-compat-mode.jd b/docs/html/guide/practices/screen-compat-mode.jd
new file mode 100644
index 0000000..a792386
--- /dev/null
+++ b/docs/html/guide/practices/screen-compat-mode.jd
@@ -0,0 +1,257 @@
+page.title=Screen Compatibility Mode
+parent.title=Supporting Multiple Screens
+parent.link=screens_support.html
+
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+ <li><a href="#Disable">Disabling Screen Compatibility Mode</a></li>
+ <li><a href="#Enable">Enabling Screen Compatibility Mode</a></li>
+</ol>
+<h2>See also</h2>
+<ol>
+ <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+ <li><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a></li>
+</ol>
+</div>
+</div>
+
+<div class="figure" style="width:500px;">
+<a href="{@docRoot}images/screens_support/compat-zoom.png">
+<img src="{@docRoot}images/screens_support/compat-zoom-thumb.png" alt="" />
+</a>
+<p class="img-caption"><strong>Figure 1.</strong> An application running in compatibility mode
+on an Android 3.2 tablet.</p>
+</div>
+
+<div class="figure" style="width:500px;">
+<a href="{@docRoot}images/screens_support/compat-stretch.png">
+<img src="{@docRoot}images/screens_support/compat-stretch-thumb.png" alt="" />
+</a>
+<p class="img-caption"><strong>Figure 2.</strong> The same application from figure 1, with
+compatibility mode disabled.</p>
+</div>
+
+<p class="caution"><strong>Notice:</strong> If you've developed an application for a version of
+Android lower than Android 3.0, but it does resize properly for larger screens such as tablets, you
+should disable screen compatibility mode in order to maintain the best user experience. To learn how
+to quickly disable the user option, jump to <a href="#Disable">Disabling Screen Compatibility
+Mode</a>.</p>
+
+<p>Screen compatibility mode is an escape hatch for applications that are not properly designed
+to resize for larger screens such as tablets. Since Android 1.6, Android has supported a
+variety of screen sizes and does most of the work to resize application layouts so that they
+properly fit each screen. However, if your application does not successfully follow the guide to
+<a href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a>,
+then it might encounter some rendering issues on larger screens. For applications with this
+problem, screen compatibility mode can make the application a little more usable on larger
+screens.</p>
+
+<p>There are two versions of screen compatibility mode with slightly different behaviors:</p>
+<dl>
+ <dt>Version 1 (Android 1.6 - 3.1)</dt>
+ <dd>The system draws the application's UI in a "postage stamp"
+window. That is, the system draws the application's layout the same as it would on a
+normal size handset (emulating a 320dp x 480dp screen), with a black border that fills
+the remaining area of the screen.
+
+<p>This was introduced with Android 1.6 to handle apps that were designed only for the
+original screen size of 320dp x 480dp. Because there are so few active devices remaining that run
+Android 1.5, almost all applications should be developed against Android 1.6 or greater and
+should not have version 1 of screen compatibility mode enabled for larger screens. This version
+is considered obsolete.</p>
+ <p>To disable this version of screen compatibility mode, you simply need to set <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "4"} or higher, or set <a
+href="guide/topics/manifest/supports-screens-element.html#resizeable">{@code
+android:resizeable}</a> to {@code "true"}.</p>
+ </dd>
+
+ <dt>Version 2 (Android 3.2 and greater)</dt>
+ <dd>The system draws the application's layout the same as
+it would on a normal size handset (approximately emulating a 320dp x 480dp screen), then scales it
+up to fill the screen. This essentially "zooms" in on your layout to make it bigger,
+which will usually cause artifacts such as blurring and pixelation in your UI.
+ <p>This was introduced with Android 3.2 to further
+assist applications on the latest tablet devices when the applications have not yet
+implemented techniques for <a
+href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple
+Screens</a>.</p>
+ <p>In general, large screen devices running Android 3.2 or higher allow users to enable
+screen compatibility mode when the application does not <strong>explicitly declare that it supports
+large screens</strong> in the manifest file. When this is the case, an icon (with
+outward-pointing arrows) appears next to the clock in the system bar, which allows the user to
+toggle screen compatibility mode on and off (figure 3). An application can also explicitly
+declare that it <em>does not</em> support large screens such that screen compatibility mode
+is always enabled and the user cannot disable it. (How to declare your application's
+support for large screens is discussed in the following sections.)</p></dd>
+</dl>
+
+<img src="{@docRoot}images/screens_support/compat-toggle.png" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong> The pop up menu to toggle screen compatibility
+mode (currently disabled, so normal resizing occurs).</p>
+
+<p>As a developer, you have control over when your application uses screen compatibility mode. The
+following sections describe how you can choose to disable or enable screen compatibility mode for
+larger screens when running Android 3.2 or higher.</p>
+
+
+<h2 id="Disable">Disabling Screen Compatibility Mode</h2>
+
+<p>If you've developed your application primarily for versions of Android lower than 3.0, but
+<strong>your application does resize properly</strong> for larger screens such as tablets,
+<strong>you should disable screen compatibility mode</strong> in order to maintain the best user
+experience. Otherwise, users may enable screen compatibility mode and experience your application in
+a less-than-ideal format.</p>
+
+<p>By default, screen compatibility mode for devices running Android 3.2 and higher is offered to
+users as an optional feature when one of the following is true:</p>
+
+<ul>
+ <li>Your application has set both <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "10"} or lower and <strong>does not explicitly
+declare support</strong> for large screens using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element.</li>
+
+ <li>Your application has set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher and <strong>explicitly declares that it does
+not support</strong> large screens, using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element.</li>
+</ul>
+
+<p>To completely disable the user option for screen compatibility mode and remove the icon in the
+system bar, you can do one of the following:</p>
+
+<ul>
+ <li><strong>Easiest:</strong>
+ <p>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element and specify the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#xlarge">{@code
+android:xlargeScreens}</a> attribute to {@code "true"}:</p>
+<pre>
+&lt;supports-screens android:xlargeScreens="true" /&gt;
+</pre>
+ <p>That's it. This declares that your application supports all larger screen sizes, so the
+system will always resize your layout to fit the screen. This works regardless of what values
+you've set in the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a>
+attributes.</p>
+ </li>
+
+ <li><strong>Easy but has other effects:</strong>
+ <p>In your manifest's <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a>
+element, set <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher:</p>
+<pre>
+&lt;uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" /&gt;
+</pre>
+ <p>This declares that your application supports Android 3.0 and, thus, is designed to
+work on larger screens such as tablets.</p>
+ <p class="caution"><strong>Caution:</strong> When running on Android 3.0 and greater, this also
+has the effect of enabling the Holographic theme for you UI, adding the <a
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> to your activities, and removing the
+Options Menu button in the system bar.</p>
+ <p>If screen compatibility mode is still enabled after you change this, check your manifest's <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> and be sure that there are no attributes set {@code "false"}. The best
+practice is to always explicitly declare your support for different screen sizes using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element, so you should use this element anyway.</p>
+ <p>For more information about updating your application to target Android 3.0 devices, read <a
+href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android
+3.0</a>.</p>
+ </li>
+<!--
+ <li><strong>Most control</strong> (but you must compile against Android 3.2 or higher):
+ <p>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element and specify the {@code android:compatibleWidthLimitDp}
+attribute to any value <em>higher than</em> {@code "320"}:</p>
+<pre>
+&lt;supports-screens android:compatibleWidthLimitDp="720" /&gt;
+</pre>
+ <p>Using this technique allows you to specify exactly what your application's limit is for
+layout resizing. Normally, only applications that are already built against Android 3.2 (or
+higher) use this attribute, because the primary intention is to specify at what size should screen
+compatibility mode actually be offered to users.</p>
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates
+handset screens with a 320dp width, so screen compatibility mode is not applied to any device if
+your value for {@code android:compatibleWidthLimitDp} is larger than 320.</p>
+ </li>
+ -->
+</ul>
+
+
+
+<h2 id="Enable">Enabling Screen Compatibility Mode</h2>
+
+<p>When your application is targeting Android 3.2 (API level 13) or higher, you can affect
+whether compatibility mode is enabled for certain screens by using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens>}</a> element.</p>
+
+<p class="note"><strong>Note:</strong> Screen compatibility mode is <strong>not</strong> a mode in
+which you should want your application to run&mdash;it causes pixelation and blurring in your UI,
+due to zooming. The proper way to make your application work well on large screens is to follow the
+guide to <a
+href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a> and
+provide alternative layouts for different screen sizes.</p>
+
+<p>By default, when you've set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher, screen compatibility mode is
+<strong>not</strong> available to users. If either of these are true and your application does not
+resize properly for larger screens, you can choose to enable screen compatibility mode in one
+of the following ways:</p>
+
+<ul>
+ <li>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element and specify the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> attribute to {@code "320"}:</p>
+<pre>
+&lt;supports-screens android:compatibleWidthLimitDp="320" /&gt;
+</pre>
+ <p>This indicates that the maximum "smallest screen width" for which your application is designed
+is 320dp. This way, any devices with their smallest side being larger than this value will offer
+screen compatibility mode as a user-optional feature.</p>
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates
+handset screens with a 320dp width, so screen compatibility mode is not applied to any device if
+your value for <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> is larger than 320.</p>
+ </li>
+
+ <li>If your application is functionally broken when resized for large screens and you want to
+force users into screen compatibility mode (rather than simply providing the option), you can use
+the <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html#largestWidth">{@code
+android:largestWidthLimitDp}</a> attribute:
+<pre>
+&lt;supports-screens android:largestWidthLimitDp="320" /&gt;
+</pre>
+ <p>This works the same as <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> except it force-enables
+screen compatibility mode and does not allow users to disable it.</p>
+ </li>
+</ul> \ No newline at end of file
diff --git a/docs/html/guide/practices/screens-distribution.jd b/docs/html/guide/practices/screens-distribution.jd
index 0c5193b..951e364 100644
--- a/docs/html/guide/practices/screens-distribution.jd
+++ b/docs/html/guide/practices/screens-distribution.jd
@@ -17,6 +17,7 @@ screen configuration</li>
<ol>
<li><a href="#FilteringHansetApps">Filtering a Handset Application from Tablets</a></li>
<li><a href="#FilteringTabletApps">Filtering a Tablet Application from Handsets</a></li>
+ <li><a href="#MultiApks">Publishing Multiple APKs for Different Screens</a></li>
</ol>
<h2>See also</h2>
@@ -43,7 +44,7 @@ application supports.</p>
should understand the techniques for <a
href="{@docRoot}guide/practices/screens_support.html">supporting multiple screens</a> and implement
them to the best of your ability. By supporting multiple screens, your application can be made
-available to the greatest number of users with different devices, using a single {@code .apk}.</p>
+available to the greatest number of users with different devices, using a single APK.</p>
@@ -144,9 +145,9 @@ href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
with <em>larger</em> screens) and set the larger screen size attributes to {@code "false"}, then
external services such as Android Market <strong>do not</strong> apply filtering. Your application
will still be available to larger screens, but when it runs, it will not resize to fit the screen.
-Instead, the system will draw it in a "postage stamp" window that's the same relative size as the
-screen size that your application does support (see <a
-href="screens-support-1.5.html#CompatMode">compatibility mode</a> for more information). If you want
+Instead, the system will emulate a handset screen size (about 320dp x 480dp; see <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">Screen Compatibility Mode</a> for more
+information). If you want
to prevent your application from being downloaded on larger screens, use <a
href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
&lt;compatible-screens>}</a>, as discussed in the previous section about <a
@@ -162,3 +163,24 @@ href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
or you have decided to provide different versions of your application for different sets of screen
configurations.</p>
+
+
+<h2 id="MultiApks">Publishing Multiple APKs for Different Screens</h2>
+
+<p>Although we recommend that you publish one APK for your application, Android Market allows
+you to publish multiple APKs for the same
+application when each APK supports a different set of screen configurations (as declared in
+the manifest file). For example, if you want to publish both a handset version and a tablet
+version of your application, but you're unable to make the same APK work for both screen sizes,
+you can actually publish two APKs for the same application listing. Depending on each device's
+screen configuration, Android Market will deliver it the APK that you've declared to support that
+device's screen.</p>
+
+<p>Beware, however, that publishing multiple APKs for the same application is
+considered an advanced feature and <strong>most applications should publish only one
+APK that can support a wide range of device configurations</strong>. Supporting multiple screen
+sizes, especially, is within reason using a single APK, as long as you follow the guide to
+<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
+
+<p>If you need more information about how to publish multiple APKs on Android Market, read <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
diff --git a/docs/html/guide/practices/screens-support-1.5.jd b/docs/html/guide/practices/screens-support-1.5.jd
index 6fd36bb..9f033b4 100644
--- a/docs/html/guide/practices/screens-support-1.5.jd
+++ b/docs/html/guide/practices/screens-support-1.5.jd
@@ -18,7 +18,6 @@ an application designed for Android 1.5</li>
<h2>In this document</h2>
<ol>
<li><a href="#strategies">Adding Multiple Screens Support</a></li>
- <li><a href="#CompatMode">Compatibility Mode</a></li>
</ol>
<h2>See also</h2>
@@ -47,11 +46,13 @@ android:targetSdkVersion}</a> set to {@code "4"} or higher, then this document i
default, an application written for Android 1.5 or below that does not set the <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
android:targetSdkVersion}</a> set to {@code "4"} or higher runs in <a
-href="#CompatMode">compatibility mode</a> when on a device with a screen larger than the
+href="screen-compat-mode">screen compatibility mode</a> when on a device with a screen larger than
+the
<em>normal</em> screen size (basically, the system displays the application in a small window
that is roughly the size of the normal screen size).</p>
-<p>This document describes how to get your application out of <a href="#CompatMode">compatibility
+<p>This document describes how to get your application out of <a
+href="screen-compat-mode.html">screen compatibility
mode</a> and instead support multiple screens, but also maintain compatibility with Android 1.5 and
below.</p>
@@ -144,43 +145,3 @@ Android 3.0 and use the WXGA emulator skin.</p>
href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to add
complete support for different screen configurations.</p>
-
-<h2 id="CompatMode">Compatibility Mode</h2>
-
-<div class="figure" style="width:450px;margin:0">
-<img src="{@docRoot}images/screens_support/compat-mode-on.png" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> An application running in compatibility mode
-on an extra large screen.</p>
-</div>
-
-<p>To allow applications to run on larger screens without stretching the UI, Android provides a
-compatibility mode that draws an application's UI in a "postage stamp" window when on larger
-screens. That is, the system displays the application at the baseline size (<em>normal</em>) and
-density (<em>mdpi</em>), with a black border that fills the rest of the screen.</p>
-
-<p>Compatibility mode exists primarily to support application's developed for Android 1.5 (or lower)
-when running on larger screens, because multiple screen support was not added until Android 1.6,
-older applications were not designed to support different screen configurations.</p>
-
-<p>As such, if you've set your <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-android:minSdkVersion}</a> to {@code "3"} or lower and have <em>not</em> set the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-android:targetSdkVersion}</a> to {@code "4"} or higher, then compatibility mode is enabled and
-the system will not scale your application, because your application implicitly declares that it
-only supports the baseline screen configuration (normal screen size and medium density).</p>
-
-<p>To disable compatibility mode, set either <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-android:minSdkVersion}</a> or <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-android:targetSdkVersion}</a> to {@code "4"} or higher. For more information, see the previous
-section about <a href="#strategies">Adding Multiple Screens Support</a>.</p>
-
-<p>You can also affect whether compatibility mode is enabled by using the <a
-href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
-&lt;supports-screens>}</a> element (you can enable it by setting {@code android:resizeable} or
-specific screen sizes to {@code "false"}). However, you should not explicitly enable compatibility
-mode for your application, but should instead apply the necessary techniques to <a
-href="{@docRoot}guide/practices/screens_support.html">supporting multiple screens</a> and allow your
-application to properly fit the screen on all screen sizes.</p>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 14de152..6dec4b3 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -25,6 +25,13 @@ page.title=Supporting Multiple Screens
<li><a href="#qualifiers">Using configuration qualifiers</a></li>
<li><a href="#DesigningResources">Designing alternative layouts and drawables</a></li>
</ol></li>
+ <li><a href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> <span
+class="new">new!</span>
+ <ol>
+ <li><a href="#NewQualifiers">Using new size qualifiers</a></li>
+ <li><a href="#ConfigurationExamples">Configuration examples</a></li>
+ <li><a href="#DeclaringScreenSizeSupport">Declaring screen size support</a></li>
+ </ol></li>
<li><a href="#screen-independence">Best Practices</a></li>
<li><a href="#DensityConsiderations">Additional Density Considerations</a>
<ol>
@@ -57,15 +64,15 @@ Guidelines</a></li>
applications, the Android system provides a consistent development environment across devices and
handles most of the work to adjust each application's user interface to the screen on which it is
displayed. At the same time, the system provides APIs that allow you to control your
-application's UI on specific screen sizes and densities, in order to modify and optimize your UI
+application's UI for specific screen sizes and densities, in order to optimize your UI
design for different screen configurations. For example, you might want a UI for tablets
-that's different from the design for handsets.</p>
+that's different from the UI for handsets.</p>
-<p>Although the system performs sufficient scaling and resizing to make your application work on
+<p>Although the system performs scaling and resizing to make your application work on
different screens, you should make the effort to optimize your application for different screen
sizes and densities. In doing so, you maximize the user experience for all devices and your users
believe that your application was actually designed for <em>their</em> devices&mdash;rather than
-simply stretched to fit their devices.</p>
+simply stretched to fit the screen on their devices.</p>
<p>By following the practices described in this document, you can create an application that
displays properly and provides an optimized user experience on all supported screen configurations,
@@ -74,7 +81,14 @@ using a single {@code .apk} file.</p>
<p class="note"><strong>Note:</strong> The information in this document assumes that your
application is designed for Android 1.6 (API Level 4) or higher. If your application supports
Android 1.5 or lower, please first read <a
-href="{@docRoot}guide/practices/screens-support-1.5.html">Strategies for Android 1.5</a>.</p>
+href="{@docRoot}guide/practices/screens-support-1.5.html">Strategies for Android 1.5</a>.
+<br/><br/>
+Also, be aware that <strong>Android 3.2 has introduced new APIs</strong> that allow you to more
+precisely control the layout resources your application uses for different screen sizes. These new
+features are especially important if you're developing an application that's optimized for tablets.
+For details, see the section about <a href="#DeclaringTabletLayouts">Declaring Tablet Layouts for
+Android 3.2</a>.
+</p>
@@ -143,9 +157,16 @@ the range of actual screen sizes and densities into:</p>
<li>A set of four generalized <strong>sizes</strong>: <em>small</em>, <em>normal</em>,
<em>large</em>,
and <em>xlarge</em></em>
+<p class="note"><strong>Note:</strong> Beginning with Android 3.2 (API level 13), these size groups
+are deprecated in favor of a new technique for managing screen sizes based on the available screen
+width. If you're developing for Android 3.2 and greater, see <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for more
+information.</p>
+</li>
<li>A set of four generalized <strong>densities</strong>: <em>ldpi</em> (low), <em>mdpi</em>
(medium),
<em>hdpi</em> (high), and <em>xhdpi</em> (extra high)
+</li>
</ul>
<p>The generalized sizes and densities are arranged around a
@@ -154,7 +175,7 @@ baseline is based upon the screen configuration for the first Android-powered de
G1, which has an HVGA screen (until Android 1.6, this was the only screen configuration that Android
supported).</p>
-<p>Each generalized size or density spans a range of actual screen sizes or density. For example,
+<p>Each generalized size and density spans a range of actual screen sizes and densities. For example,
two devices that both report a screen size of <em>normal</em> might have actual screen sizes and
aspect ratios that are slightly different when measured by hand. Similarly, two devices that report
a screen density of <em>hdpi</em> might have real pixel densities that are slightly different.
@@ -168,11 +189,30 @@ and density groups.</p>
Illustration of how Android roughly maps actual sizes and densities
to generalized sizes and densities (figures are not exact).</p>
+<p>As you design your UI for different screen sizes, you'll discover that each design requires a
+minimum amount of space. So, each generalized screen size above has an associated minimum
+resolution that's defined by the system. These minimum sizes are in "dp" units&mdash;the same units
+you should use when defining your layouts&mdash;which allows the system to avoid worrying about
+changes in screen density.</p>
+
+<ul>
+ <li><em>xlarge</em> screens are at least 960dp x 720dp</li>
+ <li><em>large</em> screens are at least 640dp x 480dp</li>
+ <li><em>normal</em> screens are at least 470dp x 320dp</li>
+ <li><em>small</em> screens are at least 426dp x 320dp</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> These minimum screen sizes were not as well defined prior to
+Android 3.0, so you may encounter some devices that are mis-classified between normal and large.
+These are also based on the physical resolution of the screen, so may vary across devices&mdash;for
+example a 1024x720 tablet with a system bar actually has a bit less space available to the
+application due to it being used by the system bar.</p>
+
<p>To optimize your application's UI for the different screen sizes and densities, you can provide
<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
resources</a> for any of the generalized sizes and densities. Typically, you should
provide alternative layouts for some of the different screen sizes and alternative bitmap images for
-different screen densities. At runtime, the system uses the appropriate size or density resources
+different screen densities. At runtime, the system uses the appropriate resources
for your application, based on the generalized size or density of the current device screen.</p>
<p>You do not need to provide alternative resources for every combination of screen size and
@@ -221,7 +261,7 @@ density, if necessary</li>
</ul>
<p>In figure 2, the text view and bitmap drawable have dimensions specified in pixels ({@code px}
-units), so the elements are physically larger on a low density screen and smaller on a high density
+units), so the views are physically larger on a low density screen and smaller on a high density
screen. This is because although the actual screen sizes may be the same, the high density screen
has more pixels per inch (the same amount of pixels fit in a smaller area). In figure 3, the layout
dimensions are specified in density-independent pixels ({@code dp} units). Because the baseline for
@@ -255,6 +295,18 @@ for the screen density, as appropriate. To more gracefully handle different scre
however, you should also:</p>
<ul>
+ <li><strong>Explicitly declare in the manifest which screen sizes your application
+supports</strong>
+ <p>By declaring which screen sizes your application supports, you can ensure that only
+devices with the screens you support can download your application. Declaring support for
+different screen sizes can also affect how the system draws your application on larger
+screens&mdash;specifically, whether your application runs in <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a>.</p>
+ <p>To declare the screen sizes your application supports, you should include the
+<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+&lt;supports-screens&gt;}</a> element in your manifest file.</p>
+ </li>
+
<li><strong>Provide different layouts for different screen sizes</strong>
<p>By default, Android resizes your application layout to fit the current device screen. In most
cases, this works fine. In other cases, your UI might not look as good and might need adjustments
@@ -264,6 +316,12 @@ you might need to adjust sizes so that everything can fit on the screen.</p>
<p>The configuration qualifiers you can use to provide size-specific resources are
<code>small</code>, <code>normal</code>, <code>large</code>, and <code>xlarge</code>. For
example, layouts for an extra large screen should go in {@code layout-xlarge/}.</p>
+ <p>Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you
+should instead use the {@code sw&lt;N&gt;dp} configuration qualifier to define the smallest
+available width required by your layout resources. For example, if your multi-pane tablet layout
+requires at least 600dp of screen width, you should place it in {@code layout-sw600dp/}. Using the
+new techniques for declaring layout resources is discussed further in the section about <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a>.</p>
</li>
<li><strong>Provide different bitmap drawables for different screen densities</strong>
@@ -386,7 +444,7 @@ provide special resources for different screen configurations.</p>
</tr>
<tr>
-<td rowspan="5">Density</td>
+<td rowspan="6">Density</td>
<td><code>ldpi</code></td>
<td>Resources for low-density (<em>ldpi</em>) screens (~120dpi).</td>
</tr>
@@ -408,7 +466,15 @@ density.)</td>
<td>Resources for all densities. These are density-independent resources. The system does not
scale resources tagged with this qualifier, regardless of the current screen's density.</td>
</tr>
-
+<tr>
+<td><code>tvdpi</code></td>
+<td>Resources for screens somewhere between mdpi and hdpi; approximately 213dpi. This is not
+considered a "primary" density group. It is mostly intended for televisions and most apps shouldn't
+need it&mdash;providing mdpi and hdpi resources is sufficient for most apps and the system will
+scale them as appropriate. If you find it necessary to provide tvdpi resources, you should size them
+at a factor of 1.33*mdpi. For example, a 100px x 100px image for mdpi screens should be 133px x
+133px for tvdpi.</td>
+</tr>
<tr>
<td rowspan="2">Orientation</td>
<td><code>land</code></td>
@@ -432,6 +498,12 @@ configuration.</td>
</tr>
</table>
+<p class="note"><strong>Note:</strong> If you're developing your application for Android 3.2 and
+higher, see the section about <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for information about
+new configuration qualifiers that you should use when declaring layout resources for specific
+screen sizes (instead of using the size qualifiers in table 1).</p></p>
+
<p>For more information about how these qualifiers roughly correspond to real screen
sizes and densities, see <a href="#range">Range of Screens Supported</a>, earlier in this
document.</p>
@@ -457,6 +529,20 @@ configuration qualifiers (not just for screen configurations), see
<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
Providing Alternative Resources</a>.</p>
+<p>Be aware that, when the Android system picks which resources to use at runtime, it uses
+certain logic to determing the "best matching" resources. That is, the qualifiers you use don't
+have to exactly match the current screen configuration in all cases in order for the system to
+use them. Specifically, when selecting resources based on the size qualifiers, the system will
+use resources designed for a screen smaller than the current screen if there are no resources
+that better match (for example, a large-size screen will use normal-size screen resources if
+necessary). However, if the only available resources are <em>larger</em> than the current screen,
+the system will not use them and your application will crash if no other resources match the device
+configuration (for example, if all layout resources are tagged with the {@code xlarge} qualifier,
+but the device is a normal-size screen). For more information about how the system selects
+resources, read <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#BestMatch">How Android Finds the
+Best-matching Resource</a>.</p>
+
<p class="note"><strong>Tip:</strong> If you have some drawable resources that the system
should never scale (perhaps because you perform some adjustments to the image yourself at
runtime), you should place them in a directory with the {@code nodpi} configuration qualifier.
@@ -554,6 +640,291 @@ icons, status bar icons, tab icons, and more.</p>
+
+<h2 id="DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</h2>
+
+<p>For the first generation of tablets running Android 3.0, the proper way to declare tablet
+layouts was to put them in a directory with the {@code xlarge} configuration qualifier (for example,
+ {@code res/layout-xlarge/}). In order to accommodate other types of tablets and screen
+sizes&mdash;in particular, 7" tablets&mdash;Android 3.2 introduces a new way to specify resources
+for more discrete screen sizes. The new technique is based on the amount of space your layout needs
+(such as 600dp of width), rather than trying to make your layout fit the generalized size groups
+(such as <em>large</em> or <em>xlarge</em>).</p>
+
+<p>The reason designing for 7" tablets is tricky when using the generalized size groups is
+that a 7" tablet is technically in the same group as a 5" handset (the <em>large</em> group). While
+these two devices are seemingly close to each other in size, the amount of space for an
+application's UI is significantly different, as is the style of user interaction. Thus, a 7" and 5"
+screen should not always use the same layout. To make it possible for you to provide different
+layouts for these two kinds of screens, Android now allows you to specify your layout resources
+based on the width and/or height that's actually available for your application's layout, specified
+in dp units.</p>
+
+<p>For example, after you've designed the layout you want to use for tablet-style devices, you might
+determine that the layout stops working well when the screen is less than 600dp wide. This threshold
+thus becomes the minimum size that you require for your tablet layout. As
+such, you can now specify that these layout resources should be used only when there is at least
+600dp of width available for your application's UI.</p>
+
+<p>You should either pick a width and design to it as your minimum size, or test what is the
+smallest width your layout supports once it's complete.</p>
+
+<p class="note"><strong>Note:</strong> Remember that all the figures used with these new size APIs
+are density-indpendent pixel (dp) values and your layout dimensions should also always be defined
+using dp units, because what you care about is the amount of screen space available after the system
+accounts for screen density (as opposed to using raw pixel resolution). For more information about
+density-indpendent pixels, read <a href="#terms">Terms and concepts</a>, earlier in this
+document.</p>
+
+
+<h3 id="NewQualifiers">Using new size qualifiers</h3>
+
+<p>The different resource configurations that you can specify based on the space available for your
+layout are summarized in table 2. These new qualifiers offer you more control over the specific
+screen sizes your application supports, compared to the traditional screen size groups (small,
+normal, large, and xlarge).</p>
+
+<p class="note"><strong>Note:</strong> The sizes that you specify using these qualifiers are
+<strong>not the actual screen sizes</strong>. Rather, the sizes are for the width or height in dp
+units that are <strong>available to your activity's window</strong>. The Android system
+might use some of the screen for system UI (such as the system bar at the bottom of the screen or
+the status bar at the top), so some of the screen might not be available for your layout. Thus, the
+sizes you declare should be specifically about the sizes needed by your activity&mdash;the system
+accounts for any space used by system UI when declaring how much space it provides for your layout.
+Also beware that the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> is considered
+a part of your application's window space, although your layout does not declare it, so it reduces
+the space available for your layout and you must account for it in your design.</p>
+
+<p class="table-caption"><strong>Table 2.</strong> New configuration qualifers for screen size
+(introduced in Android 3.2).</p>
+<table>
+ <tr><th>Screen configuration</th><th>Qualifier values</th><th>Description</th></tr>
+ <tr><td>smallestWidth</td>
+ <td><code>sw&lt;N&gt;dp</code><br/><br/>
+ Examples:<br/>
+ <code>sw600dp</code><br/>
+ <code>sw720dp</code><br/>
+ </td>
+ <td>
+ <p>The fundamental size of a screen, as indicated by the shortest dimension of the available
+screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
+height and width (you may also think of it as the "smallest possible width" for the screen). You can
+use this qualifier to ensure that, regardless of the screen's current orientation, your
+application's has at least {@code &lt;N&gt;} dps of width available for it UI.</p>
+ <p>For example, if your layout requires that its smallest dimension of screen area be at
+least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
+res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
+available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived
+height or width. The smallestWidth is a fixed screen size characteristic of the device; <strong>the
+device's smallestWidth does not change when the screen's orientation changes</strong>.</p>
+ <p>The smallestWidth of a device takes into account screen decorations and system UI. For
+example, if the device has some persistent UI elements on the screen that account for space along
+the axis of the smallestWidth, the system declares the smallestWidth to be smaller than the actual
+screen size, because those are screen pixels not available for your UI.</p>
+ <p>This is an alternative to the generalized screen size qualifiers (small, normal, large, xlarge)
+that allows you to define a discrete number for the effective size available for your UI.
+Using smallestWidth to determine the general screen size is useful because width is
+often the driving factor in designing a layout. A UI will often scroll vertically, but have fairly
+hard constraints on the minimum space it needs horizontally. The available width is also the key
+factor in determining whether to use a one-pane layout for handsets or multi-pane layout for
+tablets. Thus, you likely care most about what the smallest possible width will be on each
+device.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>Available screen width</td>
+ <td><code>w&lt;N&gt;dp</code><br/><br/>
+ Examples:<br/>
+ <code>w720dp</code><br/>
+ <code>w1024dp</code><br/>
+ </td>
+ <td>
+ <p>Specifies a minimum available width in dp units at which the resources should be
+used&mdash;defined by the <code>&lt;N&gt;</code> value. The system's corresponding value for the
+width changes when the screen's orientation switches between landscape and portrait to
+reflect the current actual width that's available for your UI.</p>
+ <p>This is often useful to determine whether to use a multi-pane layout, because even on a
+tablet device, you often won't want the same multi-pane layout for portrait orientation as you do
+for landscape. Thus, you can use this to specify the minimum width required for the layout, instead
+of using both the screen size and orientation qualifiers together.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>Available screen height</td>
+ <td><code>h&lt;N&gt;dp</code><br/><br/>
+ Examples:<br/>
+ <code>h720dp</code><br/>
+ <code>h1024dp</code><br/>
+ etc.
+ </td>
+ <td>
+ <p>Specifies a minimum screen height in dp units at which the resources should be
+used&mdash;defined by the <code>&lt;N&gt;</code> value. The system's corresponding value for
+the height changes when the screen's orientation switches between landscape and portrait to
+reflect the current actual height that's available for your UI.</p>
+ <p>Using this to define the
+height required by your layout is useful in the same way as <code>w&lt;N&gt;dp</code> is for
+defining the required width, instead of using both the screen size and orientation qualifiers.
+However, most apps won't need this qualifier, considering that UIs often scroll vertically and are
+thus more flexible with how much height is available, whereas the width is more rigid.</p>
+ </td>
+ </tr>
+</table>
+
+<p>While using these qualifiers might seem more complicated than using screen size groups, it should
+actually be simpler once you determine the requirements for your UI. When you design your UI,
+the main thing you probably care about is the actual size at which your application switches between
+a handset-style UI and a tablet-style UI that uses multiple panes. The exact point of this switch
+will depend on your particular design&mdash;maybe you need a 720dp width for your tablet layout,
+maybe 600dp is enough, or 480dp, or some number between these. Using these qualifiers in table 2,
+you are in control of the precise size at which your layout changes.</p>
+
+<p>For more discussion about these size configuration qualifiers, see the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">
+Providing Resources</a> document.</p>
+
+
+<h3 id="ConfigurationExamples">Configuration examples</h3>
+
+<p>To help you target some of your designs for different types of devices, here are some
+numbers for typical screen widths:</p>
+
+<ul>
+ <li>320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).</li>
+ <li>480dp: a tweener tablet like the Streak (480x800 mdpi).</li>
+ <li>600dp: a 7” tablet (600x1024 mdpi).</li>
+ <li>720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).</li>
+</ul>
+
+<p>Using the size qualifiers from table 2, your application can switch between your different layout
+resources for handsets and tablets using any number you want for width and/or height. For example,
+if 600dp is the smallest available width supported by your tablet layout, you can provide these two
+sets of layouts:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml # For handsets
+res/layout-sw600dp/main_activity.xml # For tablets
+</pre>
+
+<p>In this case, the smallest width of the available screen space must be 600dp in order for the
+tablet layout to be applied.</p>
+
+<p>For other cases in which you want to further customize your UI to differentiate between sizes
+such as 7” and 10” tablets, you can define additional smallest width layouts:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml # For handsets (smaller than 600dp available width)
+res/layout-sw600dp/main_activity.xml # For 7” tablets (600dp wide and bigger)
+res/layout-sw720dp/main_activity.xml # For 10” tablets (720dp wide and bigger)
+</pre>
+
+<p>Notice that the previous two sets of example resources use the "smallest width" qualifer, {@code
+sw&lt;N&gt;dp}, which specifies the smallest of the screen's two sides, regardless of the
+device's current orientation. Thus, using {@code sw&lt;N&gt;dp} is a simple way to specify the
+overall screen size available for your layout by ignoring the screen's orientation.</p>
+
+<p>However, in some cases, what might be
+important for your layout is exactly how much width or height is <em>currently</em> available. For
+example, if you have a two-pane layout with two fragments side by side, you might want to use it
+whenever the screen provides at least 600dp of width, whether the device is in landscape or
+portrait orientation. In this case, your resources might look like this:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml # For handsets (smaller than 600dp available width)
+res/layout-w600dp/main_activity.xml # Multi-pane (any screen with 600dp available width or more)
+</pre>
+
+<p>Notice that the second set is using the "available width" qualifier, {@code w&lt;N&gt;dp}. This
+way, one device may actually use both layouts, depending on the orientation of the screen (if
+the available width is at least 600dp in one orientation and less than 600dp in the other
+orientation).</p>
+
+<p>If the available height is a concern for you, then you can do the same using the {@code
+h&lt;N&gt;dp} qualifier. Or, even combine the {@code w&lt;N&gt;dp} and {@code h&lt;N&gt;dp}
+qualifiers if you need to be really specific.</p>
+
+
+<h3 id="DeclaringScreenSizeSupport">Declaring screen size support</h3>
+
+<p>Once you've implemented your layouts for different screen sizes, it's equally important that you
+declare in your manifest file which screens your application supports.</p>
+
+<p>Along with the new configuration qualifiers for screen size, Android 3.2 introduces new
+attributes for the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a>
+manifest element:</p>
+
+<dl>
+
+ <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">
+{@code android:requiresSmallestWidthDp}</a></dt>
+ <dd>Specifies the minimum smallestWidth required. The smallestWidth is the shortest dimension of
+the screen space (in {@code dp} units) that must be available to your application UI&mdash;that is,
+the shortest of the available screen's two dimensions. So, in order for a device to be considered
+compatible with your application, the device's smallestWidth must be equal to or greater than this
+value. (Usually, the value you supply for this is the "smallest width" that your layout supports,
+regardless of the screen's current orientation.)
+ <p>For example, if your application is only for tablet-style devices with a 600dp
+smallest available width:</p>
+<pre>
+&lt;manifest ... &gt;
+ &lt;supports-screens android:requiresSmallestWidthDp="600" /&gt;
+ ...
+&lt;/manifest&gt;
+</pre>
+ <p>However, if your application supports all screen sizes supported by Android (as small as
+426dp x 320dp), then you don't need to declare this attribute, because the smallest width your
+application requires is the smallest possible on any device.</p>
+
+ <p class="caution"><strong>Caution:</strong> The Android system does not pay attention to this
+attribute, so it does not affect how your application behaves at runtime. Instead, it is used
+to enable filtering for your application on services such as Android Market. However,
+<strong>Android Market currently does not support this attribute for filtering</strong> (on Android
+3.2), so you should continue using the other size attributes if your application does not support
+small screens.</p>
+</dd>
+
+ <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">
+{@code android:compatibleWidthLimitDp}</a></dt>
+ <dd>This attribute allows you to enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> as a
+user-optional feature by specifying the maximum "smallest width" that your application
+supports. If the smallest side of a device's available screen is greater than your value here,
+users can still install your application, but are offered to run it in screen compatibility mode. By
+default, screen compatibility mode is disabled and your layout is resized to fit the screen as
+usual, but a button is available in the system bar that allows users to toggle screen compatibility
+mode on and off.
+ <p class="note"><strong>Note:</strong> If your application's layout properly resizes for large
+screens, you do not need to use this attribute. We recommend that you avoid using this
+attribute and instead ensure your layout resizes for larger screens by following the
+recommendations in this document.</p></dd>
+
+ <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#largestWidth">
+{@code android:largestWidthLimitDp}</a></dt>
+ <dd>This attribute allows you to force-enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> by specifying
+the maximum "smallest width" that your application supports. If the smallest
+side of a device's available screen is greater than your value here, the application runs in screen
+compatibility mode with no way for the user to disable it.
+ <p class="note"><strong>Note:</strong> If your application's layout properly resizes for large
+screens, you do not need to use this attribute. We recommend that you avoid using this
+attribute and instead ensure your layout resizes for larger screens by following the
+recommendations in this document.</p></dd>
+</dl>
+
+<p class="caution"><strong>Caution:</strong> When developing for Android 3.2 and higher, you
+should not use the older screen size attributes in combination with the attributes
+listed above. Using both the new attributes and the older size attributes might cause
+unexpected behavior.</p>
+
+<p>For more information about each of these attributes, follow the respective links above.</p>
+
+
+
+
<h2 id="screen-independence">Best Practices</h2>
<p>The objective of supporting multiple screens is to create an application that can function
@@ -875,7 +1246,7 @@ SDK Manager.exe} from your Android SDK directory (on Windows only) or execute {@
the {@code &lt;sdk&gt;/tools/} directory (on all platforms). Figure 6 shows the Android SDK and
AVD Manager with a selection of AVDs, for testing various screen configurations.</p>
-<p>Table 2 shows the various emulator skins that are available in the Android SDK, which you can use
+<p>Table 3 shows the various emulator skins that are available in the Android SDK, which you can use
to emulate some of the most common screen configurations.</p>
<p>For more information about creating and using AVDs to test your application, see <a
@@ -883,7 +1254,7 @@ href="{@docRoot}guide/developing/devices/managing-avds.html">Managing AVDs with
Manager</a>.</p>
-<p class="table-caption" id="screens-table"><strong>Table 2.</strong> Various screen
+<p class="table-caption" id="screens-table"><strong>Table 3.</strong> Various screen
configurations available from emulator skins in the Android SDK (indicated in bold) and other
representative resolutions.</p>