diff options
Diffstat (limited to 'docs/html/resources/articles')
112 files changed, 0 insertions, 5897 deletions
diff --git a/docs/html/resources/articles/avoiding-memory-leaks.jd b/docs/html/resources/articles/avoiding-memory-leaks.jd deleted file mode 100644 index 395f590..0000000 --- a/docs/html/resources/articles/avoiding-memory-leaks.jd +++ /dev/null @@ -1,111 +0,0 @@ -page.title=Avoiding Memory Leaks -parent.title=Articles -parent.link=../browser.html?tag=article -@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">@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; - -@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 deleted file mode 100644 index f96d587..0000000 --- a/docs/html/resources/articles/backward-compatibility.jd +++ /dev/null @@ -1,252 +0,0 @@ -page.title=Backward Compatibility for Applications -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a></li> - </ol> - -</div> -</div> - -<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 — 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 — perhaps you -need to record video using an API introduced in Android 1.5 (API Level 3) -— you should add a <a -href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code><android:minSdkVersion></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> <manifest> - ... - <uses-sdk android:minSdkVersion="3" /> - ... - </manifest></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 in <a -href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</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 deleted file mode 100644 index 7787d31..0000000 --- a/docs/html/resources/articles/can-i-use-this-intent.jd +++ /dev/null @@ -1,71 +0,0 @@ -page.title=Can I Use this Intent? -parent.title=Articles -parent.link=../browser.html?tag=article -@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<ResolveInfo> list = - packageManager.queryIntentActivities(intent, - PackageManager.MATCH_DEFAULT_ONLY); - return list.size() > 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 Google Play by using the appropriate URI.</p>
\ No newline at end of file diff --git a/docs/html/resources/articles/contacts.jd b/docs/html/resources/articles/contacts.jd deleted file mode 100644 index 374587b..0000000 --- a/docs/html/resources/articles/contacts.jd +++ /dev/null @@ -1,424 +0,0 @@ -page.title=Using the Contacts API -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -<p>Starting from Android 2.0 (API Level 5), the Android platform provides an -improved Contacts API for managing and integrating contacts from multiple -accounts and from other data sources. To handle overlapping data from multiple -sources, the contacts content provider aggregates similar contacts and presents -them to users as a single entity. This article describes how to use the new API -to manage contacts.</p> - -<p>The new Contacts API is defined in the -{@link android.provider.ContactsContract android.provider.ContactsContract} -and related classes. The older API is still supported, although deprecated. -If you have an existing application that uses the older API, -see <a href="#legacy">Considerations for legacy apps</a>, below, for ideas -on how to support the Contacts API in your app.</p> - -<p>If you'd like to look at an applied example of how to use the new Contacts -API, including how to support both the new and older API in a single app, -please see the <a -href="{@docRoot}resources/samples/BusinessCard/index.html">Business Card -sample application</a>.</p> - -<h3>Data structure of Contacts</h3> - -<p>In the new Contacts API, data is laid out in three primary tables: -<em>contacts</em>, <em>raw contacts</em>, and <em>data</em>, a structure that -is slightly different from that used in the older API. The new structure -allows the system to more easily store and manage information for a -specific contact from multiple contacts sources. </p> - -<img style="margin: 0px auto 10px; display: block; text-align: center; width: 471px; height: 255px;" src="images/contacts-2.png" alt="" border="0"> - -<ul> -<li><code>Data</code> is a generic table that stores all of the data points -associated with a raw contact. Each row stores data of a specific kind — -for example name, photo, email addresses, phone numbers, and group memberships. -Each row is tagged with a MIME type to identify what type of data it can -contain, across the entire column. Columns are generic and the type of data they -contain is determined by the kind of data stored in each row. For example, if a -row's data kind is <code>Phone.CONTENT_ITEM_TYPE</code>, then the first column -stores the phone number, but if the data kind is -<code>Email.CONTENT_ITEM_TYPE</code>, then the column stores the email address. - -<p>The {@link android.provider.ContactsContract.CommonDataKinds ContactsContract.CommonDataKinds} -class provides subclasses corresponding to common MIME types for contacts data. -If needed, your application or other contacts sources can define additional MIME -types for data rows. For more information about the Data table and examples of -how to use it, see {@link android.provider.ContactsContract.Data android.provider.ContactsContract.Data}.</p></li> - -<li>A row in the <code>RawContacts</code> table represents the set of -<code>Data</code> and other information describing a person and associated with -a single contacts source. For example, a row might define the data associated -with a person's Google or Exchange account or Facebook friend. For more -information, see -{@link android.provider.ContactsContract.RawContacts ContactsContract.RawContacts}.</p> - -<li>A row in the <code>Contacts</code> table represents an aggregate of one or -more <code>RawContacts</code> describing the same person (or entity). - -<p>As mentioned above, the Contacts content provider automatically aggregates -Raw Contacts into a single Contact entry, where possible, since common data -fields (such as name or email address) are likely to be stored in each raw -contact. Since the aggregation logic maintains the entries in the Contact rows, -the entries can be read but should not be modified. See the section <a -href="#aggregation">Aggregation of contacts</a>, below, for more details, -including and information on how to -control aggregation.</li> - -</ul> - -<p>When displaying contacts to users, applications should typically operate on -the Contacts level, since it provides a unified, aggregated view of contacts -from various underlying sources. </p> - -<h4>Example: Inserting a Phone Number</h4> - -<p>To insert a phone number using the new APIs you'll need the ID of the Raw -Contact to attach the phone number to, then you'll need to create a Data -row:</p> - -<pre>import android.provider.ContactsContract.CommonDataKinds.Phone; -... -ContentValues values = new ContentValues(); -values.put(Phone.RAW_CONTACT_ID, rawContactId); -values.put(Phone.NUMBER, phoneNumber); -values.put(Phone.TYPE, Phone.TYPE_MOBILE); -Uri uri = getContentResolver().insert(Phone.CONTENT_URI, values);</pre> - - -<h3 id="aggregation">Aggregation of contacts</h3> - -<p>When users sync contacts from multiple sources, several contacts might refer -to the same person or entity, but with slightly different (or overlapping) data. - For example, "Bob Parr" might be a user's co-worker and also his personal -friend, so the user might have his contact information stored in both a -corporate email account and a personal account. To provide a simplified view for -the user, the system locates such overlapping contacts and combines them into a -single, aggregate contact. </p> - -<p>The system automatically aggregates contacts by default. However, if needed, -your application can control how the system handles aggregation or it can -disable aggregation altogether, as described in the sections below.</p> - -<h4>Automatic aggregation</h4> - -<p>When a raw contact is added or modified, the system looks for matching -(overlapping) raw contacts with which to aggregate it. It may not find any -matching raw contacts, in which case it will create an aggregate contact that -contains just the original raw contact. If it finds a single match, it creates a -new contact that contains the two raw contacts. And it may even find multiple -similar raw contacts, in which case it chooses the closest match. </p> - -<p>Two raw contacts are considered to be a match if at least one of these -conditions is met:</p> - -<ul> -<li>They have matching names.</li> -<li>Their names consist of the same words but in different order -(for example, "Bob Parr" and "Parr, Bob")</li> -<li>One of them has a common short name for the other (for example, -"Bob Parr" and "Robert Parr")</li> -<li>One of them has just a first or last name and it matches the other -raw contact. This rule is less reliable, so it only applies if the two -raw contacts are also sharing some other data like a phone number, an -email address or a nickname (for example, Helen ["elastigirl"] = Helen -Parr ["elastigirl"])</li> -<li>At least one of the two raw contacts is missing the name altogether -and they are sharing a phone number, an email address or a nickname (for -example, Bob Parr [incredible@android.com] = incredible@android.com).</li> -</ul> - -<p>When comparing names, the system ignores upper/lower case differences -(Bob=BOB=bob) and diacritical marks (Hélène=Helene). When comparing two -phone numbers the system ignores special characters such as "*", "#", -"(", ")", and whitespace. Also if the only difference between two numbers -is that one has a country code and the other does not, then the system -considers those to be a match (except for numbers in the Japan country code).</p> - -<p>Automatic aggregation is not permanent; any change of a constituent raw -contact may create a new aggregate or break up an existing one.</p> - -<h4>Explicit aggregation</h4> - -<p>In some cases, the system's automatic aggregation may not meet the -requirements of your application or sync adapter. There are two sets of APIs you -can use to control aggregation explicitly: <em>aggregation modes</em> allow you -to control automatic aggregation behaviors and <em>aggregation exceptions</em> -allow you to override automated aggregation entirely. - -<p><strong>Aggregation modes</strong></p> - -<p>You can set an aggregation mode for each raw contact individually. To do so, -add a mode constant as the value of the <code>AGGREGATION_MODE column</code> in -the <code>RawContact</code> row. The mode constants available include: </p> - -<ul> -<li><code>AGGREGATION_MODE_DEFAULT</code> — normal mode, automatic -aggregation is allowed.</li> -<li><code>AGGREGATION_MODE_DISABLED</code> — automatic aggregation is not -allowed. The raw contact will not be aggregated.</li> -<li><code>AGGREGATION_MODE_SUSPENDED</code> — automatic aggregation is -deactivated. If the raw contact is already a part of an aggregated contact when -aggregation mode changes to suspended, it will remain in the aggregate, even if -it changes in such a way that it no longer matches the other raw contacts in the -aggregate.</li> -</ul> - -<p><strong>Aggregation exceptions</strong></p> - -<p>To keep two raw contacts unconditionally together or unconditionally apart, -you can add a row to the -{@link android.provider.ContactsContract.AggregationExceptions} table. Exceptions -defined in the table override all automatic aggregation rules. </p> - - -<h3>Loookup URI</h3> - -<p>The new Contacts API introduces the notion of a lookup key for a contact. If -your application needs to maintain references to contacts, you should use lookup -keys instead of the traditional row ids. You can acquire a lookup key from the -contact itself, it is a column on the -{@link android.provider.ContactsContract.Contacts} table. Once you have a lookup key, -you can construct a URI in this way:</p> - -<pre>Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey)</pre> - -<p>and use it like you would use a traditional content URI, for example: </p> - -<pre>Cursor c = getContentResolver().query(lookupUri, new String[]{Contacts.DISPLAY_NAME}, ...); -try { - c.moveToFirst(); - String displayName = c.getString(0); -} finally { - c.close(); -}</pre> - -<p>The reason for this complication is that regular contact row IDs are -inherently volatile. Let's say your app stored a long ID of a contact. Then the -user goes and manually joins the contact with some other contact. Now there is a -single contact where there used to be two, and the stored long contact ID points -nowhere. - -<p>The lookup key helps resolve the contact in this case. The key is a string -that concatenates the server-side identities of the raw contacts. Your -application can use that string to find a contact, regardless whether the raw -contact is aggregated with others or not. </p> - -<p>If performance is a concern for your application, you might want to store -both the lookup and the long ID of a contact and construct a lookup URI out of -both IDs, as shown here:</p> - -<pre>Uri lookupUri = getLookupUri(contactId, lookupKey)</pre> - -<p>When both IDs are present in the URI, the system will try to use the long ID -first. That is a very quick query. If the contact is not found, or if the one -that is found has the wrong lookup key, the content provider will parse the -lookup key and track down the constituent raw contacts. If your app -bulk-processes contacts, you should maintain both IDs. If your app works with a -single contact per user action, you probably don't need to bother with storing -the long ID.</p> - -Android itself uses lookup URIs whenever there is a need to reference a contact, -such as with shortcuts or Quick Contact, and also during editing or even viewing -a contact. The latter case is less obvious — why would a contact ID change -while we are simply viewing the contact? It could change because there might be -a sync going in the background, and the contact might get automatically -aggregated with another while being viewed.</p> - -<p>In summary: whenever you need to reference a contact, we recommend that you -do so by its lookup URI.</p> - - -<h3 id="legacy">Considerations for legacy applications</h3> - -<p>If you have an existing application that uses the older Contacts API, -you should consider upgrading it to use the new API. You have four options: </p> - -<ul> -<li>Leave it as-is and rely on the Contacts compatibility mode.</li> -<li>Upgrade the app and discontinue support of pre-Android 2.0 platforms.</li> -<li>Build a new version of the app for the new API, while keeping the old version available.</li> -<li>Make the app use the right set of APIs depending on the platform where it is deployed. </li> -</ul> - -<p>Let's consider these options one by one.</p> - -<h4>Using compatibility mode</h4> - -<p>Compatibility mode is the easiest option because you just leave the -application as is, and it should run on Android 2.0 as long as it only uses -public APIs. A couple examples of the use of non-public API include the use of -explicit table names in nested queries and the use of columns that were not -declared as public constants in the {@link android.provider.Contacts} class. -</p> - -<p>Even if the application currently runs, you don't want to leave it like this -for long. The main reason is that it will only have access to contacts from one -account, namely the first Google account on the device. If the user opens other -accounts in addition to or instead of a Google account, your application will -not be able to access those contacts.</p> - - -<h4>Upgrading to the new API and dropping support for older platforms</h4> - -<p>If your application will no longer target platforms older than -Android 2.0, you can upgrade to the new API in this way:</p> - -<ul> -<li>Replace all usages of {@link android.provider.Contacts} with calls to new -API. After you are done, you should not see any deprecation warnings during -application build. The new application will be able to take full advantage of -multiple accounts and other new features of Android 2.0. </p> - -<li>In the application's manifest, update (or add) the -<code>android:minSdkVersion</code> attribute to the -<code><uses-sdk></code> element. To use the new Contacts API, you should -set the value of the attribute to "5" (or higher, as appropriate). For more -information about <code>android:minSdkVersion</code>, see the documentation for -the <a -href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code><uses-sdk></code></a> -element. For more information about the value of the -<code>minSdkVersion</code>, see <a -href="{@docRoot}guide/appendix/api-levels.html">API Levels</a>.</li> -</ul> - -<h4>Maintaining two applications</h4> - -<p>You may decide to have two different applications: one for pre-Android 2.0 -platforms and one for Android 2.0 and beyond. If so, here's what you'll need to do:</p> - -<ul> - <li>Clone your existing app. </li> - <li>Change the old application: </li> - <ul> - <li>At launch time, check the version of the SDK. The version of the SDK -is available as {@link android.os.Build.VERSION#SDK android.os.Build.VERSION.SDK}.</li> - <li>If the SDK version is greater or equal to 5 (Android 2.0), show a dialog -suggesting to the user that it's time to go to Google Play and find a new version of -the app. You can even provide a link to the new app on Google Play (see <a -href="{@docRoot}guide/publishing/publishing.html#marketintent">Using Intents -to Launch Google Play</a>). </li> - </ul> - <li>Change the new application:</li> - <ul> - <li>Replace all usages of the older Contacts API with calls to new API. -The new application will be able to take full advantage of multiple accounts -and other new features of Android 2.0. </li> - <li>Modify that application's AndroidManifest.xml file: </li> - <ul> - <li>Give the application a new name and a new package name. Currently -Google Play does not allow you to have two applications with the same -name/package.</li> - <li>Update (or add) the <code>android:minSdkVersion</code> attribute -to the <code><uses-sdk></code> element. To use the new Contacts API, -you should set the value of the attribute to "5" (or higher, as appropriate).</li> - </ul> - </ul> - <li>Publish both apps on Google Play, the old app one as an upgrade and the -other as new. Make sure to explain the difference between the apps in their -descriptions.</li> -</ul> - -<p>This plan has its disadvantages: </p> - -<ul> -<li>The new application will not be able to read the old application's data. -Application data can only be accessed by code living in the same package. So -databases, shared preferences, and so on, will need to be populated from -scratch.</li> -<li>The upgrade process is too clunky for the user. Some users may choose -to either stay with the crippled old version or uninstall altogether.</li> -</ul> - -<h4>Supporting the old and new APIs in the same application</h4> - -<p>This is a bit tricky, but the result is worth the effort. You can -build a single package that will work on any platform:</p> - -<p>Go through the existing application and factor out all access to -{@link android.provider.Contacts} into one class, such as ContactAccessorOldApi. -For example, if you have code like this: - -<pre> protected void pickContact() { - startActivityForResult(new Intent(Intent.ACTION_PICK, People.CONTENT_URI), 0); - }</pre> - -<p>it will change to:</p> - - -<pre> private final ContactAccessorOldApi mContactAccessor = new ContactAccessorOldApi(); - - void pickContact() { - startActivityForResult(mContactAccessor.getContactPickerIntent(), 0); - }</pre> - -<p>The corresponding method on ContactAccessorOldApi will look like this:</p> - -<pre> public Intent getContactPickerIntent() { - return new Intent(Intent.ACTION_PICK, People.CONTENT_URI); - }</pre> - -<p>Once you are done, you should see deprecation warnings coming only -from ContactAccessorOldApi. </p> - -<p>Create a new abstract class ContactAccessor, make sure the abstract -class has all method signatures from ContactAccessorOldApi. Make -ContactAccessorOldApi extend ContactAccessor:</p> - -<pre> public abstract class ContactAccessor { - public abstract Intent getContactPickerIntent(); - ... - }</pre> - -<p>Create a new subclass of ContactAccessor, ContactAccessorNewApi and -implement all methods using the new API:</p> - -<pre> public class ContactAccessorNewApi extends ContactAccessor { - @Override - public Intent getContactPickerIntent() { - return new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); - } - ... - }</pre> - -<p>At this point, you have two implementations of the same API, one using the -old API and another using the new API. Let's plug them in. Add this code to -the ContactAccessor class:</p> - -<pre> private static ContactAccessor sInstance; - - public static ContactAccessor getInstance() { - if (sInstance == null) { - String className; - int sdkVersion = Integer.parseInt(Build.VERSION.SDK); - if (sdkVersion < Build.VERSION_CODES.ECLAIR) { - className = "ContactAccessorOldApi"; - } else { - className = "ContactAccessorNewApi"; - } - try { - Class<? extends ContactAccessor> clazz = - Class.forName(ContactAccessor.class.getPackage() + "." + className) - .asSubclass(ContactAccessor.class); - sInstance = clazz.newInstance(); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - return sInstance; - }</pre> - -<p>Now replace references to ContactsAccessorOldApi with references to -ContactsAccessor:</p> - -<pre> private final ContactAccessor mContactAccessor = ContactAccessor.getInstance();</pre> - -<p>You are done! Now you will want to test on Android 2.0, 1.6 and 1.5.</p> - -<p>We hope you like the new features and APIs we've added to Contacts in -Android 2.0, and we can't wait to see what cool things developers do with -the new APIs.</p> diff --git a/docs/html/resources/articles/creating-input-method.jd b/docs/html/resources/articles/creating-input-method.jd deleted file mode 100644 index 84c2704..0000000 --- a/docs/html/resources/articles/creating-input-method.jd +++ /dev/null @@ -1,528 +0,0 @@ -page.title=Creating an Input Method -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -<div id="qv-wrapper"> -<div id="qv"> -<h2>See also</h2> -<ol> - <li> - <a href="{@docRoot}resources/articles/on-screen-inputs.html">Onscreen Input Methods</a> - </li> - <li> - <a href="{@docRoot}resources/samples/SoftKeyboard/index.html">Soft Keyboard sample</a> - </li> -</ol> -</div> -</div> -<p> - An input method editor (IME) is a user control that enables users to enter text. Android - provides an extensible input method framework that allows applications to provide users - alternative input methods, such as on-screen keyboards or even speech input. Once installed, - users can select which IME they want to use from the system settings and use it across the - entire system; only one IME may be enabled at a time. -</p> -<p> - To add an IME to the Android system, you create an Android application - containing a class that extends {@link android.inputmethodservice.InputMethodService}. In - addition, you usually create a "settings" activity that passes options to the IME - service. You can also define a settings UI that's displayed as part of the system settings. -</p> -<p>This article covers the following:</p> -<ul> - <li>The IME lifecycle.</li> - <li>Declaring IME components in the application manifest.</li> - <li>The IME API.</li> - <li>Designing an IME UI.</li> - <li>Sending text from an IME to an application.</li> - <li>Working with IME subtypes.</li> -</ul> -<p> - If you haven't worked with IMEs before, you should read the introductory article - <a href="{@docRoot}resources/articles/on-screen-inputs.html">Onscreen Input Methods</a> first. - Also, the Soft Keyboard sample app included in the SDK contains sample code that you can modify - to start building your own IME. -</p> -<h2 id="InputMethodLifecycle">The IME Lifecycle</h2> -<p> - The following diagram describes the life cycle of an IME: -</p> -<img src="{@docRoot}resources/articles/images/inputmethod_lifecycle_image.png" alt="" height="845" - id="figure1" /> -<p class="img-caption"> - <strong>Figure 1.</strong> The life cycle of an IME. -</p> -<p> - The following sections describe how to implement the UI and code associated with an IME that - follows this lifecycle. -</p> -<h2 id="DefiningIME">Declaring IME Components in the Manifest</h2> -<p> - In the Android system, an IME is an Android application that contains a special IME service. - The application's manifest file must declare the service, request the necessary permissions, - provide an intent filter that matches the action <code>action.view.InputMethod</code>, and - provide metadata that defines characteristics of the IME. In addition, to provide a settings - interface that allows the user to modify the behavior of the IME, you can define a "settings" - activity that can be launched from System Settings. -</p> -<p> - The following snippet declares IME service. It requests the permission {@link - android.Manifest.permission#BIND_INPUT_METHOD} to allow the service to connect the IME to - the system, sets up an intent filter that matches the action - <code>android.view.InputMethod</code>, and defines metadata for the IME: -</p> -<pre> -<!-- Declares the input method service --> - <service android:name="FastInputIME" - android:label="@string/fast_input_label" - android:permission="android.permission.BIND_INPUT_METHOD"> - <intent-filter> - <action android:name="android.view.InputMethod" /> - </intent-filter> - <meta-data android:name="android.view.im" android:resource="@xml/method" /> - </service> -</pre> -<p> - This next snippet declares the settings activity for the IME. It has an intent filter for - {@link android.content.Intent#ACTION_MAIN} that indicates this activity is the main entry point - for the IME application:</p> -<pre> - <!-- Optional: an activity for controlling the IME settings --> - <activity android:name="FastInputIMESettings" - android:label="@string/fast_input_settings"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - </intent-filter> - </activity> -</pre> -<p> - You can also provide access to the IME's settings directly from its UI. -</p> -<h2 id="IMEAPI">The Input Method API</h2> -<p> - Classes specific to IMEs are found in the {@link android.inputmethodservice} and {@link - android.view.inputmethod} packages. The {@link android.view.KeyEvent} class is important for - handling keyboard characters. -</p> -<p> - The central part of an IME is a service component, a class that extends - {@link android.inputmethodservice.InputMethodService}. In addition to implementing the - normal service lifecycle, this class has callbacks for providing your IME's UI, handling user - input, and delivering text to the field that currently has focus. By default, the - {@link android.inputmethodservice.InputMethodService} class provides most of the implementation - for managing the state and visibility of the IME and communicating with the current - input field. -</p> -<p> - The following classes are also important: -</p> -<dl> - <dt>{@link android.view.inputmethod.BaseInputConnection}</dt> - <dd> - Defines the communication channel from an {@link android.view.inputmethod.InputMethod} - back to the application that is receiving its input. You use it to read text around the - cursor, commit text to the text box, and send raw key events to the application. - Applications should extend this class rather than implementing the base interface - {@link android.view.inputmethod.InputConnection}. - </dd> - <dt>{@link android.inputmethodservice.KeyboardView}</dt> - <dd> - An extension of {@link android.view.View} that renders a keyboard and responds to user - input events. The keyboard layout is specified by an instance of - {@link android.inputmethodservice.Keyboard}, which you can define in an XML file. - </dd> -</dl> -<h2 id="IMEUI">Designing the Input Method UI</h2> -<p> - There are two main visual elements for an IME: the <strong>input</strong> view and the - <strong>candidates</strong> view. You only have to implement the elements that are relevant to - the input method you're designing. -</p> -<h3 id="InputView">Input view</h3> -<p> - The input view is the UI where the user inputs text, in the form of keyclicks, handwriting or - gestures. When the iIME is displayed for the first time, the system calls the - {@link android.inputmethodservice.InputMethodService#onCreateInputView()} callback. In your - implementation of this method, you create the layout you want to display in the IME - window and return the layout to the system. This snippet is an example of implementing the - {@link android.inputmethodservice.InputMethodService#onCreateInputView()} method: -<pre> - @Override - public View onCreateInputView() { - MyKeyboardView inputView = - (MyKeyboardView) getLayoutInflater().inflate( R.layout.input, null); - - inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(mLatinKeyboard); - - return mInputView; - } -</pre> -<p> - In this example, {@code MyKeyboardView} is an instance of a custom implementation of - {@link android.inputmethodservice.KeyboardView} that renders a - {@link android.inputmethodservice.Keyboard}. If you’re building a traditional QWERTY keyboard, - see the <a href=”{@docRoot}resources/samples/SoftKeyboard/index.html”>Soft Keyboard</a> sample - app for an example of how to extend the {@link android.inputmethodservice.KeyboardView} class. -</p> -<h3 id="CandidateView">Candidates view</h3> -<p> - The candidates view is the UI where the IME displays potential word corrections or - suggestions for the user to select. In the IME lifecycle, the system calls - {@link android.inputmethodservice.InputMethodService#onCreateCandidatesView()} when it's ready - to display the candidate view. In your implementation of this method, return a layout that shows - word suggestions, or return null if you don’t want to show anything (a null response is the - default behavior, so you don’t have to implement this if you don’t provide suggestions).</p> -<p> - For an example implementation that provides user suggestions, see the - <a href=”{@docRoot}resources/samples/SoftKeyboard/index.html”>Soft Keyboard</a> sample app. -</p> -<h3 id="DesignConsiderations">UI design considerations</h3> -<p> - This section describes some specific UI design considerations for IMEs. -</p> -<h4>Handling multiple screen sizes</h4> -<p> - The UI for your IME must be able to scale for different screen sizes, and it also - must handle both landscape and portrait orientations. In non-fullscreen IME mode, leave - sufficient space for the application to show the text field and any associated context, so that - no more than half the screen is occupied by the IME. In fullscreen IME mode this is not an - issue. -</p> -<h4>Handling different input types</h4> -<p> - Android text fields allow you to set a specific input type, such as free form text, numbers, - URLs, email addresses, and search strings. When you implement a new IME, you need to - detect the input type of each field and provide the appropriate interface for it. However, you - don't have to set up your IME to check that the user entered text that's valid for the - input type; that's the responsibility of the application that owns the text field. -</p> -<p> - For example, here are screenshots of the interfaces that the Latin IME provided with the - Android platform provides for text and phone number inputs: -</p> -<img src="{@docRoot}resources/articles/images/inputmethod_text_type_screenshot.png" alt="" - height="142" id="figure2" /> -<img src="{@docRoot}resources/articles/images/inputmethod_numeric_type_screenshot.png" alt="" - height="120" id="figure2a" /> -<p class="img-caption"> - <strong>Figure 2.</strong> Latin IME input types. -</p> -<p> - When an input field receives focus and your IME starts, the system calls - {@link android.inputmethodservice.InputMethodService#onStartInputView(EditorInfo, boolean) - onStartInputView()}, passing in an {@link android.view.inputmethod.EditorInfo} object that - contains details about the input type and other attributes of the text field. In this object, - the {@link android.view.inputmethod.EditorInfo#inputType} field contains the text field's input - type. -</p> -<p> - The {@link android.view.inputmethod.EditorInfo#inputType} field is an <code>int</code> - that contains bit patterns for various input type settings. To test it for the text field's - input type, mask it with the constant {@link android.text.InputType#TYPE_MASK_CLASS}, like - this: -</p> -<pre> -inputType & InputType.TYPE_MASK_CLASS -</pre> -<p> -The input type bit pattern can have one of several values, including: -</p> -<dl> - <dt>{@link android.text.InputType#TYPE_CLASS_NUMBER}</dt> - <dd> - A text field for entering numbers. As illustrated in the previous screen shot, the - Latin IME displays a number pad for fields of this type. - </dd> - <dt>{@link android.text.InputType#TYPE_CLASS_DATETIME}</dt> - <dd> - A text field for entering a date and time. - </dd> - <dt>{@link android.text.InputType#TYPE_CLASS_PHONE}</dt> - <dd> - A text field for entering telephone numbers. - </dd> - <dt>{@link android.text.InputType#TYPE_CLASS_TEXT}</dt> - <dd> - A text field for entering all supported characters. - </dd> -</dl> -<p> - These constants are described in more detail in the reference documentation for - {@link android.text.InputType}. -</p> -<p> - The {@link android.view.inputmethod.EditorInfo#inputType} field can contain other bits that - indicate a variant of the text field type, such as: -</p> -<dl> - <dt>{@link android.text.InputType#TYPE_TEXT_VARIATION_PASSWORD}</dt> - <dd> - A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for entering passwords. The - input method will display dingbats instead of the actual text. - </dd> - <dt>{@link android.text.InputType#TYPE_TEXT_VARIATION_URI}</dt> - <dd> - A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for entering web URLs and - other Uniform Resource Identifiers (URIs). - </dd> - <dt>{@link android.text.InputType#TYPE_TEXT_FLAG_AUTO_COMPLETE}</dt> - <dd> - A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for entering text that the - application "auto-completes" from a dictionary, search, or other facility. - </dd> -</dl> -<p> - Remember to mask {@link android.view.inputmethod.EditorInfo#inputType} with the appropriate - constant when you test for these variants. The available mask constants are listed in the - reference documentation for {@link android.text.InputType}. -</p> -<p class="caution"> - <strong>Caution:</strong> In your own IME, make sure you handle text correctly when you send it - to a password field. Hide the password in your UI both in the input view and in the candidates - view. Also remember that you shouldn't store passwords on a device. To learn more, see the <a - href="{@docRoot}guide/practices/security.html">Designing for Security</a> guide. -</p> -<h2 id="SendText">Sending Text to the Application</h2> -<p> - As the user inputs text with your IME, you can send text to the application by - sending individual key events or by editing the text around the cursor in the application's text - field. In either case, you use an instance of {@link android.view.inputmethod.InputConnection} - to deliver the text. To get this instance, call - {@link android.inputmethodservice.InputMethodService#getCurrentInputConnection - InputMethodService.getCurrentInputConnection()}. -</p> -<h3 id="EditingCursor">Editing the text around the cursor</h3> -<p> - When you're handling the editing of existing text in a text field, some of the more useful - methods in {@link android.view.inputmethod.BaseInputConnection} are: -</p> -<dl> - <dt> - {@link android.view.inputmethod.BaseInputConnection#getTextBeforeCursor(int, int) - getTextBeforeCursor()}</dt> - <dd> - Returns a {@link java.lang.CharSequence} containing the number of requested characters - before the current cursor position. - </dd> - <dt> - {@link android.view.inputmethod.BaseInputConnection#getTextAfterCursor(int, int) - getTextAfterCursor()} - </dt> - <dd> - Returns a {@link java.lang.CharSequence} containing the number of requested characters - following the current cursor position. - </dd> - <dt> - {@link android.view.inputmethod.BaseInputConnection#deleteSurroundingText(int, int) - deleteSurroundingText()} - </dt> - <dd> - Deletes the specified number of characters before and following the current cursor - position. - </dd> - <dt> - {@link android.view.inputmethod.BaseInputConnection#commitText(CharSequence, int) - commitText()} - </dt> - <dd> - Commit a {@link java.lang.CharSequence} to the text field and set a new cursor - position. - </dd> -</dl> -<p> - For example, the following snippet shows how to replace the text "Fell" to the left of the - with the text "Hello!": -</p> -<pre> - InputConnection ic = getCurrentInputConnection(); - - ic.deleteSurroundingText(4, 0); - - ic.commitText("Hello", 1); - - ic.commitText("!", 1); -</pre> -<h3 id="ComposeThenCommit">Composing text before committing</h3> -<p> - If your IME does text prediction or requires multiple steps to compose a glyph or - word, 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. You may give special treatment to - the text by adding a "span" to it when you pass it to InputConnection#setComposingText(). -</p> -<p> - The following snippet shows how to show progress in a text field: -</p> -<pre> - InputConnection ic = getCurrentInputConnection(); - - ic.setComposingText("Composi", 1); -... - - ic.setComposingText("Composin", 1); - -... - - ic.commitText("Composing ", 1); -</pre> -<p> - The following screenshots show how this appears to the user: -</p> -<img src="{@docRoot}resources/articles/images/inputmethod_composing_text_1.png" alt="" height="54" - id="figure3a" /> -<img src="{@docRoot}resources/articles/images/inputmethod_composing_text_2.png" alt="" height="53" - id="figure3b" /> -<img src="{@docRoot}resources/articles/images/inputmethod_composing_text_3.png" alt="" height="31" - id="figure3c" /> -<p class="img-caption"> - <strong>Figure 3.</strong> Composing text before committing. -</p> -<h3 id="HardwareKeyEvents">Intercepting hardware key events</h3> -<p> - Even though the input method window doesn't have explicit focus, it receives hardware key - events first and can choose to consume them or forward them along to the application. For - example, you may want to consume the directional keys to navigate within your UI for candidate - selection during composition. You may also want to trap the back key to dismiss any popups - originating from the input method window.</p> -<p> - To intercept hardware keys, override - {@link android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent) onKeyDown()} - and {@link android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent) onKeyUp()}. - See the <a href=”{@docRoot}resources/samples/SoftKeyboard/index.html”>Soft Keyboard</a> sample - app for an example. -</p> -<p> - Remember to call the <code>super()</code> method for keys you don't want to handle yourself. -</p> -<h2 id="IMESubTypes">Creating an IME Subtype</h2> -<p> - Subtypes allow the IME to expose multiple input modes and languages supported by an IME. A - subtype can represent: -</p> -<ul> - <li>A locale such as en_US or fr_FR</li> - <li>An input mode such as voice, keyboard, or handwriting</li> - <li> - Other input styles, forms, or properties specific to the IME, such as 10-key or qwerty - keyboard layouts. - </li> -</ul> -<p> - Basically, the mode can be any text such as "keyboard", "voice", and so forth. -</p> -<p>A subtype can also expose a combination of these.</p> -<p> - Subtype information is used for an IME switcher dialog that's available from the notification - bar and also for IME settings. The information also allows the framework to bring up a - specific subtype of an IME directly. When you build an IME, use the subtype facility, because - it helps the user identify and switch between different IME languages and modes. -</p> -<p> - You define subtypes in one of the input method's XML resource files, using the - <code><subtype></code> element. The following snippet defines an IME with two - subtypes: a keyboard subtype for the US English locale, and another keyboard subtype for the - French language locale for France: -</p> -<pre> -<input-method xmlns:android="http://schemas.android.com/apk/res/android" - android:settingsActivity="com.example.softkeyboard.Settings" - android:icon="@drawable/ime_icon" - <subtype android:name="@string/display_name_english_keyboard_ime" - android:icon="@drawable/subtype_icon_english_keyboard_ime" - android:imeSubtypeLanguage="en_US" - android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="somePrivateOption=true" - /> - <subtype android:name="@string/display_name_french_keyboard_ime" - android:icon="@drawable/subtype_icon_french_keyboard_ime" - android:imeSubtypeLanguage="fr_FR" - android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="foobar=30,someInternalOption=false" - /> - <subtype android:name="@string/display_name_german_keyboard_ime" - ... - /> -/> -</pre> -<p> - To ensure that your subtypes are labeled correctly in the UI, use %s to get a subtype label - that is the same as the subtype’s locale label. This is demonstrated in the next two snippets. - The first snippet shows part of the input method's XML file: -</p> -<pre> - <subtype - android:label="@string/label_subtype_generic" - android:imeSubtypeLocale="en_US" - android:icon="@drawable/icon_en_us" - android:imeSubtypeMode="keyboard" /> -</pre> -<p> - The next snippet is part of the IME's <code>strings.xml</code> file. The string - resource <code>label_subtype_generic</code>, which is used by the input method UI definition to - set the subtype's label, is defined as: -</p> -<pre> -<string name="label_subtype_generic">%s</string> -</pre> -<p> - This sets the subtype’s display name to “English (United States)” in any English language - locale, or to the appropriate localization in other locales. -</p> -<h3 id="SubtypeProcessing">Choosing IME subtypes from the notification bar</h3> -<p> - The Android system manages all subtypes exposed by all IMEs. IME subtypes are - treated as modes of the IME they belong to. In the notification bar, a user can select an - available subtype for the currently-set IME, as shown in the following screenshot: -</p> -<img src="{@docRoot}resources/articles/images/inputmethod_subtype_notification.png" alt="" - height="85" id="figure4" /> -<p class="img-caption"> - <strong>Figure 4.</strong> Choosing an IME subtype from the notification bar. -</p> -<img src="{@docRoot}resources/articles/images/inputmethod_subtype_preferences.png" alt="" - height="165" id="figure5" /> -<p class="img-caption"> - <strong>Figure 5.</strong> Setting subtype preferences in System Settings. -</p> -<h3 id="SubtypeSettings">Choosing IME subtypes from System Settings</h3> -<p> - A user can control how subtypes are used in the “Language & input” settings panel in the - System Settings area. In the Soft Keyboard sample, the file - <code>InputMethodSettingsFragment.java</code> contains an implementation that - facilitates a subtype enabler in the IME settings. Please refer to the SoftKeyboard sample in - the Android SDK for more information about how to support Input Method Subtypes in your IME. -</p> -<img src="{@docRoot}resources/articles/images/inputmethod_subtype_settings.png" alt="" - height="210" id="figure6" /> -<p class="img-caption"> - <strong>Figure 6.</strong> Choosing a language for the IME. -</p> -<h2 id="GeneralDesign">General IME Considerations</h2> -<p> - Here are some other things to consider as you're implementing your IME: -</p> -<ul> -<li> - Provide a way for users to set options directly from the IME's UI. -</li> -<li> - Because multiple IMEs may be installed on the device, provide a way for the user to switch to a - different IME directly from the input method UI. -</li> -<li> - Bring up the IME's UI quickly. Preload or load on demand any large resources so that users - see the IME as soon as they tap on a text field. Cache resources and views for subsequent - invocations of the input method. -</li> -<li> - Conversely, you should release large memory allocations 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 IME is in a hidden state for a few seconds. -</li> -<li> - Make sure that users can enter as many characters as possible for the language or locale - associated with the IME. Remember that users may use punctuation in passwords or user - names, so your IME has to provide many different characters to allow users to enter a - password and get access to the device. -</li> -</ul> diff --git a/docs/html/resources/articles/drawable-mutations.jd b/docs/html/resources/articles/drawable-mutations.jd deleted file mode 100644 index c5818fc..0000000 --- a/docs/html/resources/articles/drawable-mutations.jd +++ /dev/null @@ -1,93 +0,0 @@ -page.title=Drawable Mutations -parent.title=Articles -parent.link=../browser.html?tag=article -@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 deleted file mode 100644 index e7b73bf..0000000 --- a/docs/html/resources/articles/faster-screen-orientation-change.jd +++ /dev/null @@ -1,133 +0,0 @@ -page.title=Faster Screen Orientation Change -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime -Changes</a></li> - </ol> - -</div> -</div> - -<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/#git%2FPhotostream%2Fsrc%2Fcom%2Fgoogle%2Fandroid%2Fphotostream">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 to <em>your future self</em> and Android -is smart enough to call this method only when needed. In the case of Photostream, -the application used this method -to pass the downloaded images to the future activity on orientation change. -The implementation can be summarized like so:</p> - -<pre class="prettyprint">@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, this method is invoked -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> - -<p>Also read the guide to <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime -Changes</a>.</p> diff --git a/docs/html/resources/articles/future-proofing.jd b/docs/html/resources/articles/future-proofing.jd deleted file mode 100644 index b8aeedf..0000000 --- a/docs/html/resources/articles/future-proofing.jd +++ /dev/null @@ -1,91 +0,0 @@ -page.title=Future-Proofing Your Apps -parent.title=Articles -parent.link=../browser.html?tag=article -@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 deleted file mode 100644 index 5b8d760..0000000 --- a/docs/html/resources/articles/gestures.jd +++ /dev/null @@ -1,213 +0,0 @@ -page.title=Gestures -parent.title=Articles -parent.link=../browser.html?tag=article -@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&can=2&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><android.gesture.GestureOverlayView - android:id="@+id/gestures" - android:layout_width="fill_parent" - android:layout_height="0dip" - android:layout_weight="1.0" /></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<prediction> predictions = mLibrary.recognize(gesture); - - // We want at least one prediction - if (predictions.size() > 0) { - Prediction prediction = predictions.get(0); - // We want at least some confidence in the result - if (prediction.score > 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><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"> - - <ListView - android:id="@android:id/list" - android:layout_width="fill_parent" - android:layout_height="fill_parent" /> - -</android.gesture.GestureOverlayView></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<Prediction> predictions = mLibrary.recognize(gesture); - if (predictions.size() > 0 && predictions.get(0).score > 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 deleted file mode 100644 index 45407a9..0000000 --- a/docs/html/resources/articles/glsurfaceview.jd +++ /dev/null @@ -1,270 +0,0 @@ -page.title=Introducing GLSurfaceView -parent.title=Articles -parent.link=../browser.html?tag=article -@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&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 { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mGLView = new GLSurfaceView(this); - mGLView.setRenderer(new ClearRenderer()); - setContentView(mGLView); - } - - @Override - protected void onPause() { - super.onPause(); - mGLView.onPause(); - } - - @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 { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mGLView = new ClearGLSurfaceView(this); - setContentView(mGLView); - } - - @Override - protected void onPause() { - super.onPause(); - mGLView.onPause(); - } - - @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 Binary files differdeleted file mode 100644 index bc5a2b8..0000000 --- a/docs/html/resources/articles/images/File.png +++ /dev/null diff --git a/docs/html/resources/articles/images/File_002.png b/docs/html/resources/articles/images/File_002.png Binary files differdeleted file mode 100644 index 39254b30..0000000 --- a/docs/html/resources/articles/images/File_002.png +++ /dev/null diff --git a/docs/html/resources/articles/images/JFlubber.png b/docs/html/resources/articles/images/JFlubber.png Binary files differdeleted file mode 100644 index d95e32b..0000000 --- a/docs/html/resources/articles/images/JFlubber.png +++ /dev/null diff --git a/docs/html/resources/articles/images/WikiNotes.png b/docs/html/resources/articles/images/WikiNotes.png Binary files differdeleted file mode 100644 index d52c4fc..0000000 --- a/docs/html/resources/articles/images/WikiNotes.png +++ /dev/null diff --git a/docs/html/resources/articles/images/all_drawables_changed.png b/docs/html/resources/articles/images/all_drawables_changed.png Binary files differdeleted file mode 100644 index 04ec4a2..0000000 --- a/docs/html/resources/articles/images/all_drawables_changed.png +++ /dev/null diff --git a/docs/html/resources/articles/images/android.png b/docs/html/resources/articles/images/android.png Binary files differdeleted file mode 100644 index 6dc88cc..0000000 --- a/docs/html/resources/articles/images/android.png +++ /dev/null diff --git a/docs/html/resources/articles/images/buttons.png b/docs/html/resources/articles/images/buttons.png Binary files differdeleted file mode 100644 index 8c220b9..0000000 --- a/docs/html/resources/articles/images/buttons.png +++ /dev/null diff --git a/docs/html/resources/articles/images/contacts-2.png b/docs/html/resources/articles/images/contacts-2.png Binary files differdeleted file mode 100644 index 02f28aa..0000000 --- a/docs/html/resources/articles/images/contacts-2.png +++ /dev/null diff --git a/docs/html/resources/articles/images/contacts.png b/docs/html/resources/articles/images/contacts.png Binary files differdeleted file mode 100644 index d8b067d..0000000 --- a/docs/html/resources/articles/images/contacts.png +++ /dev/null diff --git a/docs/html/resources/articles/images/correct_drawables.png b/docs/html/resources/articles/images/correct_drawables.png Binary files differdeleted file mode 100644 index 516309b..0000000 --- a/docs/html/resources/articles/images/correct_drawables.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ddms_allocation_tracker.png b/docs/html/resources/articles/images/ddms_allocation_tracker.png Binary files differdeleted file mode 100644 index b9fa0a1..0000000 --- a/docs/html/resources/articles/images/ddms_allocation_tracker.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ddms_allocation_trackerl.png b/docs/html/resources/articles/images/ddms_allocation_trackerl.png Binary files differdeleted file mode 100644 index 5ac8d2a..0000000 --- a/docs/html/resources/articles/images/ddms_allocation_trackerl.png +++ /dev/null diff --git a/docs/html/resources/articles/images/device.png b/docs/html/resources/articles/images/device.png Binary files differdeleted file mode 100644 index 186b960..0000000 --- a/docs/html/resources/articles/images/device.png +++ /dev/null diff --git a/docs/html/resources/articles/images/device_002.png b/docs/html/resources/articles/images/device_002.png Binary files differdeleted file mode 100644 index 4bc3b0c..0000000 --- a/docs/html/resources/articles/images/device_002.png +++ /dev/null diff --git a/docs/html/resources/articles/images/gestures.png b/docs/html/resources/articles/images/gestures.png Binary files differdeleted file mode 100644 index fe8f7cd..0000000 --- a/docs/html/resources/articles/images/gestures.png +++ /dev/null diff --git a/docs/html/resources/articles/images/gestures_002.png b/docs/html/resources/articles/images/gestures_002.png Binary files differdeleted file mode 100644 index b20da98..0000000 --- a/docs/html/resources/articles/images/gestures_002.png +++ /dev/null diff --git a/docs/html/resources/articles/images/gestures_003.png b/docs/html/resources/articles/images/gestures_003.png Binary files differdeleted file mode 100644 index a295939..0000000 --- a/docs/html/resources/articles/images/gestures_003.png +++ /dev/null diff --git a/docs/html/resources/articles/images/gestures_004.png b/docs/html/resources/articles/images/gestures_004.png Binary files differdeleted file mode 100644 index 3fe5fb1..0000000 --- a/docs/html/resources/articles/images/gestures_004.png +++ /dev/null diff --git a/docs/html/resources/articles/images/gestures_005.png b/docs/html/resources/articles/images/gestures_005.png Binary files differdeleted file mode 100644 index 3efc519..0000000 --- a/docs/html/resources/articles/images/gestures_005.png +++ /dev/null diff --git a/docs/html/resources/articles/images/gestures_006.png b/docs/html/resources/articles/images/gestures_006.png Binary files differdeleted file mode 100644 index 399c31d..0000000 --- a/docs/html/resources/articles/images/gestures_006.png +++ /dev/null diff --git a/docs/html/resources/articles/images/grid.png b/docs/html/resources/articles/images/grid.png Binary files differdeleted file mode 100644 index 4713de5..0000000 --- a/docs/html/resources/articles/images/grid.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ime.png b/docs/html/resources/articles/images/ime.png Binary files differdeleted file mode 100644 index 57f6df1..0000000 --- a/docs/html/resources/articles/images/ime.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ime_002.png b/docs/html/resources/articles/images/ime_002.png Binary files differdeleted file mode 100644 index 3ec00b2..0000000 --- a/docs/html/resources/articles/images/ime_002.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ime_003.png b/docs/html/resources/articles/images/ime_003.png Binary files differdeleted file mode 100644 index a3f57bb..0000000 --- a/docs/html/resources/articles/images/ime_003.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ime_004.png b/docs/html/resources/articles/images/ime_004.png Binary files differdeleted file mode 100644 index efeddf0..0000000 --- a/docs/html/resources/articles/images/ime_004.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ime_005.png b/docs/html/resources/articles/images/ime_005.png Binary files differdeleted file mode 100644 index a7394e0..0000000 --- a/docs/html/resources/articles/images/ime_005.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ime_006.png b/docs/html/resources/articles/images/ime_006.png Binary files differdeleted file mode 100644 index 0b55c79..0000000 --- a/docs/html/resources/articles/images/ime_006.png +++ /dev/null diff --git a/docs/html/resources/articles/images/layouts_comparison_small.png b/docs/html/resources/articles/images/layouts_comparison_small.png Binary files differdeleted file mode 100644 index 0ba4cb8..0000000 --- a/docs/html/resources/articles/images/layouts_comparison_small.png +++ /dev/null diff --git a/docs/html/resources/articles/images/list01.png b/docs/html/resources/articles/images/list01.png Binary files differdeleted file mode 100644 index e1b7fa8..0000000 --- a/docs/html/resources/articles/images/list01.png +++ /dev/null diff --git a/docs/html/resources/articles/images/list02.png b/docs/html/resources/articles/images/list02.png Binary files differdeleted file mode 100644 index 7f72a3f..0000000 --- a/docs/html/resources/articles/images/list02.png +++ /dev/null diff --git a/docs/html/resources/articles/images/list_fade_1.png b/docs/html/resources/articles/images/list_fade_1.png Binary files differdeleted file mode 100644 index 43013d6..0000000 --- a/docs/html/resources/articles/images/list_fade_1.png +++ /dev/null diff --git a/docs/html/resources/articles/images/list_fade_2.png b/docs/html/resources/articles/images/list_fade_2.png Binary files differdeleted file mode 100644 index 160d3ff..0000000 --- a/docs/html/resources/articles/images/list_fade_2.png +++ /dev/null diff --git a/docs/html/resources/articles/images/list_fade_3.png b/docs/html/resources/articles/images/list_fade_3.png Binary files differdeleted file mode 100644 index 70dca64..0000000 --- a/docs/html/resources/articles/images/list_fade_3.png +++ /dev/null diff --git a/docs/html/resources/articles/images/list_fade_4.png b/docs/html/resources/articles/images/list_fade_4.png Binary files differdeleted file mode 100644 index 7619fca..0000000 --- a/docs/html/resources/articles/images/list_fade_4.png +++ /dev/null diff --git a/docs/html/resources/articles/images/live_wallpapers_small.png b/docs/html/resources/articles/images/live_wallpapers_small.png Binary files differdeleted file mode 100644 index 3b49b24..0000000 --- a/docs/html/resources/articles/images/live_wallpapers_small.png +++ /dev/null diff --git a/docs/html/resources/articles/images/merge1.jpg b/docs/html/resources/articles/images/merge1.jpg Binary files differdeleted file mode 100644 index 114eed6..0000000 --- a/docs/html/resources/articles/images/merge1.jpg +++ /dev/null diff --git a/docs/html/resources/articles/images/merge2.png b/docs/html/resources/articles/images/merge2.png Binary files differdeleted file mode 100644 index b4a8d4c..0000000 --- a/docs/html/resources/articles/images/merge2.png +++ /dev/null diff --git a/docs/html/resources/articles/images/merge3.png b/docs/html/resources/articles/images/merge3.png Binary files differdeleted file mode 100644 index 61ed983..0000000 --- a/docs/html/resources/articles/images/merge3.png +++ /dev/null diff --git a/docs/html/resources/articles/images/merge4.jpg b/docs/html/resources/articles/images/merge4.jpg Binary files differdeleted file mode 100644 index 17b6c20..0000000 --- a/docs/html/resources/articles/images/merge4.jpg +++ /dev/null diff --git a/docs/html/resources/articles/images/merge5.png b/docs/html/resources/articles/images/merge5.png Binary files differdeleted file mode 100644 index 289f47e..0000000 --- a/docs/html/resources/articles/images/merge5.png +++ /dev/null diff --git a/docs/html/resources/articles/images/mutated_states.png b/docs/html/resources/articles/images/mutated_states.png Binary files differdeleted file mode 100644 index 50518b6..0000000 --- a/docs/html/resources/articles/images/mutated_states.png +++ /dev/null diff --git a/docs/html/resources/articles/images/on-screen-inputs.png b/docs/html/resources/articles/images/on-screen-inputs.png Binary files differdeleted file mode 100644 index b8b3cf7..0000000 --- a/docs/html/resources/articles/images/on-screen-inputs.png +++ /dev/null diff --git a/docs/html/resources/articles/images/on-screen-inputs_002.png b/docs/html/resources/articles/images/on-screen-inputs_002.png Binary files differdeleted file mode 100644 index a5d21c7..0000000 --- a/docs/html/resources/articles/images/on-screen-inputs_002.png +++ /dev/null diff --git a/docs/html/resources/articles/images/on-screen-inputs_003.png b/docs/html/resources/articles/images/on-screen-inputs_003.png Binary files differdeleted file mode 100644 index 81ee257..0000000 --- a/docs/html/resources/articles/images/on-screen-inputs_003.png +++ /dev/null diff --git a/docs/html/resources/articles/images/on-screen-inputs_004.png b/docs/html/resources/articles/images/on-screen-inputs_004.png Binary files differdeleted file mode 100644 index 651b72a..0000000 --- a/docs/html/resources/articles/images/on-screen-inputs_004.png +++ /dev/null diff --git a/docs/html/resources/articles/images/on-screen-inputs_005.png b/docs/html/resources/articles/images/on-screen-inputs_005.png Binary files differdeleted file mode 100644 index 75185ff..0000000 --- a/docs/html/resources/articles/images/on-screen-inputs_005.png +++ /dev/null diff --git a/docs/html/resources/articles/images/on-screen-inputs_006.png b/docs/html/resources/articles/images/on-screen-inputs_006.png Binary files differdeleted file mode 100644 index b653d75..0000000 --- a/docs/html/resources/articles/images/on-screen-inputs_006.png +++ /dev/null diff --git a/docs/html/resources/articles/images/photostream_landscape.png b/docs/html/resources/articles/images/photostream_landscape.png Binary files differdeleted file mode 100644 index ad4a0c5..0000000 --- a/docs/html/resources/articles/images/photostream_landscape.png +++ /dev/null diff --git a/docs/html/resources/articles/images/photostream_portrait.png b/docs/html/resources/articles/images/photostream_portrait.png Binary files differdeleted file mode 100644 index 3794f63..0000000 --- a/docs/html/resources/articles/images/photostream_portrait.png +++ /dev/null diff --git a/docs/html/resources/articles/images/qsb.png b/docs/html/resources/articles/images/qsb.png Binary files differdeleted file mode 100644 index 4e40af1..0000000 --- a/docs/html/resources/articles/images/qsb.png +++ /dev/null diff --git a/docs/html/resources/articles/images/qsb_002.png b/docs/html/resources/articles/images/qsb_002.png Binary files differdeleted file mode 100644 index 8c2f772..0000000 --- a/docs/html/resources/articles/images/qsb_002.png +++ /dev/null diff --git a/docs/html/resources/articles/images/qsb_003.png b/docs/html/resources/articles/images/qsb_003.png Binary files differdeleted file mode 100644 index 069b6cd..0000000 --- a/docs/html/resources/articles/images/qsb_003.png +++ /dev/null diff --git a/docs/html/resources/articles/images/relativelayout_1.png b/docs/html/resources/articles/images/relativelayout_1.png Binary files differdeleted file mode 100644 index 3360ad8..0000000 --- a/docs/html/resources/articles/images/relativelayout_1.png +++ /dev/null diff --git a/docs/html/resources/articles/images/relativelayout_2.png b/docs/html/resources/articles/images/relativelayout_2.png Binary files differdeleted file mode 100644 index 8e71bb2..0000000 --- a/docs/html/resources/articles/images/relativelayout_2.png +++ /dev/null diff --git a/docs/html/resources/articles/images/relativelayout_3.png b/docs/html/resources/articles/images/relativelayout_3.png Binary files differdeleted file mode 100644 index 16a9767..0000000 --- a/docs/html/resources/articles/images/relativelayout_3.png +++ /dev/null diff --git a/docs/html/resources/articles/images/relativelayout_wire_1.png b/docs/html/resources/articles/images/relativelayout_wire_1.png Binary files differdeleted file mode 100644 index 9cb241d..0000000 --- a/docs/html/resources/articles/images/relativelayout_wire_1.png +++ /dev/null diff --git a/docs/html/resources/articles/images/relativelayout_wire_2.png b/docs/html/resources/articles/images/relativelayout_wire_2.png Binary files differdeleted file mode 100644 index 4243812..0000000 --- a/docs/html/resources/articles/images/relativelayout_wire_2.png +++ /dev/null diff --git a/docs/html/resources/articles/images/relativelayout_wire_3.png b/docs/html/resources/articles/images/relativelayout_wire_3.png Binary files differdeleted file mode 100644 index 04ce1ce..0000000 --- a/docs/html/resources/articles/images/relativelayout_wire_3.png +++ /dev/null diff --git a/docs/html/resources/articles/images/search01.png b/docs/html/resources/articles/images/search01.png Binary files differdeleted file mode 100644 index 4160a76..0000000 --- a/docs/html/resources/articles/images/search01.png +++ /dev/null diff --git a/docs/html/resources/articles/images/search02.png b/docs/html/resources/articles/images/search02.png Binary files differdeleted file mode 100644 index 6300018..0000000 --- a/docs/html/resources/articles/images/search02.png +++ /dev/null diff --git a/docs/html/resources/articles/images/service-api-changes-starting-with_runningservices.png b/docs/html/resources/articles/images/service-api-changes-starting-with_runningservices.png Binary files differdeleted file mode 100644 index e159fff..0000000 --- a/docs/html/resources/articles/images/service-api-changes-starting-with_runningservices.png +++ /dev/null diff --git a/docs/html/resources/articles/images/service-api-changes-starting-with_stopservice.png b/docs/html/resources/articles/images/service-api-changes-starting-with_stopservice.png Binary files differdeleted file mode 100644 index cc8f0a2..0000000 --- a/docs/html/resources/articles/images/service-api-changes-starting-with_stopservice.png +++ /dev/null diff --git a/docs/html/resources/articles/images/shared_states.png b/docs/html/resources/articles/images/shared_states.png Binary files differdeleted file mode 100644 index 81bec09..0000000 --- a/docs/html/resources/articles/images/shared_states.png +++ /dev/null diff --git a/docs/html/resources/articles/images/shelves2.png b/docs/html/resources/articles/images/shelves2.png Binary files differdeleted file mode 100644 index 2de239f..0000000 --- a/docs/html/resources/articles/images/shelves2.png +++ /dev/null diff --git a/docs/html/resources/articles/images/speech-input.png b/docs/html/resources/articles/images/speech-input.png Binary files differdeleted file mode 100644 index 78fbc98..0000000 --- a/docs/html/resources/articles/images/speech-input.png +++ /dev/null diff --git a/docs/html/resources/articles/images/text_field.png b/docs/html/resources/articles/images/text_field.png Binary files differdeleted file mode 100644 index b9dedec..0000000 --- a/docs/html/resources/articles/images/text_field.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ui-1.6.png b/docs/html/resources/articles/images/ui-1.6.png Binary files differdeleted file mode 100644 index bc5a2b8..0000000 --- a/docs/html/resources/articles/images/ui-1.6.png +++ /dev/null diff --git a/docs/html/resources/articles/images/ui-1.6_002.png b/docs/html/resources/articles/images/ui-1.6_002.png Binary files differdeleted file mode 100644 index 39254b30..0000000 --- a/docs/html/resources/articles/images/ui-1.6_002.png +++ /dev/null diff --git a/docs/html/resources/articles/images/viewstub1.png b/docs/html/resources/articles/images/viewstub1.png Binary files differdeleted file mode 100644 index 2de239f..0000000 --- a/docs/html/resources/articles/images/viewstub1.png +++ /dev/null diff --git a/docs/html/resources/articles/images/viewstub2.png b/docs/html/resources/articles/images/viewstub2.png Binary files differdeleted file mode 100644 index 6e6feb9..0000000 --- a/docs/html/resources/articles/images/viewstub2.png +++ /dev/null diff --git a/docs/html/resources/articles/images/viewstub3.png b/docs/html/resources/articles/images/viewstub3.png Binary files differdeleted file mode 100644 index 5e793e6..0000000 --- a/docs/html/resources/articles/images/viewstub3.png +++ /dev/null diff --git a/docs/html/resources/articles/images/viewstub4.png b/docs/html/resources/articles/images/viewstub4.png Binary files differdeleted file mode 100644 index cffb9c6..0000000 --- a/docs/html/resources/articles/images/viewstub4.png +++ /dev/null diff --git a/docs/html/resources/articles/images/webview.png b/docs/html/resources/articles/images/webview.png Binary files differdeleted file mode 100644 index 92472af..0000000 --- a/docs/html/resources/articles/images/webview.png +++ /dev/null diff --git a/docs/html/resources/articles/images/window_background.png b/docs/html/resources/articles/images/window_background.png Binary files differdeleted file mode 100644 index 58f4f7e..0000000 --- a/docs/html/resources/articles/images/window_background.png +++ /dev/null diff --git a/docs/html/resources/articles/images/window_background_null.png b/docs/html/resources/articles/images/window_background_null.png Binary files differdeleted file mode 100644 index 83f7b45..0000000 --- a/docs/html/resources/articles/images/window_background_null.png +++ /dev/null diff --git a/docs/html/resources/articles/images/window_background_root.png b/docs/html/resources/articles/images/window_background_root.png Binary files differdeleted file mode 100644 index 95a47c0..0000000 --- a/docs/html/resources/articles/images/window_background_root.png +++ /dev/null diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd deleted file mode 100644 index 2947e4a..0000000 --- a/docs/html/resources/articles/index.jd +++ /dev/null @@ -1,168 +0,0 @@ -page.title=Technical Articles -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -<dl> - <dt><a href="{@docRoot}resources/articles/avoiding-memory-leaks.html">Avoiding Memory Leaks</a></dt> - <dd>Mobile devices often have limited memory, and memory leaks can cause your application to waste this valuable resource without your knowledge. This article provides tips to help you avoid common causes of memory leaks on the Android platform.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/backward-compatibility.html">Backward Compatibility</a></dt> - <dd>The Android platform strives to ensure backwards compatibility. However, sometimes you want to use new features which aren't supported on older platforms. This article discusses strategies for selectively using these features based on availability, allowing you to keep your applications portable across a wide range of devices.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/can-i-use-this-intent.html">Can I Use this Intent?</a></dt> - <dd>Android offers a very powerful and yet easy-to-use message type called an intent. You can use intents to turn applications into high-level libraries and make code modular and reusable. 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 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.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/creating-input-method.html">Creating an Input Method</a></dt> - <dd>Input Method Editors (IMEs) provide the mechanism for entering text into text fields and other Views. Android devices come bundled with at least one IME, but users can install additional IMEs. This article covers the basics of developing an IME for the Android platform.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/drawable-mutations.html">Drawable Mutations</a></dt> - <dd>Drawables are pluggable drawing containers that allow applications to display graphics. This article explains some common pitfalls when trying to modify the properties of multiple Drawables.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/faster-screen-orientation-change.html">Faster Screen Orientation Change</a></dt> - <dd>When an Android device changes its orientation, the default behavior is to automatically restart the current activity with a new configuration. However, this can become a bottleneck in applications that access a large amount of external data. This article discusses how to gracefully handle this situation without resorting to manually processing configuration changes.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/future-proofing.html">Future-Proofing Your Apps</a></dt> - <dd>A collection of common sense advice to help you ensure that your applications don't break when new versions of the Android platform are released.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/gestures.html">Gestures</a></dt> - <dd>Touch screens allow users to perform gestures, such as tapping, dragging, flinging, or sliding, to perform various actions. The gestures API enables your application to recognize even complicated gestures with ease. This article explains how to integrate this API into an application.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/glsurfaceview.html">Introducing GLSurfaceView</a></dt> - <dd>This article provides an overview of GLSurfaceView, a class that makes it easy to implement 2D or 3D OpenGL rendering inside of an Android application.</dd> -</dl> -<dl> - <dt> - <a href="{@docRoot}resources/articles/spell-checker-framework.jd"> - Using the Spell Checker Framework</a> - </dt> - <dd> - This article describes how to use the Spell Checker Framework to check spelling in - various ways in your application. - </dd> -</dl> -<dl> - <dt><a href="{@docRoot}resources/articles/layout-tricks-reuse.html">Layout Tricks: Creating Reusable UI Components</a></dt> - <dd>Learn how to combine multiple standard UI widgets into a single high-level component, which can be reused throughout your application.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/layout-tricks-efficiency.html">Layout Tricks: Creating Efficient Layouts</a></dt> - <dd>Learn how to optimize application layouts as this article walks you through converting a LinearLayout into a RelativeLayout, and analyzes the resulting implications on performance.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/layout-tricks-stubs.html">Layout Tricks: Using ViewStubs</a></dt> - <dd>Learn about using ViewStubs inside an application's layout in order to inflate rarely used UI elements, without the performance implications which would otherwise be caused by using the <code><include></code> tag.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/layout-tricks-merge.html">Layout Tricks: Merging Layouts</a></dt> - <dd>Learn how to use the <code><merge></code> tag in your XML layouts in order to avoid unnecessary levels of hierarchy within an application's view tree.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/listview-backgrounds.html">ListView Backgrounds: An Optimization</a></dt> - <dd>ListViews are very popular widgets within the Android framework. This article describes some of the optimizations used by the ListView widget, and how to avoid some common issues that this causes when trying to use a custom background.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/live-folders.html">Live Folders</a></dt> - <dd>Live Folders allow users to display any source of data on their home screen without launching an application. This article discusses how to export an application's data in a format suitable for display inside of a live folder.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/live-wallpapers.html">Live Wallpapers</a></dt> - <dd>Live wallpapers are richer, animated, interactive backgrounds that users can display in their home screens. Learn how to create a live wallpaper and bundle it in an application that users can install on their devices.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/on-screen-inputs.html">Onscreen Input Methods</a></dt> - <dd>The Input Method Framework (IMF) allows users to take advantage of on-screen input methods, such as software keyboards. This article provides an overview of Input Method Editors (IMEs) and how applications interact with them.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/painless-threading.html">Painless Threading</a></dt> - <dd>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.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/qsb.html">Quick Search Box</a></dt> - <dd>Quick Search Box (QSB) is a powerful, system-wide search framework. QSB makes it possible for users to quickly and easily find what they're looking for, both on their devices and on the web. This article discusses how to work with the QSB framework to add new search results for an installed application.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/touch-mode.html">Touch Mode</a></dt> - <dd>This article explains the touch mode, one of the most important principles of Android's UI toolkit. Whenever a user interacts with a device's touch screen, the system enters touch mode. While simple in concept, there are important implications touch mode that are often overlooked.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/track-mem.html">Tracking Memory Allocations</a></dt> - <dd>This article discusses how to use the Allocation Tracker tool to observe memory allocations and avoid performance problems that would otherwise be caused by ignoring the effect of Dalvik's garbage collector.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/ui-1.5.html">UI Framework Changes in Android 1.5</a></dt> - <dd>Explore the UI changes that were introduced in Android 1.5, compared with the UI provided in Android 1.0 and 1.1.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/ui-1.6.html">UI Framework Changes in Android 1.6</a></dt> - <dd>Explore the UI changes that were introduced in Android 1.6, compared with the UI provided in Android 1.5. In particular, this article discusses changes to RelativeLayouts and click listeners.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/timed-ui-updates.html">Updating the UI from a Timer</a></dt> - <dd>Learn about how to use Handlers as a more efficient replacement for java.util.Timer on the Android platform.</dd> -</dl> - -<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> - -<dl> - <dt><a href="{@docRoot}resources/articles/tts.html">Using the Contacts API</a></dt> - <dd>This article discusses the improved Contacts API introduced in Android 2.0 and how to use it to manage and integrate contacts from multiple accounts and data sources. The article also discusses techniques for using the new API on devices that support it, while maintaining backward compatibility with the old API on other devices. </dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/using-webviews.html">Using WebViews</a></dt> - <dd>WebViews allow an application to dynamically display HTML and execute JavaScript, without relinquishing control to a separate browser application. This article introduces the WebView classes and provides a sample application that demonstrates its use.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/wikinotes-linkify.html">WikiNotes: Linkify your Text!</a></dt> - <dd>This article introduces WikiNotes for Android, part of the Apps for Android 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.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/wikinotes-intents.html">WikiNotes: Routing Intents</a></dt> - <dd>This article illustrates how an application, in this case the WikiNotes sample app, can use intents to route various types of linked text to the application that handles that type of data. For example, an app can use intents to route a linked telephone number to a dialer app and a web URL to a browser.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/window-bg-speed.html">Window Backgrounds & UI Speed</a></dt> - <dd>Some Android applications need 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 perceived startup time of your activities. Both of these techniques rely on a single feature, the window's background drawable.</dd> -</dl> - -<dl> - <dt><a href="{@docRoot}resources/articles/zipalign.html">Zipalign: an Easy Optimization</a></dt> - <dd>The Android SDK includes a tool called zipalign that optimizes the way an application is packaged. Running zipalign against your application enables Android to interact with it more efficiently at run time and thus has the potential to make it and the overall system run faster. This article provides a high-level overview of the zipalign tool and its use.</dd> -</dl> diff --git a/docs/html/resources/articles/layout-tricks-efficiency.jd b/docs/html/resources/articles/layout-tricks-efficiency.jd deleted file mode 100644 index 00b4147..0000000 --- a/docs/html/resources/articles/layout-tricks-efficiency.jd +++ /dev/null @@ -1,179 +0,0 @@ -page.title=Layout Tricks: Creating Efficient Layouts -parent.title=Articles -parent.link=../browser.html?tag=article -@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 — or worse, every layout -manager — 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"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="?android:attr/listPreferredItemHeight" - - android:padding="6dip"> - - <ImageView - android:id="@+id/icon" - - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_marginRight="6dip" - - android:src="@drawable/icon" /> - - <LinearLayout - android:orientation="vertical" - - android:layout_width="0dip" - android:layout_weight="1" - android:layout_height="fill_parent"> - - <TextView - android:layout_width="fill_parent" - android:layout_height="0dip" - android:layout_weight="1" - - android:gravity="center_vertical" - android:text="My Application" /> - - <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" /> - - </LinearLayout> - -</LinearLayout></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"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="?android:attr/listPreferredItemHeight" - - android:padding="6dip"> - - <ImageView - android:id="@+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="@drawable/icon" /> - - <TextView - android:id="@+id/secondLine" - - android:layout_width="fill_parent" - android:layout_height="26dip" - - android:layout_toRightOf="@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" /> - - <TextView - android:layout_width="fill_parent" - android:layout_height="wrap_content" - - android:layout_toRightOf="@id/icon" - android:layout_alignParentRight="true" - android:layout_alignParentTop="true" - android:layout_above="@id/secondLine" - android:layout_alignWithParentIfMissing="true" - - android:gravity="center_vertical" - android:text="My Application" /> - -</RelativeLayout></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 deleted file mode 100644 index 0ca0317..0000000 --- a/docs/html/resources/articles/layout-tricks-merge.jd +++ /dev/null @@ -1,202 +0,0 @@ -page.title=Layout Tricks: Merging Layouts -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -<p>The articles showed you how to use the <code><include /></code> tag in XML layouts, to -reuse and share your layout code. This article explains the <code><merge /></code> tag and how -it complements the <code><include /></code> tag.</p> - -<p>The <code><merge /></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"><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <ImageView - android:layout_width="fill_parent" - android:layout_height="fill_parent" - - android:scaleType="center" - android:src="@drawable/golden_gate" /> - - <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" /> - -</FrameLayout></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/debugging/debugging-ui.html#hierarchyViewer">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><merge /></code> tag comes in handy. When the -{@link android.view.LayoutInflater} encounters this tag, it skips it and adds -the <code><merge /></code> children to the <code><merge /></code> -parent. Confused? Let's rewrite our previous XML layout by replacing the -<code>FrameLayout</code> with <code><merge /></code>:</p> - -<pre class="prettyprint"><merge xmlns:android="http://schemas.android.com/apk/res/android"> - - <ImageView - android:layout_width="fill_parent" - android:layout_height="fill_parent" - - android:scaleType="center" - android:src="@drawable/golden_gate" /> - - <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" /> - -</merge></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><merge /></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><merge /></code> can be useful in -other situations though. For instance, it works perfectly when combined with the -<code><include /></code> tag. You can also use <code><merge -/></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"><merge - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge"> - - <ImageView - android:layout_width="fill_parent" - android:layout_height="fill_parent" - - android:scaleType="center" - android:src="@drawable/golden_gate" /> - - <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" /> - -</merge></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><merge /></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"><merge xmlns:android="http://schemas.android.com/apk/res/android"> - <include - layout="@layout/okcancelbar_button" - android:id="@+id/okcancelbar_ok" /> - - <include - layout="@layout/okcancelbar_button" - android:id="@+id/okcancelbar_cancel" /> -</merge></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><merge /></code> tag is extremely useful and can do wonders -in your code. However, it suffers from a couple of limitations:</p> - -<ul> -<li><code><merge /></code> can only be used as the root tag of an XML layout</li> -<li>When inflating a layout starting with a <code><merge /></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 deleted file mode 100644 index 179c1d8..0000000 --- a/docs/html/resources/articles/layout-tricks-reuse.jd +++ /dev/null @@ -1,81 +0,0 @@ -page.title=Layout Tricks: Creating Reusable UI Components -parent.title=Articles -parent.link=../browser.html?tag=article -@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><requestFocus /></code>, <code><merge /></code> and -<code><include /></code>. This article shows how to use <code><include -/></code> to create pure XML visual components. For information about how to -use <code><merge /></code>, which can be particularly powerful when -combined with <code><include /></code>see the <a -href="{@docRoot}resources/articles/layout-tricks-merge.html">Merging Layouts</a> -article. </p> - -<p>The <code><include /></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"><com.android.launcher.Workspace - android:id="@+id/workspace" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - - launcher:defaultScreen="1"> - - <include android:id="@+id/cell1" layout="@layout/workspace_screen" /> - <include android:id="@+id/cell2" layout="@layout/workspace_screen" /> - <include android:id="@+id/cell3" layout="@layout/workspace_screen" /> - -</com.android.launcher.Workspace></pre> - -<p>In the <code><include /></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><include -/></code> tag. Here is an example in -which the same layout is included twice, but only the first one overrides the layout properties:</p> - -<pre> -<!-- override the layout height and width --> -<include layout="@layout/image_holder" - android:layout_height="fill_parent" - android:layout_width="fill_parent" /> -<!-- do not override layout dimensions; inherit them from image_holder --> -<include layout="@layout/image_holder" /> -</pre> - -<p class="caution"><strong>Caution:</strong> If you want to override the layout dimensions, -you must override both <code>android:layout_height</code> and -<code>android:layout_width</code>—you cannot override only the height or only the width. -If you override only one, it will not take effect. (Other layout properties, such as weight, -are still inherited from the source layout.)</p> - -<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 deleted file mode 100644 index 64f07f9..0000000 --- a/docs/html/resources/articles/layout-tricks-stubs.jd +++ /dev/null @@ -1,86 +0,0 @@ -page.title=Layout Tricks: Using ViewStubs -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -<p>Sharing and reusing UI components is very easy with Android, thanks to the <a -href="layout-tricks-reuse.html"><include /></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><include /></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.com/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"><ViewStub - android:id="@+id/stub_import" - android:inflatedId="@+id/panel_import" - - android:layout="@layout/progress_overlay" - - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="bottom" /></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"><merge /> -tag</a>.</p> diff --git a/docs/html/resources/articles/listview-backgrounds.jd b/docs/html/resources/articles/listview-backgrounds.jd deleted file mode 100644 index c4037ba..0000000 --- a/docs/html/resources/articles/listview-backgrounds.jd +++ /dev/null @@ -1,88 +0,0 @@ -page.title=ListView Backgrounds: An Optimization -parent.title=Articles -parent.link=../browser.html?tag=article -@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 — 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 deleted file mode 100644 index aeab997..0000000 --- a/docs/html/resources/articles/live-folders.jd +++ /dev/null @@ -1,170 +0,0 @@ -page.title=Live Folders -parent.title=Articles -parent.link=../browser.html?tag=article -@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><activity - android:name=".activity.BookShelfLiveFolder" - android:label="BookShelf"> - <intent-filter> - <action android:name="android.intent.action.CREATE_LIVE_FOLDER" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> -</activity></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"); - - @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<string, string=""> LIVE_FOLDER_PROJECTION_MAP; -static { - LIVE_FOLDER_PROJECTION_MAP = new HashMap<string, string="">(); - 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/live-wallpapers.jd b/docs/html/resources/articles/live-wallpapers.jd deleted file mode 100644 index 0692a62..0000000 --- a/docs/html/resources/articles/live-wallpapers.jd +++ /dev/null @@ -1,102 +0,0 @@ -page.title=Live Wallpapers -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}resources/samples/CubeLiveWallpaper/index.html">Live Wallpaper -sample</a></li> - </ol> - -</div> -</div> - -<p>Starting with Android 2.1 (API Level 7), users can now enjoy <em>live -wallpapers</em> — richer, animated, interactive backgrounds — on -their home screens. A live wallpaper is very similar to a normal Android -application and has access to all the facilities of the platform: SGL (2D -drawing), OpenGL (3D drawing), GPS, accelerometers, network access, etc. The -live wallpapers included on Nexus One demonstrate the use of some of these APIs -to create fun and interesting user experiences. For instance, the Grass -wallpaper uses the phone's location to compute sunrise and sunset times in order -to display the appropriate sky.</p> - -<img src="images/live_wallpapers_small.png" style="align:center" /> - -<p>Creating your own live wallpaper is easy, especially if you have had -previous experience with {@link android.view.SurfaceView} or {@link -android.graphics.Canvas}. -To learn how to create a live wallpaper, you should check out the <a -href="../samples/CubeLiveWallpaper/index.html">CubeLiveWallpaper sample code</a>.</p> - -<p>In terms of implementation, a live wallpaper is very similar to a {@link android.app.Service}. -The only difference is the addition of a new method, {@link -android.service.wallpaper.WallpaperService#onCreateEngine()}, whose goal is to create a {@link -android.service.wallpaper.WallpaperService.Engine}. The engine is responsible for -handling the lifecycle and drawing of a wallpaper. The system provides a surface -on which you can draw, just like you would with a {@link android.view.SurfaceView}. -Drawing a wallpaper can be very expensive so you should optimize your code -as much as possible to avoid using too much CPU, not only for battery life -but also to avoid slowing down the rest of the system. That is also why the -most important part of the lifecycle of a wallpaper is when it becomes visible, as indicated -by a call to {@link android.service.wallpaper.WallpaperService.Engine#onVisibilityChanged -onVisibilityChanged()}. -When invisible, such as when the user launches an application that covers -the home screen, a wallpaper must stop all activity.</p> - -<p>The engine can also implement several methods to interact with the user -or the home application. For instance, if you want your wallpaper to scroll -along when the user swipes from one home screen to another, you can use -{@link android.service.wallpaper.WallpaperService.Engine#onOffsetsChanged -onOffsetsChanged()}. -To react to touch events, simply implement {@link -android.service.wallpaper.WallpaperService.Engine#onTouchEvent onTouchEvent()}. -Finally, applications can send arbitrary commands to the live wallpaper. -Currently, only the standard home application sends commands to the -{@link android.service.wallpaper.WallpaperService.Engine#onCommand onCommand()} -method of the live wallpaper:</p> - -<ul> -<li><code>android.wallpaper.tap</code>: When the user taps an empty space -on the workspace. This command is interpreted by the Nexus and Water live -wallpapers to make the wallpaper react to user interaction. For instance, -if you tap an empty space on the Water live wallpaper, new ripples appear -under your finger.</li> -<li><code>android.home.drop</code>: When the user drops an icon or a widget -on the workspace. This command is also interpreted by the Nexus and Water -live wallpapers.</li> -</ul> - -<p>If you are developing a live wallpaper, remember that the feature is -supported only on Android 2.1 (API level 7) and higher versions of the platform. -To ensure that your application can only be installed on devices that support -live wallpapers, remember to add the following to the application's manifest -before publishing to Google Play:</p> - -<ul> -<li><code><uses-sdk android:minSdkVersion="7" /></code>, which indicates -to Google Play and the platform that your application requires Android 2.1 or -higher. For more information, see the <a href="{@docRoot}guide/appendix/api-levels.html">API -Levels</a> and the documentation for the -<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code><uses-sdk></code></a> -element.</li> -<li><code><uses-feature android:name="android.software.live_wallpaper" /></code>, -which tells Google Play that your application includes a live wallpaper -Google Play uses this feature as a filter, when presenting users lists of -available applications. When you declaring this feature, Google Play -displays your application only to users whose devices support live wallpapers, -while hiding it from other devices on which it would not be able to run. For -more information, see the documentation for the -<a -href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code -<uses-feature></a> -element.</li> -</ul> - -<p>Many great live wallpapers are already available on Google Play and -we can't wait to see more!</p> diff --git a/docs/html/resources/articles/multitasking-android-way.jd b/docs/html/resources/articles/multitasking-android-way.jd deleted file mode 100644 index 0dc8627..0000000 --- a/docs/html/resources/articles/multitasking-android-way.jd +++ /dev/null @@ -1,103 +0,0 @@ -page.title=Multitasking the Android Way -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a></li> - <li><a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a></li> - </ol> - - <h2>Key classes</h2> - <ol> - <li>{@link android.app.Service}</li> - <li>{@link android.content.BroadcastReceiver}</li> - </ol> - -</div> -</div> - -<p>Android is fairly unique in the ways it allows multiple applications to run at the same time. Developers coming from a different platform may find the way it operates surprising. Understanding its behavior is important for designing applications that will work well and integrate seamlessly with the rest of the Android platform. This article covers the reasons for Android's multitasking design, its impact on how applications work, and how you can best take advantage of Android's unique features.</p> -<h3>Design considerations</h3> -<p>Mobile devices have technical limitations and user experience requirements not present in desktop or web systems. Here are the four key constraints we were working under as we designed Android's multitasking:</p> -<ul> - <li> - <p>We did not want to require that users close applications when "done" with them. Such a usage pattern does not work well in a mobile environment, where usage tends to involve repeated brief contact with a wide variety of applications throughout the day.</p> - </li> - <li> - <p>Mobile devices don't have the luxury of swap space, so have fairly hard limits on memory use. Robert Love has <a href="http://blog.rlove.org/2010/04/why-ipad-and-iphone-dont-support.html">a very good article</a> covering the topic.</p> - </li> - <li> - <p>Application switching on a mobile device is extremely critical; we target significantly less than 1 second to launch a new application. This is especially important when the user is switching between a few applications, such as switching to look at a new SMS message while watching a video, and then returning to that video. A noticeable wait in such situations will quickly make users hate you.</p> - </li> - <li> - <p>The available APIs must be sufficient for writing the built-in Google applications, as part of our "all applications are created equal" philosophy. This means background music playback, data syncing, GPS navigation, and application downloading must be implemented with the same APIs that are available to third party developers.</p> - </li> -</ul> -<p>The first two requirements highlight an interesting conflict. We don't want users to worry about closing their apps, but rather make it appear that all of the applications are always running. At the same time, mobile devices have hard limits on memory use, so that a system will degrade or even start failing very quickly as it needs more RAM than is available; a desktop computer, with swap, in contrast will simply start slowing down as it needs to page RAM to its swap space. These competing constraints were a key motivation for Android's design.</p> -<h3>When does an application "stop"?</h3> -<p>A common misunderstanding about Android multitasking is the difference between a process and an application. In Android these are not tightly coupled entities: applications may seem present to the user without an actual process currently running the app; multiple applications may share processes, or one application may make use of multiple processes depending on its needs; the process(es) of an application may be kept around by Android even when that application is not actively doing something.</p> -<p>The fact that you can see an application's process "running" does not mean the application is running or doing anything. It may simply be there because Android needed it at some point, and has decided that it would be best to keep it around in case it needs it again. Likewise, you may leave an application for a little bit and return to it from where you left off, and during that time Android may have needed to get rid of the process for other things.</p> -<p>A key to how Android handles applications in this way is that processes don't shut down cleanly. When the user leaves an application, its process is kept around in the background, allowing it to continue working (for example downloading web pages) if needed, and come immediately to the foreground if the user returns to it. If a device never runs out of memory, then Android will keep all of these processes around, truly leaving all applications "running" all of the time.</p> -<p>Of course, there is a limited amount of memory, and to accommodate this Android must decide when to get rid of processes that are not needed. This leads to Android's <a href="{@docRoot}guide/topics/fundamentals.html#proclife">process lifecycle</a>, the rules it uses to decide how important each process is and thus the next one that should be dropped. These rules are based on both how important a process is for the user's current experience, as well as how long it has been since the process was last needed by the user.</p> -<p>Once Android determines that it needs to remove a process, it does this brutally, simply force-killing it. The kernel can then immediately reclaim all resources needed by the process, without relying on that application being well written and responsive to a polite request to exit. Allowing the kernel to immediately reclaim application resources makes it a lot easier to avoid serious out of memory situations.</p> -<p>If a user later returns to an application that's been killed, Android needs a way to re-launch it in the same state as it was last seen, to preserve the "all applications are running all of the time" experience. This is done by keeping track of the parts of the application the user is aware of (the Activities), and re-starting them with information about the last state they were seen in. This last state is generated each time the user leaves that part of the application, not when it is killed, so that the kernel can later freely kill it without depending on the application to respond correctly at that point.</p> -<p>In some ways, Android's process management can be seen as a form of swap space: application processes represent a certain amount of in-use memory; when memory is low, some processes can be killed (swapped out); when those processes are needed again, they can be re-started from their last saved state (swapped in).</p> -<h3>Explicitly running in the background</h3> -<p>So far, we have a way for applications to implicitly do work in the background, as long as the process doesn't get killed by Android as part of its regular memory management. This is fine for things like loading web pages in the background, but what about features with harder requirements? Background music playback, data synchronization, location tracking, alarm clocks, etc.</p> -<p/> -<p>For these tasks, the application needs a way to tell Android "I would explicitly like to run at this point." There are two main facilities available to applications for this, represented by two kinds of components they can publish in their manifest: <span style="font-style:italic;">broadcast receivers</span> and <span style="font-style:italic;">services</span>.</p> -<h4>Broadcast Receivers</h4> -<p>A BroadcastReceiver allows an application to run, for a brief amount of time, in the background as a result of something else happening. It can be used in many ways to build higher-level facilities: for example the AlarmManager allows an application to have a broadcast sent at a certain time in the future, and the LocationManager can send a broadcast when it detects interesting changes in location. Because information about the receiver is part of an application's manifest, Android can find and launch the application even if it isn't running; of course if it already has its process available in the background, the broadcast can very efficiently be directly dispatched to it.</p> -<p>When handling a broadcast, the application is given a fixed set of time (currently 10 seconds) in which to do its work. If it doesn't complete in that time, the application is considered to be misbehaving, and its process immediately tossed into the background state to be killed for memory if needed.</p> -<p>Broadcast receivers are great for doing small pieces of work in response to an external stimulus, such as posting a notification to the user after being sent a new GPS location report. They are very lightweight, since the application's process only needs to be around while actively receiving the broadcast. Because they are active for a deterministic amount of time, fairly strong guarantees can be made about not killing their process while running. However they are not appropriate for anything of indeterminate length, such as networking.</p> -<h4>Services</h4> -<p>A Service allows an application to implement longer-running background operations. There are actually a lot of other functions that services provide, but for the discussion here their fundamental purpose is for an application to say "hey I would like to continue running even while in the background, until I say I am done." An application controls when its service runs by explicitly starting and stopping the service.</p> -<p>While services do provide a rich client-server model, its use is optional. Upon starting an application's services, Android simply instantiates the component in the application's process to provide its context. How it is used after that is up to the application: it can put all of the needed code inside of the service itself without interacting with other parts of the application, make calls on other singleton objects shared with other parts of the app, directly retrieve the Service instance from elsewhere if needed, or run it in another process and do a full-blown RPC protocol if that is desired.</p> -<p>Process management for services is different than broadcast receivers, because an unbounded number of services can ask to be running for an unknown amount of time. There may not be enough RAM to have all of the requesting services run, so as a result no strong guarantees are made about being able to keep them running.</p> -<p>If there is too little RAM, processes hosting services will be immediately killed like background processes are. However, if appropriate, Android will remember that these services wish to remain running, and restart their process at a later time when more RAM is available. For example, if the user goes to a web page that requires large amounts of RAM, Android may kill background service processes like sync until the browser's memory needs go down.</p> -<p>Services can further negotiate this behavior by requesting they be considered "foreground." This places the service in a "please don't kill" state, but requires that it include a notification to the user about it actively running. This is useful for services such as background music playback or car navigation, which the user is actively aware of; when you're playing music and using the browser, you can always see the music-playing glyph in the status bar. Android won't try to kill these services, but as a trade-off, ensures the user knows about them and is able to explicitly stop them when desired.</p> -<h3>The value of generic components</h3> -<p>Android's generic broadcast receiver and service components allow developers to create a wide variety of efficient background operations, including things that were never originally considered. In Android 1.0 they were used to implement nearly all of the background behavior that the built-in and proprietary Google apps provided:</p> -<ul> - <li> - Music playback runs in a service to allow it to continue operating after the user leaves the music application. - </li> - <li> - The alarm clock schedules a broadcast receiver with the alarm manager, to go off at the next set alarm time. - </li> - <li> - The calendar application likewise schedules an alarm to display or update its notification at the appropriate time for the next calendar event. - </li> - <li> - Background file download is implemented a service that runs when there are any downloads to process. - </li> - <li> - The e-mail application schedules an alarm to wake up a service at regular intervals that looks for and retrieves any new mail. - </li> - <li> - The Google applications maintain a service to receive push notifications from the network; it in turn sends broadcasts to individual apps when it is told that they need to do things like synchronize contacts.</p> - </li> -</ul> -<p>As the platform has evolved, these same basic components have been used to implement many of the major new developer features: -<ul> - <li> - Input methods are implemented by developers as a Service component that Android manages and works with to display as the current IME. - </li> - <li> - Application widgets are broadcast receivers that Android sends broadcasts to when it needs to interact with them. This allows app widgets to be quite lightweight, by not needing their application's process remain running. - </li> - <li> - Accessibility features are implemented as services that Android keeps running while in use and sends appropriate information to about user interactions. - </li> - <li> - Sync adapters introduced in Android 2.0 are services that are run in the background when a particular data sync needs to be performed. - </li> - <li> - Live wallpapers are a service started by Android when selected by the user. - </li> -</ul> diff --git a/docs/html/resources/articles/on-screen-inputs.jd b/docs/html/resources/articles/on-screen-inputs.jd deleted file mode 100644 index 6a028c8..0000000 --- a/docs/html/resources/articles/on-screen-inputs.jd +++ /dev/null @@ -1,265 +0,0 @@ -page.title=Onscreen Input Methods -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}resources/articles/creating-input-method.html">Creating an Input -Method</a></li> - <li><a href="{@docRoot}resources/samples/SoftKeyboard/index.html">Soft Keyboard sample</a></li> - </ol> - -</div> -</div> - - -<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> <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"/></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><activity></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> <activity name="EditContactActivity" - android:windowSoftInputMode="stateVisible|adjustResize"> - ... - </activity></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"><uses-sdk></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 deleted file mode 100644 index fea7ee2..0000000 --- a/docs/html/resources/articles/painless-threading.jd +++ /dev/null @@ -1,149 +0,0 @@ -page.title=Painless Threading -parent.title=Articles -parent.link=../browser.html?tag=article -@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<String, Void, Bitmap> { - 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 deleted file mode 100644 index 01fb115..0000000 --- a/docs/html/resources/articles/qsb.jd +++ /dev/null @@ -1,169 +0,0 @@ -page.title=Quick Search Box -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}guide/topics/search/index.html">Search</a></li> - <li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary -sample</a></li> - </ol> - -</div> -</div> - -<div class="figure" style="width:233px"> -<img src="images/qsb_002.png" alt="" height="350" /> -</div> - -<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="{@docRoot}resources/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><activity></code>, an intent filter, and a reference -to a <code>searchable.xml</code> file (described below):</p> - -<pre class="prettyprint"><intent-filter> - <action android:name="android.intent.action.SEARCH" /> - <category android:name="android.intent.category.DEFAULT" /> -</intent-filter> - -<meta-data android:name="android.app.searchable" - android:resource="@xml/searchable" /></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"><!-- Provides search suggestions for words and their definitions. --> -<provider android:name="DictionaryProvider" - android:authorities="dictionary" - android:syncable="false" /></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"><searchable xmlns:android="http://schemas.android.com/apk/res/android" - android:label="@string/search_label" - android:searchSuggestAuthority="dictionary" - android:searchSuggestIntentAction="android.intent.action.VIEW"> -</searchable></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"><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"> -</searchable></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" > "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/service-api-changes-starting-with.jd b/docs/html/resources/articles/service-api-changes-starting-with.jd deleted file mode 100644 index 7bafd81..0000000 --- a/docs/html/resources/articles/service-api-changes-starting-with.jd +++ /dev/null @@ -1,177 +0,0 @@ -page.title=Service API changes starting with Android 2.0 -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - - -<div id="qv-wrapper"> -<div id="qv"> - - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a></li> - </ol> - - <h2>Key classes</h2> - <ol> - <li>{@link android.app.Service}</li> - </ol> - -</div> -</div> - -<p>Watching developers use the Android platform the last year has shown a number of trouble areas in the Service API as well as growing issues in the ways services operate. As a result, Android 2.0 introduced a number of changes and improvements in this area for both developers and users.</p> -<p>The three main changes to be aware of are:</p> -<ul> - <li>Service.setForeground() is now deprecated and in 2.0 does nothing.</li> - <li>There were many edge cases in the service lifecycle that made it very easy to accidentally leave a service running; new APIs in 2.0 make this much easier to deal with.</li> - <li>Android 2.0 also introduces a new UI for end users to monitor and manage the running services on their device.</li> -</ul> -<h3>Background on services</h3> -<p>Before going into the details of 2.0, it may be useful to go over a quick summary of services. The Service API in Android is one of the key mechanisms for applications to do work in the background. Due to the way Android is designed, once an application is no longer visible to the user it is generally considered expendable and a candidate to be killed by the system if it ever needs memory elsewhere. The main way applications get around this is by starting a Service component, which explicitly tells the system that they are doing some valuable work and would prefer that the system not kill their process if it doesn't truly need to.</p> -<p>This is a very powerful facility but along with that power comes some responsibility: an actively running service is taking resources away from other things that can run (including inactive processes in the background that don't need to be initialized the next time the user visits them). It is thus important that developers take care when designing their services that they only run when truly needed and avoid any bugs where they may accidentally leave the service running for long durations.</p> -<h3>Redesigning Service.setForeground()</h3> -<p>During the final stabilization period of Android 1.6 we started to see more issues due to an increasing number of applications using the Service.setForeground() API when they shouldn't be. This is an API that we haven't advertised much because it should not be used by most applications and can be very hard on the system: it asks that the service's process be treated as in the foreground, essentially making it unkillable and thus more difficult for the system to recover from low memory situations.</p> -<p>At that point in 1.6 it was too late to make any significant changes to the behavior here, but in 2.0 we have done so: Service.setForeground() now does nothing. The API was always intended to be something a service would do in conjunction with putting up an ongoing notification for the user; by saying you are in the foreground, the user should be "aware" that the service is running in some way and know how to stop it. Thus in place of the old API Andriod 2.0 introduces two new APIs that require a notification go along with being in the foreground:</p> -<pre class="prettyprint"> -public final void startForeground(int id, Notification notification); -public final void stopForeground(boolean removeNotification); -</pre> -<p>This also not coincidentally makes it much easier to manage the notification state along with the service, since the system can now guarantee that there is always a notification while the service is in the foreground, and that the notification goes away whenever the service does.</p> -<p>Many developers will want to write a service that works on older platforms as well as 2.0 and later; this can be accomplished by using something like the following code to selectively call the new APIs when they are available.</p> -<pre class="prettyprint"> -private static final Class[] mStartForegroundSignature = new Class[] { - int.class, Notification.class}; -private static final Class[] mStopForegroundSignature = new Class[] { - boolean.class}; - -private NotificationManager mNM; -private Method mStartForeground; -private Method mStopForeground; -private Object[] mStartForegroundArgs = new Object[2]; -private Object[] mStopForegroundArgs = new Object[1]; - -@Override -public void onCreate() { - mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - try { - mStartForeground = getClass().getMethod("startForeground", - mStartForegroundSignature); - mStopForeground = getClass().getMethod("stopForeground", - mStopForegroundSignature); - } catch (NoSuchMethodException e) { - // Running on an older platform. - mStartForeground = mStopForeground = null; - } -} - -/** - * This is a wrapper around the new startForeground method, using the older - * APIs if it is not available. - */ -void startForegroundCompat(int id, Notification notification) { - // If we have the new startForeground API, then use it. - if (mStartForeground != null) { - mStartForegroundArgs[0] = Integer.valueOf(id); - mStartForegroundArgs[1] = notification; - try { - mStartForeground.invoke(this, mStartForegroundArgs); - } catch (InvocationTargetException e) { - // Should not happen. - Log.w("MyApp", "Unable to invoke startForeground", e); - } catch (IllegalAccessException e) { - // Should not happen. - Log.w("MyApp", "Unable to invoke startForeground", e); - } - return; - } - - // Fall back on the old API. - setForeground(true); - mNM.notify(id, notification); -} - -/** - * This is a wrapper around the new stopForeground method, using the older - * APIs if it is not available. - */ -void stopForegroundCompat(int id) { - // If we have the new stopForeground API, then use it. - if (mStopForeground != null) { - mStopForegroundArgs[0] = Boolean.TRUE; - try { - mStopForeground.invoke(this, mStopForegroundArgs); - } catch (InvocationTargetException e) { - // Should not happen. - Log.w("MyApp", "Unable to invoke stopForeground", e); - } catch (IllegalAccessException e) { - // Should not happen. - Log.w("MyApp", "Unable to invoke stopForeground", e); - } - return; - } - - // Fall back on the old API. Note to cancel BEFORE changing the - // foreground state, since we could be killed at that point. - mNM.cancel(id); - setForeground(false); -} -</pre> -<h3>Service lifecycle changes</h3> -<p>Another situation we were increasingly seeing in 1.6 was that, even ignoring the services that inappropriately make themselves foreground, we had a growing number of devices with a large number of services running in the background all fighting each other over the available memory.</p> -<p>Part of this problem is services that are running more than they should or there simply being too much stuff trying to be done on the device. However, we also found many issues in the interaction between services and the platform that made it easy for an application to leave a service running even when it is trying to do the right thing. Consider this typical scenario:</p> -<ol> - <li>An application calls startService().</li> - <li>That service gets onCreate(), onStart(), and then spawns a background thread to do some work.</li> - <li>The system is tight on memory, so has to kill the currently running service.</li> - <li>Later when memory is free, the service is restarted, and gets onCreate() called but not onStart() because there has not been another call to startService() with a new Intent command to send it.</li> -</ol> -<p>Now the service will sit there created, not realizing it used to be doing some work, and so not knowing it should stop itself at some point.</p> -<p>To address this, in Android 2.0 Service.onStart() as been deprecated (though still exists and operates as it used to in previous versions of the platform). It is replaced with a new {@link android.app.Service#onStartCommand(android.content.Intent, int, int)} callback that allows the service to better control how the system should manage it. The key part here is a new result code returned by the function, telling the system what it should do with the service if its process is killed while it is running:</p> -<ul> - <li>{@link android.app.Service#START_STICKY} is basically the same as the previous behavior, where the service is left "started" and will later be restarted by the system. The only difference from previous versions of the platform is that it if it gets restarted because its process is killed, onStartCommand() will be called on the next instance of the service with a null Intent instead of not being called at all. Services that use this mode should always check for this case and deal with it appropriately.</li> - <li>{@link android.app.Service#START_NOT_STICKY} says that, after returning from onStartCreated(), if the process is killed with no remaining start commands to deliver, then the service will be stopped instead of restarted. This makes a lot more sense for services that are intended to only run while executing commands sent to them. For example, a service may be started every 15 minutes from an alarm to poll some network state. If it gets killed while doing that work, it would be best to just let it be stopped and get started the next time the alarm fires.</li> - <li>{@link android.app.Service#START_REDELIVER_INTENT} is like START_NOT_STICKY, except if the service's process is killed before it calls stopSelf() for a given intent, that intent will be re-delivered to it until it completes (unless after some number of more tries it still can't complete, at which point the system gives up). This is useful for services that are receiving commands of work to do, and want to make sure they do eventually complete the work for each command sent.</li> -</ul> -<p>For compatibility with existing applications, the default return code for applications that are targeting an earlier version of the platform is a special {@link android.app.Service#START_STICKY_COMPATIBILITY} code that provides the old behavior of not calling onStart() with a null intent. Once you start targeting API version 5 or later, the default mode is START_STICKY and you must be prepared to deal with onStart() or onStartCommand() being called with a null Intent.</p> -<p>You can also easily write a Service that uses both the old and new APIs, depending on the platform. All you need to do is compile against the 2.0 SDK with this code:</p> -<pre class="prettyprint"> -// This is the old onStart method that will be called on the pre-2.0 -// platform. On 2.0 or later we override onStartCommand() so this -// method will not be called. -@Override -public void onStart(Intent intent, int startId) { - handleStart(intent, startId); -} - -@Override -public int onStartCommand(Intent intent, int flags, int startId) { - handleStart(intent, startId); - return START_NOT_STICKY; -} - -void handleStart(Intent intent, int startId) { - // do work -} -</pre> -<h3>New "running services" user interface</h3> -<p>Our final issue to address is the case where there are simply too many service running in the amount of memory available on a device. This may be due to bugs or design flaws in installed applications, or the user simply trying to do too much. Historically users have had no visibility into what is going on at this level in the system, but it has become important to expose this, at least for lower-end devices, as the use of services has had an increasing impact on the user experience.</p> -<p>To help address this, Android 2.0 introduces a new "Running Services" activity available from the Application system settings. When brought up, it looks something like this:</p> -<img src="images/service-api-changes-starting-with_runningservices.png" width="192" height="320" alt="Running Services"/> -<p>The main content is a list of all running services that may be of interest to the user, organized by the processes they run in. In the example here, we see three services:</p> -<ul> - <li><b>GTalkService</b> is part of the standard Google application suit; it is running in Google's "gapps" process, which currently consumes 6.8MB. It has been started for 3 hours 55 minutes, which on this device is the time from when it was first booted.</li> - <li><b>ActivityService</b> is part of the Phonebook app, and its process consumes 4MB. This also has been running since boot.</li> - <li><b>SoftKeyboard</b> is a third party input method. It has been running since I switched to it, about 4 minutes ago.</li> -</ul> -<p>The user can tap on any of these services to control it; for normal services that are running because they were explicitly started, this will present a dialog allowing the user to explicitly stop it:</p> -<img src="images/service-api-changes-starting-with_stopservice.png" height="320" width="192" alt="Stop Service"/> -<p>Some other services, like the input method, are running for other reasons. For these, tapping on the service will go to the corresponding UI to manage it (in this case the system's input settings).</p> -<p>Finally, along the bottom of the screen are some obscure numbers. If you know how to interpret them, this gives you a lot of information on the memory status of your device:</p> -<ul> - <li><b>Avail: 38MB+114MB in 25</b> says that the device has 38MB of completely free (or likely used for unrequired caches) memory, and has another 114MB of available memory in 25 background processes it can kill at any time.</li> - <li><b>Other: 32MB in 3</b> says that the device has 32MB of unavailable memory in 3 unkillable processes (that is, processes that are currently considered to be foreground and must be kept running)</li> -</ul> -<p>For most users, this new user interface should be a much more effective way to manage the background applications on their device than the existing "task killer" applications. In the vast majority of cases the reason for a slow running device is too many services trying to run. This prevents the system from being able to run any background processes (which speed up app switching), and ultimately can result in thrashing through the services when not even they can all be kept running. The Running Services UI is intended to provide very specific information about the services that are running, to help make a good decision about what should be stopped. It also does not use the API to force stop an application, which can unintentionally break applications in numerous ways.</p> -<p>For developers, this is an important tool to ensure your services are well behaved. As you develop your app, be sure to keep an eye on Running Services to ensure that you are not accidentally leaving your services running when they shouldn't be. You should also now keep in mind that users may freely stop any of your services as they wish, without your control, and account for that.</p> -<p>Android's Services are a very powerful tool, but one of the main and subtle ways that application developers can harm the overall experience a user has with their phone.</p> diff --git a/docs/html/resources/articles/speech-input.jd b/docs/html/resources/articles/speech-input.jd deleted file mode 100644 index 2f9cd69..0000000 --- a/docs/html/resources/articles/speech-input.jd +++ /dev/null @@ -1,94 +0,0 @@ -page.title=Speech Input -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body - -<p> People love their mobile phones because they can stay in touch wherever they -are. That means not just talking, but e-mailing, texting, microblogging, and so -on. </p> - -<p>Speech input adds another dimension to staying in touch. -Google's Voice Search application, which is pre-installed on many Android devices -and available on Google Play, provides powerful features like "search by voice" -and Voice Actions like "Navigate to." Further -enhancing the voice experience, Android 2.1 introduces a <a -href="http://www.youtube.com/watch?v=laOlkD8LmZw"> -voice-enabled keyboard</a>, which makes it even easier -to stay connected. Now you can dictate your message instead of typing it. Just -tap the new microphone button on the keyboard, and you can speak in just about -any context in which you would normally type. </p> - -<p> We believe speech can -fundamentally change the mobile experience. We would like to invite every -Android application developer to consider integrating speech input capabilities -via the Android SDK. One of our favorite apps on Google Play that integrates -speech input is <a href="http://www.handcent.com/">Handcent SMS</a>, -because you can dictate a reply to any SMS with a -quick tap on the SMS popup window. Here is Speech input integrated into -Handcent SMS:</p> - -<img src="images/speech-input.png"/> - - -<p> The Android SDK makes it easy to integrate speech input directly into your -own application. Just copy and paste from this <a -href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/VoiceRecognition.html">sample -application</a> to get -started. The sample application first verifies that the target device is able -to recognize speech input:</p> -<pre> -// Check to see if a recognition activity is present -PackageManager pm = getPackageManager(); -List<ResolveInfo> activities = pm.queryIntentActivities( - new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0); -if (activities.size() != 0) { - speakButton.setOnClickListener(this); -} else { - speakButton.setEnabled(false); - speakButton.setText("Recognizer not present"); -} -</pre> -<p> -The sample application then uses {@link -android.app.Activity#startActivityForResult(android.content.Intent, int) -startActivityForResult()} to broadcast an intent that requests voice -recognition, including an extra parameter that specifies one of two language -models. The voice recognition application that handles the intent processes the -voice input, then passes the recognized string back to your application by -calling the {@link android.app.Activity#onActivityResult(int, int, -android.content.Intent) onActivityResult()} callback. </p> - - -<p>Android is an open platform, so your application can potentially make -use of any speech recognition service on the device that's registered to receive -a {@link android.speech.RecognizerIntent}. Google's Voice Search application, -which is pre-installed on -many Android devices, responds to a <em>RecognizerIntent</em> by displaying the -"Speak -now" dialog and streaming audio to Google's servers -- the same servers used -when a user taps the microphone button on the search widget or the voice-enabled -keyboard. You can check whether Voice Search is installed in -<strong>Settings > Applications > Manage applications</strong>. </p> - -<p> One important tip: for speech input to be as accurate as possible, it's -helpful to have an idea of what words are likely to be spoken. While a message -like "Mom, I'm writing you this message with my voice!" might be appropriate for -an email or SMS message, you're probably more likely to say something like -"weather in Mountain View" if you're using Google Search. You can make sure your -users have the best experience possible by requesting the appropriate -<em>language model:</em> {@link -android.speech.RecognizerIntent#LANGUAGE_MODEL_FREE_FORM free_form} for -dictation, or {@link android.speech.RecognizerIntent#LANGUAGE_MODEL_WEB_SEARCH -web_search} for shorter, search-like phrases. We developed the "free form" -model to improve dictation accuracy for the voice keyboard, -while the "web search" model is used when users want to search by voice. </p> - -<p> Google's servers support many languages for voice input, with more arriving -regularly. You can use the -{@link android.speech.RecognizerIntent#ACTION_GET_LANGUAGE_DETAILS} -broadcast intent to query for the list of supported languages. -The web search model is available for all languages, while the free-form model -may not be optimized for all languages. As we work hard to support more models in -more languages, and to improve the accuracy of the speech recognition technology -we use in our products, Android developers who integrate speech capabilities -directly into their applications can reap the benefits as well. </p> diff --git a/docs/html/resources/articles/spell-checker-framework.jd b/docs/html/resources/articles/spell-checker-framework.jd deleted file mode 100644 index 8d57b4e..0000000 --- a/docs/html/resources/articles/spell-checker-framework.jd +++ /dev/null @@ -1,236 +0,0 @@ -page.title=Using the Spell Checker Framework -parent.title=Articles -parent.link=../browser.html?tag=article -@jd:body -<div id="qv-wrapper"> -<div id="qv"> -<h2>In This Document</h2> -<ol> - <li> - <a href="#SpellCheckLifeCycle">Spell Check Lifecycle</a> - </li> - <li> - <a href="#SpellCheckImplementation">Implementing a Spell Checker Service</a> - </li> - <li> - <a href="#SpellCheckClient">Implementing a Spell Checker Client</a> - </li> -</ol> - <h2>See also</h2> - <ol> - <li> - <a href="{@docRoot}resources/samples/SpellChecker/SampleSpellCheckerService/index.html"> - Spell Checker Service</a> sample app - </li> - <li> - <a href="{@docRoot}resources/samples/SpellChecker/HelloSpellChecker/index.html"> - Spell Checker Client</a> sample app - </li> - </ol> -</div> -</div> - -<p> - The Android platform offers a spell checker framework that lets you implement - and access spell checking in your application. The framework is one of the - Text Service APIs offered by the Android platform. -</p> -<p> - To use the framework in your app, you create a special type of Android service that - generates a spell checker <strong>session</strong> object. Based on text you provide, - the session object returns spelling suggestions generated by the spell checker. -</p> -<h2 id="SpellCheckLifeCycle">Spell Checker Lifecycle</h2> -<p> - The following diagram shows the lifecycle of the spell checker service: -</p> -<img src="{@docRoot}resources/articles/images/spellcheck_lifecycle.png" alt="" height="596" - id="figure1" /> -<p class="img-caption"> - <strong>Figure 1.</strong> The spell checker service lifecycle. -</p> -<p> - To initiate spell checking, your app starts its implementation of the spell checker - service. Clients in your app, such as activities or individual UI elements, request a - spell checker session from the service, then use the session to get suggestions for text. - As a client terminates its operation, it closes its spell checker session. If necessary, your - app can shut down the spell checker service at any time. -</p> -<h2 id="SpellCheckImplementation">Implementing a Spell Checker Service</h2> -<p> - To use the spell checker framework in your app, add a spell checker service component including - the session object definition. You can also add to your app an optional activity that - controls settings. You must also add an XML metadata file that describes - the spell checker service, and add the appropriate elements to your manifest file. -</p> -<h3 id="SpellCheckCode">Spell checker classes</h3> -<p> - Define the service and session object with the following classes: -</p> -<dl> - <dt> - A subclass of {@link android.service.textservice.SpellCheckerService} - </dt> - <dd> - The {@link android.service.textservice.SpellCheckerService} implements both the - {@link android.app.Service} class and the spell checker framework interface. Within your - subclass, you must implement the following method: - <dl> - <dt>{@link android.service.textservice.SpellCheckerService#createSession()}</dt> - <dd> - A factory method that returns a - {@link android.service.textservice.SpellCheckerService.Session} object to a - client that wants to do spell checking. - </dd> - </dl> - <p> - See the - <a href="{@docRoot}resources/samples/SpellChecker/SampleSpellCheckerService/index.html"> - Spell Checker Service</a> sample app to learn more about implementing this class. - </p> - </dd> - <dt> - An implementation of {@link android.service.textservice.SpellCheckerService.Session} - </dt> - <dd> - An object that the spell checker service provides to clients, to let them pass text to - the spell checker and receive suggestions. Within this class, you must implement the - following methods: - <dl> - <dt> - {@link android.service.textservice.SpellCheckerService.Session#onCreate()} - </dt> - <dd> - Called by the system in response to - {@link android.service.textservice.SpellCheckerService#createSession()}. In this - method, you can initialize the - {@link android.service.textservice.SpellCheckerService.Session} object based on - the current locale and so forth. - </dd> - <dt> - {@link android.service.textservice.SpellCheckerService.Session#onGetSuggestions(TextInfo, int) - onGetSuggestions()} - </dt> - <dd> - Does the actual spell checking. This method returns an object containing - suggestions for the text passed to it. - </dd> - </dl> - <p> - Optionally, you can implement - {@link android.service.textservice.SpellCheckerService.Session#onCancel()}, which - handles requests to cancel spell checking, or -{@link android.service.textservice.SpellCheckerService.Session#onGetSuggestionsMultiple(TextInfo[], int, boolean) -onGetSuggestionsMultiple()}, which handles batches of suggestion requests, or both. - </p> - <p> - See the - <a href="{@docRoot}resources/samples/SpellChecker/HelloSpellChecker/index.html"> - Spell Checker Client</a> sample app to learn more about implementing this class. - </p> - </dd> -</dl> -<p class="note"> - <strong>Note:</strong> You must implement all aspects of spell checking as asynchronous and - thread-safe. A spell checker may be called simultaneously by different threads running on - different cores. The {@link android.service.textservice.SpellCheckerService} and - {@link android.service.textservice.SpellCheckerService.Session} take care of this - automatically. -</p> -<h3 id="SpellCheckXML">Spell checker manifest and metadata</h3> -<p> - In addition to code, you need to provide the appropriate manifest file and a metadata file for - the spell checker. -</p> -<p> - The manifest file defines the application, the service, and the activity for controlling - settings, as shown in the following snippet: -</p> -<pre> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.example.android.samplespellcheckerservice" > - <application - android:label="@string/app_name" > - <service - android:label="@string/app_name" - android:name=".SampleSpellCheckerService" - android:permission="android.permission.BIND_TEXT_SERVICE" > - <intent-filter > - <action android:name="android.service.textservice.SpellCheckerService" /> - </intent-filter> - - <meta-data - android:name="android.view.textservice.scs" - android:resource="@xml/spellchecker" /> - </service> - - <activity - android:label="@string/sample_settings" - android:name="SpellCheckerSettingsActivity" > - <intent-filter > - <action android:name="android.intent.action.MAIN" /> - </intent-filter> - </activity> - </application> -</manifest> -</pre> -<p> - Notice that components that want to use the service must request the permission - {@link android.Manifest.permission#BIND_TEXT_SERVICE} to ensure that only the system binds to - the service. The service's definition also specifies the <code>spellchecker.xml</code> metadata - file, which is described in the next section. -</p> -<p> - The metadata file <code>spellchecker.xml</code> contains the following XML: -</p> -<pre> -<spell-checker xmlns:android="http://schemas.android.com/apk/res/android" - android:label="@string/spellchecker_name" - android:settingsActivity="com.example.SpellCheckerSettingsActivity"> - <subtype - android:label="@string/subtype_generic" - android:subtypeLocale="en” - /> - <subtype - android:label="@string/subtype_generic" - android:subtypeLocale="fr” - /> -</spell-checker> -</pre> -<p> - The metadata specifies the activity that the spell checker uses for controlling settings. It - also defines subtypes for the spell checker; in this case, the subtypes define locales that - the spell checker can handle. -</p> - - -<!-- Accessing the Spell Checker Service from a Client --> -<h2 id="SpellCheckClient">Accessing the Spell Checker Service from a Client</h2> -<p> - Applications that use {@link android.widget.TextView} views automatically benefit from spell - checking, because {@link android.widget.TextView} automatically uses a spell checker. The - following screenshots show this: -</p> -<img src="{@docRoot}resources/articles/images/textview_spellcheck_screenshot_1.png" alt="" - height="45" id="figure2a" /> -<br> -<img src="{@docRoot}resources/articles/images/textview_spellcheck_screenshot_2.png" alt="" - height="121" id="figure2b" /> -<p class="img-caption"> - <strong>Figure 2.</strong> Spell checking in TextView. -</p> -<p> - However, you may want to interact directly with a spell checker service in other cases as well. - The following diagram shows the flow of control for interacting with a spell checker service: -</p> -<img src="{@docRoot}resources/articles/images/spellcheck_client_flow.png" alt="" - height="394" id="figure3" /> -<p class="img-caption"> - <strong>Figure 3.</strong> Interacting with a spell checker service. -</p> -<p> - The <a href="{@docRoot}resources/samples/SpellChecker/HelloSpellChecker/index.html"> - Spell Checker Client</a> sample app shows how to interact with a spell checker service. The - LatinIME input method editor in the Android Open Source Project also contains an example of - spell checking. -</p>
\ No newline at end of file diff --git a/docs/html/resources/articles/timed-ui-updates.jd b/docs/html/resources/articles/timed-ui-updates.jd deleted file mode 100644 index 7a0804f..0000000 --- a/docs/html/resources/articles/timed-ui-updates.jd +++ /dev/null @@ -1,151 +0,0 @@ -page.title=Updating the UI from a Timer -parent.title=Articles -parent.link=../browser.html?tag=article -@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 < 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 deleted file mode 100644 index 5eae9b9..0000000 --- a/docs/html/resources/articles/touch-mode.jd +++ /dev/null @@ -1,140 +0,0 @@ -page.title=Touch Mode -parent.title=Articles -parent.link=../browser.html?tag=article -@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 deleted file mode 100644 index c4184b5..0000000 --- a/docs/html/resources/articles/track-mem.jd +++ /dev/null @@ -1,64 +0,0 @@ -page.title=Tracking Memory Allocations -parent.title=Articles -parent.link=../browser.html?tag=article -@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 — and sometimes not possible — 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 deleted file mode 100644 index 929d084..0000000 --- a/docs/html/resources/articles/tts.jd +++ /dev/null @@ -1,243 +0,0 @@ -page.title=Using Text-to-Speech -parent.title=Articles -parent.link=../browser.html?tag=article -@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 Google Play, 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<String, String> 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<String, String> 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 deleted file mode 100644 index 2edaa2e..0000000 --- a/docs/html/resources/articles/ui-1.5.jd +++ /dev/null @@ -1,50 +0,0 @@ -page.title=UI Framework Changes in Android 1.5 -parent.title=Articles -parent.link=../browser.html?tag=article -@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 deleted file mode 100644 index b3238e3..0000000 --- a/docs/html/resources/articles/ui-1.6.jd +++ /dev/null @@ -1,132 +0,0 @@ -page.title=UI Framework Changes in Android 1.6 -parent.title=Articles -parent.link=../browser.html?tag=article -@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><?xml version="1.0" encoding="utf-8"?> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="64dip" - android:padding="6dip"> - - <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" /> - - <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" /> - - <ImageView - android:id="@id/artwork" - android:layout_width="56dip" - android:layout_height="56dip" - android:layout_gravity="center_vertical" - - android:src="@drawable/artwork" /> - -</RelativeLayout></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><Button android:onClick="myClickHandler" /></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 Google Play.</p> diff --git a/docs/html/resources/articles/using-webviews.jd b/docs/html/resources/articles/using-webviews.jd deleted file mode 100644 index 3a2430b..0000000 --- a/docs/html/resources/articles/using-webviews.jd +++ /dev/null @@ -1,63 +0,0 @@ -page.title=Using WebViews -parent.title=Articles -parent.link=../browser.html?tag=article -@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 deleted file mode 100644 index 78fe62e..0000000 --- a/docs/html/resources/articles/wikinotes-intents.jd +++ /dev/null @@ -1,257 +0,0 @@ -page.title=WikiNotes: Routing Intents -parent.title=Articles -parent.link=../browser.html?tag=article -@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> — 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><provider name="com.google.android.wikinotes.db.WikiNotesProvider" - android:authorities="com.google.android.wikinotes.db.wikinotes" /></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 — '*' — 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><intent-filter> - <action name="android.intent.action.VIEW"/> - <category name="android.intent.category.DEFAULT"/> - <category name="android.intent.category.BROWSABLE"/> - <data mimetype="vnd.android.cursor.item/vnd.google.wikinote"/> -</intent-filter></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 deleted file mode 100644 index fb49f86..0000000 --- a/docs/html/resources/articles/wikinotes-linkify.jd +++ /dev/null @@ -1,115 +0,0 @@ -page.title=WikiNotes: Linkify your Text! -parent.title=Articles -parent.link=../browser.html?tag=article -@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 -»</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 »</a> and no -spaces). Linkify can then turn this into a Content URI — 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 deleted file mode 100644 index c5e5e90..0000000 --- a/docs/html/resources/articles/window-bg-speed.jd +++ /dev/null @@ -1,127 +0,0 @@ -page.title=Window Backgrounds & UI Speed -parent.title=Articles -parent.link=../browser.html?tag=article -@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"><resources> - <style name="Theme.NoBackground" parent="android:Theme"> - <item name="android:windowBackground">@null</item> - </style> -</resources></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><activity /></code> or <code><application /></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"><bitmap xmlns:android="http://schemas.android.com/apk/res/android" - android:src="@drawable/shelf_panel" - android:tileMode="repeat" /></pre><p>This drawable is simply referenced by the theme:</p> - -<pre class="prettyprint"><resources> - <style name="Theme.Shelves" parent="android:Theme"> - <item name="android:windowBackground">@drawable/background_shelf</item> - <item name="android:windowNoTitle">true</item> - </style> -</resources></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 deleted file mode 100644 index d3c68a6..0000000 --- a/docs/html/resources/articles/zipalign.jd +++ /dev/null @@ -1,100 +0,0 @@ -page.title=Zipalign: an Easy Optimization -parent.title=Articles -parent.link=../browser.html?tag=article -@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 — 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 — 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 — 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" > -"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>ant.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> |
