<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;A0EER3s8eyp7ImA9WhRUFk0.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179</id><updated>2012-01-26T12:26:46.573-08:00</updated><category term="User Interface" /><category term="Mountain View" /><category term="Location" /><category term="Gestures" /><category term="London" /><category term="Android 2.1" /><category term="Android Developer Phone" /><category term="Boston" /><category term="Open source" /><category term="Android Developer Challenge" /><category term="Resources" /><category term="Apps" /><category term="OpenGL ES" /><category term="NDK" /><category term="Cool Stuff" /><category term="Debugging" /><category term="Speech Input" /><category term="Text-to-Speech" /><category term="io2010" /><category term="Google I/O" /><category term="Android 2.3.3" /><category term="Android 3.2" /><category term="Munich" /><category term="Guidelines" /><category term="Android 2.0" /><category term="JNI" /><category term="Quick Search Box" /><category term="Tel Aviv" /><category term="Android Market" /><category term="Android 2.3" /><category term="Android 1.5" /><category term="Developer profiles" /><category term="Widgets" /><category term="Developer Labs" /><category term="Announcements" /><category term="Sample code" /><category term="Dashboard" /><category term="Intents" /><category term="Android 2.2" /><category term="Layout" /><category term="Code Day" /><category term="Android 1.6" /><category term="Developer Days" /><category term="How-to" /><category term="Android 3.0" /><category term="SDK updates" /><category term="Input methods" /><category term="Android 4.0" /><category term="Optimization" /><title type="text">Android Developers Blog</title><subtitle type="html">An Open Handset Alliance Project.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://android-developers.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://android-developers.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>A Googler</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>257</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/hsDu" /><feedburner:info uri="blogspot/hsdu" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0EER3k4eyp7ImA9WhRUFk0.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-7750059148144062785</id><published>2012-01-26T12:10:00.000-08:00</published><updated>2012-01-26T12:26:46.733-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-26T12:26:46.733-08:00</app:edited><title>Say Goodbye to the Menu Button</title><content type="html">&lt;a href="http://4.bp.blogspot.com/-iuj3Ow47b_k/TyG1PTXTodI/AAAAAAAABGo/Z5kHmVtOUF0/s1600/RUNE4057.jpg"&gt;&lt;img style="border: 5px solid #ddd; float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 200px; height: 164px;" src="http://4.bp.blogspot.com/-iuj3Ow47b_k/TyG1PTXTodI/AAAAAAAABGo/Z5kHmVtOUF0/s200/RUNE4057.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5702037877728453074" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by Scott Main, lead tech writer for &lt;a href="http://developer.android.com"&gt;developer.android.com&lt;/a&gt;.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Before Android 3.0 (Honeycomb), all Android-powered devices included a dedicated Menu button. As a developer, you could use the Menu button to display whatever options were relevant to the user, often using the activity’s built-in options menu. Honeycomb removed the reliance on physical buttons, and introduced the &lt;a href="http://developer.android.com/reference/android/app/ActionBar.html"&gt;ActionBar&lt;/a&gt; class as the standard solution to make actions from the user options immediately visible and quick to invoke. In order to provide the most intuitive and consistent user experience in your apps, you should migrate your designs away from using the Menu button and toward using the action bar. This isn’t a new concept — the action bar pattern has been around on Android even before Honeycomb — but as Ice Cream Sandwich rolls out to more devices, it’s important that you begin to migrate your designs to the action bar in order to promote a consistent Android user experience.&lt;/p&gt;&lt;p&gt;You might worry that it’s too much work to begin using the action bar, because you need to support versions of Android older than Honeycomb. However, it’s quite simple for most apps because you can continue to support the Menu button on pre-Honeycomb devices, but also provide the action bar on newer devices with only a few lines of code changes.&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/-KIyVJ4DBLdw/TyGbNsLn4hI/AAAAAAAABFs/xgLPIAaEP6I/s1600/image01.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 230px; height: 400px;" src="http://1.bp.blogspot.com/-KIyVJ4DBLdw/TyGbNsLn4hI/AAAAAAAABFs/xgLPIAaEP6I/s400/image01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702009262728274450" /&gt;&lt;/a&gt;&lt;p&gt;If I had to put this whole post into one sentence, it’d be: Set &lt;a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target"&gt;&lt;code&gt;targetSdkVersion&lt;/code&gt;&lt;/a&gt; to 14 and, if you use the options menu, surface a few actions in the action bar with &lt;code&gt;showAsAction="ifRoom"&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;Don’t call it a menu&lt;/h3&gt;&lt;p&gt;Not only should your apps stop relying on the hardware Menu button, but you should stop thinking about your activities using a “menu button” at all. Your activities should provide buttons for important user actions directly in the action bar (or elsewhere on screen). Those that can’t fit in the action bar end up in the &lt;i&gt;action overflow&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;In the screenshot here, you can see an action button for Search and the action overflow on the right side of the action bar.&lt;/p&gt;&lt;p&gt;Even if your app is built to support versions of Android older than 3.0 (in which apps traditionally use the options menu panel to display user options/actions), when it runs on Android 3.0 and beyond, there’s no Menu button. The button that appears in the system/navigation bar represents the action overflow for legacy apps, which reveals actions and user options that have “overflowed off the screen.” &lt;/p&gt;&lt;p&gt;This might seem like splitting hairs over terminology, but the name &lt;i&gt;action overflow&lt;/i&gt; promotes a different way of thinking. Instead of thinking about a menu that serves as a catch-all for various user options, you should think more about which user options you want to display on the screen as actions. Those that don't need to be on the screen can overflow off the screen. Users can reveal the overflow and other options by touching an overflow button that appears alongside the on-screen action buttons.&lt;/p&gt;&lt;h3&gt;Action overflow button for legacy apps&lt;/h3&gt;&lt;p&gt;If you’ve already developed an app to support Android 2.3 and lower, then you might have noticed that when it runs on a device without a hardware Menu button (such as a Honeycomb tablet or Galaxy Nexus), the system adds the action overflow button beside the system navigation. &lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/-u-3KNfy5n9M/TyG235X2rGI/AAAAAAAABHM/g_qGEXBdJW8/s1600/image00.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 400px; height: 49px;" src="http://1.bp.blogspot.com/-u-3KNfy5n9M/TyG235X2rGI/AAAAAAAABHM/g_qGEXBdJW8/s400/image00.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702039674637692002" /&gt;&lt;/a&gt;&lt;!--&lt;a href="http://3.bp.blogspot.com/-OEFZwRHwsFA/TyGbZ_-MsnI/AAAAAAAABF4/rq9uuGlQm8Q/s1600/image00.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 49px;" src="http://3.bp.blogspot.com/-OEFZwRHwsFA/TyGbZ_-MsnI/AAAAAAAABF4/rq9uuGlQm8Q/s400/image00.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702009474199106162" /&gt;&lt;/a&gt;--&gt;&lt;p&gt;This is a compatibility behavior for legacy apps designed to ensure that apps built to expect a Menu button remain functional. However, this button doesn’t provide an ideal user experience. In fact, in apps that don’t use an options menu anyway, this action overflow button does nothing and creates user confusion. So you should update your legacy apps to remove the action overflow from the navigation bar when running on Android 3.0+ and begin using the action bar if necessary. You can do so all while remaining backward compatible with the devices your apps currently support.&lt;/p&gt;&lt;p&gt;If your app runs on a device without a dedicated Menu button, the system decides whether to add the action overflow to the navigation bar based on which API levels you declare to support in the &lt;a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html"&gt;&lt;code&gt;&amp;lt;uses-sdk&gt;&lt;/code&gt;&lt;/a&gt; manifest element. The logic boils down to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;If you set either &lt;code&gt;minSdkVersion&lt;/code&gt; or &lt;code&gt;targetSdkVersion&lt;/code&gt; to 11 or higher, the system &lt;em&gt;will not&lt;/em&gt; add the legacy overflow button. &lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Otherwise, the system &lt;em&gt;will&lt;/em&gt; add the legacy overflow button when running on Android 3.0 or higher.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The only exception is that if you set &lt;code&gt;minSdkVersion&lt;/code&gt; to 10 or lower, set &lt;code&gt;targetSdkVersion&lt;/code&gt; to 11, 12, or 13, and you do not use &lt;a href="http://developer.android.com/reference/android/app/ActionBar.html "&gt;ActionBar&lt;/a&gt;, the system &lt;em&gt;will&lt;/em&gt; add the legacy overflow button when running your app &lt;em&gt;on a handset&lt;/em&gt; with Android 4.0 or higher. &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That exception might be a bit confusing, but it’s based on the belief that if you designed your app to support pre-Honeycomb handsets and Honeycomb tablets, it probably expects handset devices to include a Menu button (but it supports tablets that don’t have one).&lt;/p&gt;&lt;p&gt;So, to ensure that the overflow action button never appears beside the system navigation, you should set the &lt;code&gt;targetSdkVersion&lt;/code&gt; to 14. (You can leave &lt;code&gt;minSdkVersion&lt;/code&gt; at something much lower to continue supporting older devices.)&lt;/p&gt;&lt;h3&gt;Migrating to the action bar&lt;/h3&gt;&lt;p&gt;If you have activities that use the options menu (they implement &lt;a href="http://developer.android.com/reference/android/app/Activity.html#onCreateOptionsMenu(android.view.Menu)"&gt;onCreateOptionsMenu()&lt;/a&gt;), then once the legacy overflow button disappears from the system/navigation bar (because you’ve set &lt;code&gt;targetSdkVersion&lt;/code&gt; to 14), you need to provide an alternative means for the user to access the activity’s actions and other options. Fortunately, the system provides such a means by default: the action bar.&lt;/p&gt;&lt;p&gt;Add &lt;code&gt;showAsAction="ifRoom"&lt;/code&gt; to the &lt;code&gt;&amp;lt;item&gt;&lt;/code&gt; elements representing the activity’s most important actions to show them in the action bar when space is available. For help deciding how to prioritize which actions should appear in the action bar, see &lt;cite&gt;Android Design’s&lt;/cite&gt; &lt;a href="http://developer.android.com/design/patterns/actionbar.html"&gt;Action Bar guide&lt;/a&gt;.&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/-sUzHJNpXDkw/TyGwS1y-asI/AAAAAAAABGc/5_dEJ8DfhCA/s1600/icon_samples.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 315px; height: 60px;" src="http://1.bp.blogspot.com/-sUzHJNpXDkw/TyGwS1y-asI/AAAAAAAABGc/5_dEJ8DfhCA/s400/icon_samples.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5702032440952777410" /&gt;&lt;/a&gt;&lt;p&gt;To further provide a consistent user experience in the action bar, we suggest that you use action icons designed by the Android UX Team where appropriate. The available icons support common user actions such as Refresh, Delete, Attach, Star, Share and more, and are designed for the light and dark Holo themes.  &lt;a href="http://developer.android.com/design/static/download/action_bar_icons-v4.0.zip"&gt;Here they are!&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If these icons don’t accommodate your needs and you need to create your own, you should follow the &lt;a href="http://developer.android.com/design/style/iconography.html"&gt;Iconography design guide&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Removing the action bar&lt;/h3&gt;&lt;p&gt;If you don’t need the action bar, you can remove it from your entire app or from individual activities. This is appropriate for apps that never used the options menu or for apps in which the action bar doesn’t meet design needs (such as games). You can remove the action bar using a theme such as &lt;code&gt;Theme.Holo.NoActionBar&lt;/code&gt; or &lt;code&gt;Theme.DeviceDefault.NoActionBar&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;In order to use such a theme and remain backward compatible, you can use Android’s resource system to define different themes for different platform versions, as described by Adam Powell’s post, &lt;a href="http://android-developers.blogspot.com/2012/01/holo-everywhere.html"&gt;Holo Everywhere&lt;/a&gt;. All you need is your own theme, which you define to inherit different platform themes depending on the current platform version.&lt;/p&gt;&lt;p&gt;For example, here’s how you can declare a custom theme for your application:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;application android:theme="@style/NoActionBar"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or you can instead declare the theme for individual &lt;code&gt;&amp;lt;activity&gt;&lt;/code&gt; elements.&lt;/p&gt;&lt;p&gt;For pre-Honeycomb devices, include the following theme in &lt;code&gt;res/values/themes.xml&lt;/code&gt; that inherits the standard platform theme:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;resources&gt;
    &amp;lt;style name="NoActionBar" parent="@android:style/Theme"&gt;
        &amp;lt;!-- Inherits the default theme for pre-HC (no action bar) --&gt;
    &amp;lt;/style&gt;
&amp;lt;/resources&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For Honeycomb and beyond, include the following theme in &lt;code&gt;res/values-v11/themes.xml&lt;/code&gt; that inherits a &lt;code&gt;NoActionBar&lt;/code&gt; theme:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;resources&gt;
    &amp;lt;style name="NoActionBar" parent="@android:style/Theme.Holo.NoActionBar"&gt;
        &amp;lt;!-- Inherits the Holo theme with no action bar; no other styles needed. --&gt;
    &amp;lt;/style&gt;
&amp;lt;/resources&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At runtime, the system applies the appropriate version of the &lt;code&gt;NoActionBar&lt;/code&gt; theme based on the system’s API version.&lt;/p&gt;&lt;h3&gt;Summary&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Android no longer requires a dedicated Menu button, some devices don’t have one, and you should migrate away from using it. &lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Set &lt;a href="http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target"&gt;&lt;code&gt;targetSdkVersion&lt;/code&gt;&lt;/a&gt; to 14, then test your app on Android 4.0. &lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Add &lt;code&gt;showAsAction="ifRoom"&lt;/code&gt; to menu items you’d like to surface in the action bar.&lt;/p&gt;&lt;/li&gt;&lt;p&gt;&lt;li&gt;If the ActionBar doesn’t work for your app, you can remove it with &lt;code&gt;Theme.Holo.NoActionBar&lt;/code&gt; or &lt;code&gt;Theme.DeviceDefault.NoActionBar&lt;/code&gt;.&lt;/li&gt;&lt;/p&gt;&lt;/ul&gt;&lt;p&gt;For information about how you should design your action bar, see &lt;cite&gt;Android Design’s&lt;/cite&gt; &lt;a href="http://developer.android.com/design/patterns/actionbar.html"&gt;Action Bar guide&lt;/a&gt;. More information about implementing the action bar is also available in the &lt;a href="http://developer.android.com/guide/topics/ui/actionbar.html"&gt;Action Bar developer guide&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7750059148144062785?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=2N-PP9COf0M:1fvrpPf08ss:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=2N-PP9COf0M:1fvrpPf08ss:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=2N-PP9COf0M:1fvrpPf08ss:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/2N-PP9COf0M" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/7750059148144062785?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/7750059148144062785?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/2N-PP9COf0M/say-goodbye-to-menu-button.html" title="Say Goodbye to the Menu Button" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-iuj3Ow47b_k/TyG1PTXTodI/AAAAAAAABGo/Z5kHmVtOUF0/s72-c/RUNE4057.jpg" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMBRHo4fyp7ImA9WhRVF0g.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-2318375095485779407</id><published>2012-01-16T15:37:00.000-08:00</published><updated>2012-01-16T15:44:15.437-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-16T15:44:15.437-08:00</app:edited><title>Southern-hemisphere Developer Labs</title><content type="html">&lt;p&gt;We’ve just scheduled Android Developer Labs for Melbourne (January 31), Sydney (February 3), and Auckland (February 8).  The material is not introductory; it’s aimed at people with existing apps who want to make them better in the era of Ice Cream Sandwich and tablets.  You’ll want to show up with the SDK installed, and a couple of devices.&lt;/p&gt;&lt;p&gt;If this describes you, drop by the &lt;a href="https://sites.google.com/site/androiddeveloperlabs/"&gt;ADL page&lt;/a&gt; and sign up.  You should hurry, because these are not large-scale events and there are more qualified people than there are seats.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2318375095485779407?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=7cdK06U-jSg:MyFdhTCeqRc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=7cdK06U-jSg:MyFdhTCeqRc:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=7cdK06U-jSg:MyFdhTCeqRc:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/7cdK06U-jSg" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2318375095485779407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2318375095485779407?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/7cdK06U-jSg/southern-hemisphere-developer-labs.html" title="Southern-hemisphere Developer Labs" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><feedburner:origLink>http://android-developers.blogspot.com/2012/01/southern-hemisphere-developer-labs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8MQ3o9eCp7ImA9WhRVFEw.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-5428686436183648102</id><published>2012-01-12T13:00:00.000-08:00</published><updated>2012-01-12T16:34:42.460-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-12T16:34:42.460-08:00</app:edited><title>Introducing the Android Design site</title><content type="html">&lt;a href="http://4.bp.blogspot.com/-mvxnJ_jo-Do/Tw3RY2z9a5I/AAAAAAAABCU/aOnMTHkF7MI/s1600/sg.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 291px;" src="http://4.bp.blogspot.com/-mvxnJ_jo-Do/Tw3RY2z9a5I/AAAAAAAABCU/aOnMTHkF7MI/s320/sg.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5696439328654060434" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="https://plus.google.com/110879635926653430880/posts"&gt;Christian Robertson&lt;/a&gt;,  who  leads the Android visual design group. He is also the designer of the Roboto font family.&amp;nbsp;—Tim Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Ice Cream Sandwich (Android 4.0) is our biggest redesign yet&amp;nbsp;—&amp;nbsp;both for users and developers. We’ve enhanced the UI framework with new interactions and styles that will let you create Android apps that are simpler and more beautiful than ever before.&lt;/p&gt;&lt;p&gt;To help you in that mission, we’re introducing &lt;a href="http://developer.android.com/design/"&gt;&lt;cite&gt;Android Design&lt;/cite&gt;&lt;/a&gt;: the place to learn about principles, building blocks, and patterns for creating world-class Android user interfaces. Whether you’re a UI professional or a developer playing that role, these docs show you how to make good design decisions, big and small.&lt;/p&gt;&lt;p&gt;The Android User Experience Team is committed to helping you design amazing apps that people love, and this is just the beginning. In the coming months, we’ll expand &lt;cite&gt;Android Design&lt;/cite&gt; with more in-depth content. And watch this blog for a series of posts about design, and invitations to Google+ hangouts on the topics you care about most.&lt;/p&gt;&lt;p&gt;So head on over to &lt;a href="http://developer.android.com/design/"&gt;&lt;cite&gt;Android Design&lt;/cite&gt;&lt;/a&gt;, and make something amazing!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5428686436183648102?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=iHQNI_dgb2w:nCP2ztVbQok:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=iHQNI_dgb2w:nCP2ztVbQok:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=iHQNI_dgb2w:nCP2ztVbQok:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/iHQNI_dgb2w" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/5428686436183648102?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/5428686436183648102?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/iHQNI_dgb2w/introducing-android-design-site.html" title="Introducing the Android Design site" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-mvxnJ_jo-Do/Tw3RY2z9a5I/AAAAAAAABCU/aOnMTHkF7MI/s72-c/sg.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2012/01/introducing-android-design-site.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcMSHw9cSp7ImA9WhRVEk4.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-5058038089639562398</id><published>2012-01-10T13:43:00.000-08:00</published><updated>2012-01-10T15:28:09.269-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-10T15:28:09.269-08:00</app:edited><title>Levels in Renderscript</title><content type="html">&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="https://plus.google.com/113680924389579925739/posts"&gt;R. Jason Sams&lt;/a&gt;, an Android Framework engineer who specializes in graphics, performance tuning, and software architecture.&amp;nbsp;—Tim Bray]&lt;/i&gt;&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/-1AN0Pp29JF8/Twy_hmUcPhI/AAAAAAAABBk/e9VKCVmrytY/s1600/jsams.jpg"&gt;&lt;img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 320px; height: 201px;" src="http://1.bp.blogspot.com/-1AN0Pp29JF8/Twy_hmUcPhI/AAAAAAAABBk/e9VKCVmrytY/s320/jsams.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5696138212659707410" /&gt;&lt;/a&gt;&lt;p&gt;For ICS, Renderscript (RS) has been updated with several new features to simplify adding compute acceleration to your application.  RS is interesting for compute acceleration when you have large buffers of data on which you need to do significant processing.  In this example we will look at applying a levels/saturation operation on a bitmap.&lt;/p&gt;&lt;p&gt;In this case, saturation is implemented by multiplying every pixel by a color matrix Levels are typically implemented with several operations.  &lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Input levels are adjusted.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Gamma correction.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Output levels are adjusted.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Clamp to the valid range.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;A simple implementation of this might look like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;for (int i=0; i &amp;lt; mInPixels.length; i++) {
    float r = (float)(mInPixels[i] &amp;amp; 0xff);
    float g = (float)((mInPixels[i] &gt;&gt; 8) &amp;amp; 0xff);
    float b = (float)((mInPixels[i] &gt;&gt; 16) &amp;amp; 0xff);

    float tr = r * m[0] + g * m[3] + b * m[6];
    float tg = r * m[1] + g * m[4] + b * m[7];
    float tb = r * m[2] + g * m[5] + b * m[8];
    r = tr;
    g = tg;
    b = tb;

    if (r &amp;lt; 0.f) r = 0.f;
    if (r &gt; 255.f) r = 255.f;
    if (g &amp;lt; 0.f) g = 0.f;
    if (g &gt; 255.f) g = 255.f;
    if (b &amp;lt; 0.f) b = 0.f;
    if (b &gt; 255.f) b = 255.f;

    r = (r - mInBlack) * mOverInWMinInB;
    g = (g - mInBlack) * mOverInWMinInB;
    b = (b - mInBlack) * mOverInWMinInB;

    if (mGamma != 1.0f) {
        r = (float)java.lang.Math.pow(r, mGamma);
        g = (float)java.lang.Math.pow(g, mGamma);
        b = (float)java.lang.Math.pow(b, mGamma);
    }

    r = (r * mOutWMinOutB) + mOutBlack;
    g = (g * mOutWMinOutB) + mOutBlack;
    b = (b * mOutWMinOutB) + mOutBlack;

    if (r &amp;lt; 0.f) r = 0.f;
    if (r &gt; 255.f) r = 255.f;
    if (g &amp;lt; 0.f) g = 0.f;
    if (g &gt; 255.f) g = 255.f;
    if (b &amp;lt; 0.f) b = 0.f;
    if (b &gt; 255.f) b = 255.f;

    mOutPixels[i] = ((int)r) + (((int)g) &amp;lt;&amp;lt; 8) + (((int)b) &amp;lt;&amp;lt; 16)
                    + (mInPixels[i] &amp;amp; 0xff000000);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This code assumes a bitmap has been loaded and transferred to an integer array for processing.  Assuming the bitmaps are already loaded, this is simple.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;        mInPixels = new int[mBitmapIn.getHeight() * mBitmapIn.getWidth()];
        mOutPixels = new int[mBitmapOut.getHeight() * mBitmapOut.getWidth()];
        mBitmapIn.getPixels(mInPixels, 0, mBitmapIn.getWidth(), 0, 0,
                            mBitmapIn.getWidth(), mBitmapIn.getHeight());&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the data is processed with the loop, putting it back into the bitmap to draw is simple.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;        mBitmapOut.setPixels(mOutPixels, 0, mBitmapOut.getWidth(), 0, 0,
                             mBitmapOut.getWidth(), mBitmapOut.getHeight());&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The full code of the application is around 232 lines when you include code to compute the constants for the filter kernel, manage the controls, and display the image.  On the devices I have laying around this takes about 140-180ms to process an 800x423 image.&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/-6jVhUd2Tyk4/TwzHq8NEgtI/AAAAAAAABBw/1kLwL4oY2Xw/s1600/city2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 600px; " src="http://2.bp.blogspot.com/-6jVhUd2Tyk4/TwzHq8NEgtI/AAAAAAAABBw/1kLwL4oY2Xw/s400/city2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5696147169246216914" /&gt;&lt;/a&gt;&lt;p&gt;What if that is not fast enough?  &lt;/p&gt;&lt;p&gt;Porting the kernel of this image processing to RS (available at &lt;a href="http://code.google.com/p/android-renderscript-samples/source/browse/Levels"&gt;android-renderscript-samples&lt;/a&gt;) is quite simple.  The pixel processing kernel above, reimplemented for RS looks like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
    float3 pixel = convert_float4(in[0]).rgb;
    pixel = rsMatrixMultiply(&amp;amp;colorMat, pixel);
    pixel = clamp(pixel, 0.f, 255.f);
    pixel = (pixel - inBlack) * overInWMinInB;
    if (gamma != 1.0f)
        pixel = pow(pixel, (float3)gamma);
    pixel = pixel * outWMinOutB + outBlack;
    pixel = clamp(pixel, 0.f, 255.f);
    out-&gt;xyz = convert_uchar3(pixel);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It takes far fewer lines of code because of the built-in support for vectors of floats, matrix operations, and format conversions.  Also note that there is no loop present.&lt;/p&gt;&lt;p&gt;The setup code is slightly more complex because you also need to load the script.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;        mRS = RenderScript.create(this);
        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
                                                          Allocation.MipmapControl.MIPMAP_NONE,
                                                          Allocation.USAGE_SCRIPT);
        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
                                                           Allocation.MipmapControl.MIPMAP_NONE,
                                                           Allocation.USAGE_SCRIPT);
        mScript = new ScriptC_levels(mRS, getResources(), R.raw.levels);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This code creates the RS context.  It then uses this context to create two memory allocations to hold the RS copy of the bitmap data.  Last, it loads the script to process the data.&lt;/p&gt;&lt;p&gt;Also in the source there are a few small blocks of code to copy the computed constants to the script when they change.  Because we reflect the globals from the script this is easy.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;        mScript.set_inBlack(mInBlack);
        mScript.set_outBlack(mOutBlack);
        mScript.set_inWMinInB(mInWMinInB);
        mScript.set_outWMinOutB(mOutWMinOutB);
        mScript.set_overInWMinInB(mOverInWMinInB);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Earlier we noted that there was no loop to process all the pixels.  The RS code that processes the bitmap data and copies the result back looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
        mOutPixelsAllocation.copyTo(mBitmapOut);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The first line takes the script and processes the input allocation and places the result in the output allocation.  It does this by calling the natively compiled version of the script above once for each pixel in the allocation.  However, unlike the dalvik implementation, the primitives will automatically launch extra threads to do the work.  This, combined with the performance of native code can produce large performance gains.  I’ll show the results with and without the gamma function working because it adds a lot of cost.&lt;/p&gt;&lt;h4&gt;800x423 image&lt;/h4&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Device&lt;/th&gt;&lt;th&gt;Dalvik&lt;/th&gt;&lt;th&gt;RS&lt;/th&gt;&lt;th&gt;Gain&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Xoom&lt;/th&gt;&lt;td&gt;174ms&lt;/td&gt;&lt;td&gt;39ms&lt;/td&gt;&lt;td&gt;4.5x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Galaxy Nexus&lt;/th&gt;&lt;td&gt;139ms&lt;/td&gt;&lt;td&gt;30ms&lt;/td&gt;&lt;td&gt;4.6x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Tegra 30 device&lt;/th&gt;&lt;td&gt;136ms&lt;/td&gt;&lt;td&gt;19ms&lt;/td&gt;&lt;td&gt;7.2x&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;h4&gt;800x423 image with gamma correction&lt;/h4&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Device&lt;/th&gt;&lt;th&gt;Dalvik&lt;/th&gt;&lt;th&gt;RS&lt;/th&gt;&lt;th&gt;Gain&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Xoom&lt;/th&gt;&lt;td&gt;994ms&lt;/td&gt;&lt;td&gt;259ms&lt;/td&gt;&lt;td&gt;3.8x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Galaxy Nexus&lt;/th&gt;&lt;td&gt;787ms&lt;/td&gt;&lt;td&gt;213ms&lt;/td&gt;&lt;td&gt;3.7x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;Tegra 30 device&lt;/th&gt;&lt;td&gt;783ms&lt;/td&gt;&lt;td&gt;104ms&lt;/td&gt;&lt;td&gt;7.5x&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;These large gains represent a large return on the simple coding investment shown above.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5058038089639562398?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=MwdUsePnIWE:RIVcqQJP4yw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=MwdUsePnIWE:RIVcqQJP4yw:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=MwdUsePnIWE:RIVcqQJP4yw:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/MwdUsePnIWE" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/5058038089639562398?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/5058038089639562398?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/MwdUsePnIWE/levels-in-renderscript.html" title="Levels in Renderscript" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-1AN0Pp29JF8/Twy_hmUcPhI/AAAAAAAABBk/e9VKCVmrytY/s72-c/jsams.jpg" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2012/01/levels-in-renderscript.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcMSX05eyp7ImA9WhRWFk8.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-8646760043976821672</id><published>2012-01-03T13:35:00.000-08:00</published><updated>2012-01-03T14:01:28.323-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-03T14:01:28.323-08:00</app:edited><title>Holo Everywhere</title><content type="html">&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="https://plus.google.com/107708120842840792570/posts"&gt;Adam Powell&lt;/a&gt;, an Android Framework engineer who cares about style. —Tim Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Android 4.0 showcases the Holo theme family, further refined since its debut in Android 3.0. But as most developers know, a new system theme for some Android devices isn’t a new or uncommon event. For developers new system themes mean more design targets for their apps. Using system themes means developers can take advantage of a user’s existing expectations and it can save a lot of production time, but only if an app designer can reliably predict the results. Before Android 4.0 the variance in system themes from device to device could make it difficult to design an app with a single predictable look and feel. We set out to improve this situation for the developer community in Ice Cream Sandwich and beyond.&lt;/p&gt;&lt;div style="float:left; margin: 5px 20px 10px 0;"&gt;&lt;img style="margin:0 0 0 0;width: 240px; height: 400px;" src="http://3.bp.blogspot.com/-Ih4mfw7ugas/TwNnpaoc79I/AAAAAAAABAE/BmBauVfE7OA/s400/Screenshot_2011-11-17-22-19-53.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5693508315147726802" /&gt;&lt;p style="text-align: center;"&gt;Theme.Holo&lt;/p&gt;&lt;/div&gt;&lt;p&gt;If you’re not already familiar with Android’s style and theme system, you should read &lt;a href="http://developer.android.com/guide/topics/ui/themes.html"&gt;Styles and Themes&lt;/a&gt; before continuing.&lt;/p&gt;&lt;h3&gt;Compatibility Standard&lt;/h3&gt;&lt;p&gt;In Android 4.0, Holo is different. We’ve made the inclusion of the unmodified Holo theme family a compatibility requirement for devices running Android 4.0 and forward. If the device has Android Market it will have the Holo themes as they were originally designed.&lt;/p&gt;&lt;p&gt;This standardization goes for all of the public Holo widget styles as well. The Widget.Holo styles will be stable from device to device, safe for use as parent styles for incremental customizations within your app.&lt;/p&gt;&lt;p&gt;The Holo theme family in Android 4.0 consists of the themes Theme.Holo, Theme.Holo.Light, and Theme.Holo.Light.DarkActionBar. Examples of these themes in action are shown in the screenshots lining this post.&lt;/p&gt;&lt;p&gt;To use a Holo theme, explicitly request one from your manifest on your activity or application element, e.g. &lt;code&gt;android:theme="@android:style/Theme.Holo"&lt;/code&gt;. Your app will be displayed using the unmodified theme on all compatible Android 4.0 devices. The Holo themes may also be used as stable parent themes for app-level theme customizations.&lt;/p&gt;&lt;h3&gt;What about device themes?&lt;/h3&gt;&lt;p&gt;We have no desire to restrict manufacturers from building their own themed experience across their devices. In fact we’ve gone further to make this even easier. In Android 4.0’s API (level 14) we’ve added a new public theme family to complement the Holo family introduced in Android 3.0: DeviceDefault. DeviceDefault themes are aliases for the device’s native look and feel. The DeviceDefault theme family and widget style family offer ways for developers to target the device’s native theme with all customizations intact.&lt;/p&gt;&lt;div style="float:right;margin: 5px 0 10px 20px;"&gt;&lt;img style="margin:0 0 0 0;width: 240px; height: 400px;" src="http://1.bp.blogspot.com/-Mi2BW-8T8eY/TwNpdVemR_I/AAAAAAAABAc/-oOTaZ5M4_A/s400/Screenshot_2011-11-17-22-23-18.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5693510306629044210" /&gt;&lt;p style="text-align: center;"&gt;Theme.Holo.Light&lt;/p&gt;&lt;/div&gt;&lt;p&gt; Formally separating these theme families will also make future merges easier for manufacturers updating to a new platform version, helping more devices update more quickly. Google’s Nexus devices alias DeviceDefault to the unmodified Holo themes.&lt;/p&gt;&lt;h3&gt;Making use of your chosen theme&lt;/h3&gt;&lt;p&gt;We’ve added a number of theme attributes to report common metrics and color palette info to apps that want to fit in with a theme. These include highlight colors, default padding and margins for common UI elements such as list items, and more. Apps that wish to integrate with their chosen theme (both Holo and DeviceDefault included) can refer to these theme attributes as in the examples below:&lt;/p&gt;&lt;p&gt;Sample button with system-supplied touch highlight:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;ImageButton android:id="@+id/my_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/button_icon"
    android:background="?android:attr/selectableItemBackground" /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sample widget with a custom pressedHighlightColor attribute, value retrieved from the system theme:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;MyWidget android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    myapp:pressedHighlightColor="?android:attr/colorPressedHighlight" /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sample list item layout using system-supplied metrics and text appearance:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;LinearLayout android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
    android:paddingRight="?android:attr/listPreferredItemPaddingRight"&gt;
    &amp;lt;TextView android:id="@+id/text"
        android:textAppearance="?android:attr/textAppearanceListItem" /&gt;
    &amp;lt;!-- Other views here --&gt;
&amp;lt;/LinearLayout&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style="float:left; margin: 5px 20px 10px 0;"&gt;&lt;img style="margin:0 0 0 0;width: 240px; height: 400px;" src="http://1.bp.blogspot.com/-99NqKnTQ2Ew/TwNp6O1LBVI/AAAAAAAABAo/TIQZ27oOhd4/s400/Screenshot_2011-11-17-22-24-28.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5693510803060884818"  /&gt;&lt;p style="text-align: center;"&gt;Theme.Holo.Light.DarkActionBar&lt;br/&gt;(Available in API level 14 and above)&lt;/p&gt;&lt;/div&gt;&lt;h3&gt;Defaults for Older Apps&lt;/h3&gt;&lt;p&gt;If an app does not explicitly request a theme in its manifest, Android 4.0 will determine the default theme based on the app’s targetSdkVersion to maintain the app’s original expectations: For values less than 11, &lt;code&gt;@android:style/Theme&lt;/code&gt;; between 11 and 13 &lt;code&gt;@android:style/Theme.Holo&lt;/code&gt;; and for 14 and higher &lt;code&gt;@android:style/Theme.DeviceDefault&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;Using Holo while supporting Android 2.x&lt;/h3&gt;&lt;p&gt;Most Android developers will still want to support 2.x devices for a while as updates and new devices continue to roll out. This doesn’t stop you from taking advantage of newer themes on devices that support them though. Using Android’s resource system you can define themes for your app that are selected automatically based on the platform version of the device it’s running on.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Theme.Holo and Theme.Holo.Light have been available since API level 11, but Theme.Holo.Light.DarkActionBar is new in API level 14.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;res/values/themes.xml:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;resources&gt;
    &amp;lt;style name="MyTheme" parent="&lt;b&gt;@android:style/Theme&lt;/b&gt;"&gt;
        &amp;lt;!-- Any customizations for your app running on pre-3.0 devices here --&gt;
    &amp;lt;/style&gt;
&amp;lt;/resources&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;res/values-v11/themes.xml:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;resources&gt;
    &amp;lt;style name="MyTheme" parent="&lt;b&gt;@android:style/Theme.Holo&lt;/b&gt;"&gt;
        &amp;lt;!-- Any customizations for your app running on devices with Theme.Holo here --&gt;
    &amp;lt;/style&gt;
&amp;lt;/resources&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, in AndroidManifest.xml:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!-- [...] --&gt;
    &amp;lt;application android:name="MyApplication"
            android:label="@string/application_label"
            android:icon="@drawable/app_icon"
            android:hardwareAccelerated="true"
            android:theme="@style/MyTheme"&gt;
&amp;lt;!-- [...] --&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can go as far with this idea as you like, up to and including defining your own theme attributes with different values across configurations for use in your other resources. To learn more about Android’s resource system, see &lt;a href="http://developer.android.com/guide/topics/resources/index.html"&gt;Application Resources&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Final Thoughts&lt;/h3&gt;&lt;p&gt;Android apps running on 4.0 and forward can use the Holo themes and be assured that their look and feel will not change when running on a device with a custom skin. Apps that wish to use the device’s default styling can do so using the DeviceDefault themes that are now in the public API. These changes let you spend more time on your design and less time worrying about what will be different from one device to another. Finally, Android’s resource system allows you to support features from the latest platform version while offering graceful fallback on older devices.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8646760043976821672?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=_qkac7tku-4:_YSl4q5ifZ8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=_qkac7tku-4:_YSl4q5ifZ8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=_qkac7tku-4:_YSl4q5ifZ8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/_qkac7tku-4" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/8646760043976821672?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/8646760043976821672?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/_qkac7tku-4/holo-everywhere.html" title="Holo Everywhere" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-Ih4mfw7ugas/TwNnpaoc79I/AAAAAAAABAE/BmBauVfE7OA/s72-c/Screenshot_2011-11-17-22-19-53.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2012/01/holo-everywhere.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUNRns6fSp7ImA9WhRXE04.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-7567337483684147968</id><published>2011-12-19T10:55:00.000-08:00</published><updated>2011-12-19T14:04:57.515-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-19T14:04:57.515-08:00</app:edited><title>Watch out for XmlPullParser.nextText()</title><content type="html">&lt;a href="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s1600/jessehawaii.jpg"&gt;&lt;img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 150px; height: 149px;" src="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s200/jessehawaii.jpg" border="0" alt="Jesse Wilson" id="BLOGGER_PHOTO_ID_5657543353414584562" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="http://www.publicobject.com/"&gt;Jesse Wilson&lt;/a&gt; from the Dalvik team. —Tim Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Using &lt;a href="http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html"&gt;XmlPullParser&lt;/a&gt; is an efficient and maintainable way to parse XML on Android. Historically Android has had two implementations of this interface:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;KXmlParser, via &lt;a href="http://developer.android.com/reference/org/xmlpull/v1/XmlPullParserFactory.html#newPullParser()"&gt;XmlPullParserFactory.newPullParser()&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ExpatPullParser, via &lt;a href="http://developer.android.com/reference/android/util/Xml.html#newPullParser()"&gt;Xml.newPullParser()&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The implementation from &lt;code&gt;Xml.newPullParser()&lt;/code&gt; had a bug where calls to &lt;code&gt;nextText()&lt;/code&gt; didn’t always advance to the &lt;code&gt;END_TAG&lt;/code&gt; as the documentation promised it would. As a consequence, some apps may be working around the bug with extra calls to &lt;code&gt;next()&lt;/code&gt; or &lt;code&gt;nextTag()&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;    public void parseXml(Reader reader)
            throws XmlPullParserException, IOException {
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(reader);

        parser.nextTag();
        parser.require(XmlPullParser.START_TAG, null, "menu");
        while (parser.nextTag() == XmlPullParser.START_TAG) {
            parser.require(XmlPullParser.START_TAG, null, "item");
            String itemText = parser.nextText();
            &lt;b&gt;parser.nextTag(); // this call shouldn’t be necessary!&lt;/b&gt;
            parser.require(XmlPullParser.END_TAG, null, "item");
            System.out.println("menu option: " + itemText);
        }
        parser.require(XmlPullParser.END_TAG, null, "menu");
    }

    public static void main(String[] args) throws Exception {
        new Menu().parseXml(new StringReader("&amp;lt;?xml version='1.0'?&gt;"
                + "&amp;lt;menu&gt;"
                + "  &amp;lt;item&gt;Waffles&amp;lt;/item&gt;"
                + "  &amp;lt;item&gt;Coffee&amp;lt;/item&gt;"
                + "&amp;lt;/menu&gt;"));
    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In Ice Cream Sandwich we changed &lt;code&gt;Xml.newPullParser()&lt;/code&gt; to return a KxmlParser and deleted our ExpatPullParser class. This fixes the &lt;code&gt;nextTag()&lt;/code&gt; bug. Unfortunately, apps that currently work around the bug may crash under Ice Cream Sandwich:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;org.xmlpull.v1.XmlPullParserException: expected: END_TAG {null}item (position:START_TAG &amp;lt;item&gt;@1:37 in java.io.StringReader@40442fa8) 
     at org.kxml2.io.KXmlParser.require(KXmlParser.java:2046)
     at com.publicobject.waffles.Menu.parseXml(Menu.java:25)
 at com.publicobject.waffles.Menu.main(Menu.java:32)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The fix is to call &lt;code&gt;nextTag()&lt;/code&gt; after a call to &lt;code&gt;nextText()&lt;/code&gt; only if the current position is not an &lt;code&gt;END_TAG&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  while (parser.nextTag() == XmlPullParser.START_TAG) {
      parser.require(XmlPullParser.START_TAG, null, "item");
      String itemText = parser.nextText();
      if (parser.getEventType() != XmlPullParser.END_TAG) {
          parser.nextTag();
      }
      parser.require(XmlPullParser.END_TAG, null, "item");
      System.out.println("menu option: " + itemText);
  }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The code above will parse XML correctly on all releases. If your application uses &lt;code&gt;nextText()&lt;/code&gt; extensively, use this helper method in place of calls to &lt;code&gt;nextText()&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  private String safeNextText(XmlPullParser parser)
          throws XmlPullParserException, IOException {
      String result = parser.nextText();
      if (parser.getEventType() != XmlPullParser.END_TAG) {
          parser.nextTag();
      }
      return result;
  }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Moving to a single XmlPullParser simplifies maintenance and allows us to spend more energy on improving system performance.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7567337483684147968?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=gEupS9k-CQI:2Ufc2X6nwng:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=gEupS9k-CQI:2Ufc2X6nwng:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=gEupS9k-CQI:2Ufc2X6nwng:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/gEupS9k-CQI" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/7567337483684147968?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/7567337483684147968?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/gEupS9k-CQI/watch-out-for-xmlpullparsernexttext.html" title="Watch out for XmlPullParser.nextText()" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s72-c/jessehawaii.jpg" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/12/watch-out-for-xmlpullparsernexttext.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEENR3c9eCp7ImA9WhRXEEs.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-4401349552320883515</id><published>2011-12-16T11:00:00.000-08:00</published><updated>2011-12-16T11:11:36.960-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-16T11:11:36.960-08:00</app:edited><title>Android 4.0.3 Platform and Updated SDK tools</title><content type="html">&lt;p&gt;Today we are announcing Android 4.0.3, an incremental release of the Android 4.0 (Ice Cream Sandwich) platform. The new release includes a variety of optimizations and bug fixes for phones and tablets, as well as a small number of new APIs for developers. The new API level is 15.&lt;/p&gt;&lt;p&gt;Some of the new APIs in Android 4.0.3 include:&lt;/p&gt;&lt;dl&gt;&lt;dd&gt;&lt;p&gt;&lt;em&gt;Social stream API in Contacts provider:&lt;/em&gt; Applications that use social stream data such as status updates and check-ins can now sync that data with each of the user’s contacts, providing items in a stream along with photos for each. This new API lets apps show users what the people they know are doing or saying, in addition to their photos and contact information.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Calendar provider enhancements.&lt;/em&gt; Apps can now add color to events, for easier tracking, and new attendee types and states are now available.&lt;/p&gt;&lt;p&gt;&lt;em&gt;New camera capabilities.&lt;/em&gt; Apps can now check and manage video stabilization and use QVGA resolution profiles where needed.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Accessibility refinements.&lt;/em&gt; Improved content access for screen readers and new status and error reporting for text-to-speech engines.&lt;/p&gt;&lt;p&gt;Incremental improvements in graphics, database, spell-checking, Bluetooth, and more.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;p&gt;For a complete overview of what’s new in the platform, see the &lt;a href="http://developer.android.com/sdk/android-4.0.3.html"&gt;Android 4.0.3 API Overview&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Going forward, we’ll be focusing our partners on Android 4.0.3 as the base version of Ice Cream Sandwich. The new platform will be rolling out to production phones and tablets in the weeks ahead, so we strongly encourage you to test your applications on Android 4.0.3 as soon as possible.&lt;/p&gt;&lt;p&gt;We would also like to remind developers that we recently released new version of the &lt;a href="http://developer.android.com/sdk/tools-notes.html"&gt;SDK Tools&lt;/a&gt; (r16) and of the &lt;a href="http://developer.android.com/sdk/eclipse-adt.html"&gt;Eclipse plug-in&lt;/a&gt; (ADT 16.0.1). We have also updated the &lt;a href="http://developer.android.com/sdk/ndk/index.html"&gt;NDK&lt;/a&gt; to r7.&lt;/p&gt;&lt;p&gt;Visit the &lt;a href="http://developer.android.com/sdk/index.html"&gt;Android Developers&lt;/a&gt; site for more information about Android 4.0.3 and other platform versions. To get started developing or testing on the new platform, you can download it into your SDK using the &lt;a href="http://developer.android.com/sdk/adding-components.html"&gt;Android SDK Manager&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-4401349552320883515?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=kuKj9bxAHFM:Qg8bfm9VLSM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=kuKj9bxAHFM:Qg8bfm9VLSM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=kuKj9bxAHFM:Qg8bfm9VLSM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/kuKj9bxAHFM" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/4401349552320883515?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/4401349552320883515?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/kuKj9bxAHFM/android-403-platform-and-updated-sdk.html" title="Android 4.0.3 Platform and Updated SDK tools" /><author><name>Xavier Ducrohet, Android SDK Tech Lead</name><uri>http://www.blogger.com/profile/05953032183412177238</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><feedburner:origLink>http://android-developers.blogspot.com/2011/12/android-403-platform-and-updated-sdk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4BSH8_eyp7ImA9WhRXEEw.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-3511095358900350369</id><published>2011-12-15T20:00:00.000-08:00</published><updated>2011-12-15T21:22:39.143-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-15T21:22:39.143-08:00</app:edited><title>Introducing Android Training</title><content type="html">&lt;a href="http://2.bp.blogspot.com/-65ZTcnMYW9c/TurVOon7PrI/AAAAAAAAA_s/07tBb3zCktI/s1600/new%2Bprof.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 400px; height: 277px;" src="http://2.bp.blogspot.com/-65ZTcnMYW9c/TurVOon7PrI/AAAAAAAAA_s/07tBb3zCktI/s400/new%2Bprof.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5686591926908436146" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="https://plus.google.com/111169963967137030210/posts"&gt;Reto Meier&lt;/a&gt;, Android Developer Relations Tech Lead.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Today I’m thrilled to announce the beta launch of &lt;a href="https://developer.android.com/training/"&gt;Android Training&lt;/a&gt; — a collection of classes that we hope will help you to build better Android apps. &lt;/p&gt;&lt;p&gt;From &lt;a href="https://developer.android.com/training/design-navigation/"&gt;designing effective navigation&lt;/a&gt;, to &lt;a href="https://developer.android.com/training/managing-audio/"&gt;managing audio playback&lt;/a&gt;, to &lt;a href="https://developer.android.com/training/monitoring-device-state/"&gt;optimizing battery life&lt;/a&gt;, these classes are designed to demonstrate best practices for solving common Android development problems.&lt;/p&gt;&lt;p&gt;Each class explains the steps required to solve a problem, or implement a feature, with plenty of code snippets and sample code for you to use within your own apps. &lt;/p&gt;&lt;p&gt;We’re starting small and this is just the beginning for Android Training. Over the coming months we will be increasing the number of classes available, as well as introducing over-arching courses and sample apps to further help your development experience.&lt;/p&gt;&lt;p&gt;Helping developers build great apps is what the Android Developer Relations team is all about, so we’re excited to see how you use these classes to make your apps even better.&lt;/p&gt;&lt;p&gt;We’d love to know what you think of these classes, and what classes you’d like to see next.&lt;!-- Let us know over at Google+ [Link to Android Google+ page].--&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3511095358900350369?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=AK5WxM_vnEI:7vHvwqXcbbI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=AK5WxM_vnEI:7vHvwqXcbbI:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=AK5WxM_vnEI:7vHvwqXcbbI:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/AK5WxM_vnEI" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/3511095358900350369?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/3511095358900350369?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/AK5WxM_vnEI/introducing-android-training.html" title="Introducing Android Training" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-65ZTcnMYW9c/TurVOon7PrI/AAAAAAAAA_s/07tBb3zCktI/s72-c/new%2Bprof.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/12/introducing-android-training.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUEQHk9cCp7ImA9WhRQGUw.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-2298285560651431866</id><published>2011-12-14T14:36:00.000-08:00</published><updated>2011-12-14T17:23:21.768-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-14T17:23:21.768-08:00</app:edited><title>More Android Games that Play Nice</title><content type="html">&lt;a href="http://4.bp.blogspot.com/-fixaHjPgkZo/Tukog-1pbjI/AAAAAAAAA_Q/iqVq-CVMxac/s1600/dan.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 185px; height: 228px;" src="http://4.bp.blogspot.com/-fixaHjPgkZo/Tukog-1pbjI/AAAAAAAAA_Q/iqVq-CVMxac/s400/dan.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5686120551620898354" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="https://plus.google.com/105593270217665985575/posts"&gt;Dan Galpin&lt;/a&gt;, who lives the Android Games lifestyle every day.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Making a game on Android is easy. Making a great game for a mobile, multitasking, often multi-core, multi-purpose system like Android is trickier. Even the best developers frequently make mistakes in the way they interact with the Android system and with other applications — mistakes that don’t affect the quality of gameplay, but which affect the quality of the user’s experience in other ways.&lt;/p&gt;&lt;p&gt;A truly great Android game knows how to play nice: how to fit seamlessly into the system of apps, services, and UI features that run on Android devices. In this multi-part series of posts, Android Developer Relations engineers who specialize in games explain what it takes to make your game play nice.&lt;/p&gt;&lt;h3&gt;II: Navigation and Lifecycle&lt;/h3&gt;&lt;p&gt;Android users get used to using the back key.  We expect the volume keys to work in some intuitive fashion.  We expect that the home key behaves in a manner consistent with the &lt;a href="http://developer.android.com/guide/practices/ui_guidelines/activity_task_design.html"&gt;Android navigation paradigm&lt;/a&gt;.  Sometimes we even expect the menu key to do something.&lt;/p&gt;&lt;h3&gt;1. Problem: There’s no place like [Home]&lt;/h3&gt;&lt;p&gt;I’m playing [insert favorite game here] and I accidentally hit the [Home] key or the [Back] key. This is probably happening because I’m furiously using the touchscreen to actually play the game.  Whether I’ve been cutting ropes, controlling aircraft, cleaving fruit, or flinging birds, I’m almost certainly angry if I’ve suddenly lost all of my game progress.&lt;/p&gt;&lt;h4&gt;What went wrong?&lt;/h4&gt;&lt;p&gt;Lots of developers assume that pressing the Home key exits a game.  Perhaps this is because on some mobile devices the Home key is a somewhat-difficult-to-press physical button. Depending on the device and Android release, it might be a physical, capacitive, or soft button. This means that it is relatively easy to hit accidentally.  Having progress lost by such an event as an incoming call is even worse.&lt;/p&gt;&lt;h4&gt;How to avoid Angry Users&lt;/h4&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Save as much about the status of the game into the Bundle in &lt;a href="http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)"&gt;onSaveInstanceState()&lt;/a&gt; as you can. This helper function will get called whenever your application receives an &lt;a href="http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)"&gt;onPause()&lt;/a&gt; callback.  Note that you can save byte arrays into that bundle, so it can easily be used for raw data.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If your game takes lots of native system resources, consider dumping large textures (or all textures and geometry) during onPause() or onStop().  (&lt;a href="a"&gt;GLSurfaceView&lt;/a&gt; will do this automatically unless you &lt;a href="http://developer.android.com/reference/android/opengl/GLSurfaceView.html#setPreserveEGLContextOnPause(boolean)"&gt;tell it not to&lt;/a&gt; — at least you can tell it not to do so starting in API level 11).  This will help your title continue to reside in memory, which will typically speed task-switching back to your game for very large titles that might otherwise be swapped out of memory, but may slow things down for smaller titles that can more efficiently multitask if they don’t bother to do this.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;When your game resumes, restore the state from the bundle in &lt;a href="http://developer.android.com/reference/android/app/Activity.html#onRestoreInstanceState(android.os.Bundle)"&gt;onRestoreInstanceState()&lt;/a&gt;. If there is any sort of time-consuming loading that has to be done, make sure that you notify the user of what is happening to give them the best possible experience.&lt;/p&gt;&lt;/li&gt;&lt;p&gt;&lt;li&gt;Test thoroughly!&lt;/li&gt;&lt;/p&gt;&lt;/ol&gt;&lt;h4&gt;2. Problem: [Back] I say!&lt;/h4&gt;&lt;p&gt;I’m in the middle of playing a game and I hit the back key.  One of several bad things can happen here:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;The game exits immediately, losing all state and leading to Angry User Syndrome.  (see Problem 1).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The game does nothing.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h4&gt;What went wrong?&lt;/h4&gt;&lt;p&gt;We already know what is wrong with scenario 1.  It’s essentially a data loss scenario, and it’s worse than &lt;a href="http://www.youtube.com/watch?v=Tjl9tg9smgc"&gt;pigs stealing your eggs&lt;/a&gt;.  What is wrong with scenario 2?&lt;/p&gt;&lt;p&gt;The [Back] key is an essential part of the Android navigation paradigm.  If the back key doesn’t return to the previous screen in the activity stack (or in the game hierarchy) there better be a very good reason, such as an active document with no capability to save a draft.&lt;/p&gt;&lt;h4&gt;What to do about it&lt;/h4&gt;&lt;p&gt;If the user is in the middle of gameplay It is customary to display some sort of dialog asking the user if they intended the action:&lt;/p&gt;&lt;p&gt;“Are you sure you wish to exit now?  &lt;a href="http://www.youtube.com/watch?v=1JpdW-D6c14"&gt;That monster looks hungry&lt;/a&gt;.”&lt;/p&gt;&lt;p&gt;In an extreme action game, you might also wish to do something similar to what &lt;a href="http://code.google.com/p/replicaisland/"&gt;Replica Island&lt;/a&gt; (RI) did.  RI assumed that any [Back] keypress that happened within 200ms of another touch event was invalid in order to make it a bit more challenging to accidentally press the key.&lt;/p&gt;&lt;p&gt;At the Main Menu of the game, you can decide whether it makes sense to prompt the user or not.  If your game has very long load times, you might want to prompt the user.&lt;/p&gt;&lt;h3&gt;3.  Problem: Quiet [Down]!&lt;/h3&gt;&lt;p&gt;There’s nothing worse than wanting to settle down for a good session of [insert favorite game here] in some sort of public place with your volume turned up.  Suddenly everyone has learned that you &lt;a href="http://youtu.be/8XJUYmwBlZA"&gt;prefer pummelling produce&lt;/a&gt; to predicting present progressions and that’s practically profane in your profession.&lt;/p&gt;&lt;h4&gt;What went wrong?&lt;/h4&gt;&lt;p&gt;By default, volume keys in most Android devices will control the ringer volume, and your application must pass the volume keys through to the super class so this continues to work.&lt;/p&gt;&lt;h4&gt;What to do about it&lt;/h4&gt;&lt;p&gt;In order to make these keys control the music volume (which is the channel that your game will be using), you need to call &lt;a href="http://developer.android.com/reference/android/app/Activity.html#setVolumeControlStream(int)"&gt;setVolumeControlStream(AudioManager.STREAM_MUSIC)&lt;/a&gt;.  As stated previously, all you need to do is pass these keys through to the framework and you’ll get control of the audio in the standard and proper way.  Do it as early as possible so a user can start changing the volume far before you begin playing anything.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2298285560651431866?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=sne9dsqQUc4:fvACYXtde2k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=sne9dsqQUc4:fvACYXtde2k:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=sne9dsqQUc4:fvACYXtde2k:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/sne9dsqQUc4" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2298285560651431866?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2298285560651431866?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/sne9dsqQUc4/more-android-games-that-play-nice.html" title="More Android Games that Play Nice" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-fixaHjPgkZo/Tukog-1pbjI/AAAAAAAAA_Q/iqVq-CVMxac/s72-c/dan.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/12/more-android-games-that-play-nice.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcMRno9cSp7ImA9WhRQF08.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-1436820868716344333</id><published>2011-12-12T13:40:00.000-08:00</published><updated>2011-12-12T13:41:27.469-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-12T13:41:27.469-08:00</app:edited><title>Add Voice Typing To Your IME</title><content type="html">&lt;p&gt;&lt;i&gt;[This post is by Luca Zanolin, an Android engineer who works on voice typing.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;A new feature available in Android 4.0 is voice typing: the difference for users is that the recognition results appear in the text box while they are still speaking. If you are an IME developer, you can easily integrate with voice typing. &lt;/p&gt;&lt;p&gt;To simplify the integration, if you download &lt;a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/voiceimeutils.jar"&gt;this&lt;/a&gt; library and modify your IME as described below, everything will work smoothly on any device with Android 2.2 or later. On 4.0+, users will get voice typing, and earlier versions will use standard voice recognition; the difference is illustrated below.&lt;/p&gt;&lt;a href="http://4.bp.blogspot.com/-HXI0a-ADssM/TuZvhNAPSsI/AAAAAAAAA-c/bh9t_h2L_x0/s1600/voice-modes.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 333px;" src="http://4.bp.blogspot.com/-HXI0a-ADssM/TuZvhNAPSsI/AAAAAAAAA-c/bh9t_h2L_x0/s400/voice-modes.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5685354195818859202" /&gt;&lt;/a&gt;&lt;p&gt;To see how to integrate voice typing you can take a look at this &lt;a href="https://code.google.com/p/google-voice-typing-integration/source/browse/#git%2FVoiceImeDemo"&gt;sample IME&lt;/a&gt;. The IME is really simple and contains only one button: a microphone. By pressing the microphone, the user triggers voice recognition.&lt;/p&gt;&lt;p&gt;Here are the steps that you need to follow to integrate voice recognition into your IME.&lt;/p&gt;&lt;h3&gt;Download the library&lt;/h3&gt;&lt;p&gt;Download &lt;a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/voiceimeutils.jar"&gt;this library&lt;/a&gt; and add it to your IME APK.&lt;/p&gt;&lt;h3&gt;Create the voice recognition trigger&lt;/h3&gt;&lt;p&gt;The library contains the &lt;a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/index.html?com/google/android/voiceime/VoiceRecognitionTrigger.html"&gt;VoiceRecognitionTrigger&lt;/a&gt; helper class. Create an instance of it inside the &lt;a href="http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html#onCreate()"&gt;InputMethodService#onCreate&lt;/a&gt; method in your IME.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;public void onCreate() {
    super.onCreate();
    ...
    mVoiceRecognitionTrigger = new VoiceRecognitionTrigger(this);
}&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Add the microphone icon to your IME&lt;/h3&gt;&lt;p&gt;You need to modify the UI of your IME, add a microphone icon, and register an OnClickListener to trigger voice recognition. You can find the assets inside the sample IME. The microphone icon should be displayed only if voice recognition is installed; use &lt;a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/index.html?com/google/android/voiceime/VoiceRecognitionTrigger.html"&gt;VoiceRecognitionTrigger#isInstalled()&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;public View onCreateInputView() {
  LayoutInflater inflater = (LayoutInflater) getSystemService(
      Service.LAYOUT_INFLATER_SERVICE);
  mView = inflater.inflate(R.layout.ime, null);
  ...
  mButton = (ImageButton) mView.findViewById(R.id.mic_button);
  if (mVoiceRecognitionTrigger.isInstalled()) {
    mButton.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        mVoiceRecognitionTrigger.startVoiceRecognition();
      }
    });
    mButton.setVisibility(View.VISIBLE);
  } else {
    mButton.setVisibility(View.GONE);
  }
  return mView;
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If your IME supports multiple languages, you can specify in which language recognition should be done as a parameter of &lt;a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/com/google/android/voiceime/VoiceRecognitionTrigger.html#startVoiceRecognition(java.lang.String)"&gt;startVoiceRecognition()&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Notify the trigger when your IME starts&lt;/h3&gt;&lt;p&gt;When your IME starts, you need to notify the trigger, so it can insert into the text view any pending recognition results.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
  super.onStartInputView(info, restarting);
  if (mVoiceRecognitionTrigger != null) {
    mVoiceRecognitionTrigger.onStartInputView();
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Modify your AndroidManifest&lt;/h3&gt;&lt;p&gt;In order to start a voice recognition through the Intent API, the library uses a service and an activity, and you need to add them into your manifest.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;manifest ... &gt;
  &amp;lt;application ...&gt;
    ...
    &amp;lt;service android:name="com.google.android.voiceime.ServiceHelper" /&gt;
    &amp;lt;activity
        android:name="com.google.android.voiceime.ActivityHelper"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        android:excludeFromRecents="true"
        android:windowSoftInputMode="stateAlwaysHidden"
        android:finishOnTaskLaunch="true"
        android:configChanges="keyboard|keyboardHidden|navigation
                               |orientation"/&gt;
  &amp;lt;/application&gt;
&amp;lt;/manifest&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Update the microphone icon dynamically (optional)&lt;/h3&gt;&lt;p&gt;This step is optional, but you should implement it if possible as it will improve the user experience. Voice recognition requires network access, and if there is no network, your IME should notify the user that voice recognition is currently disabled. To achieve this, you need to register the &lt;a href="https://google-voice-typing-integration.googlecode.com/git/VoiceImeUtils/doc/index.html?com/google/android/voiceime/VoiceRecognitionTrigger.html"&gt;VoiceRecognitionTrigger.Listener&lt;/a&gt; and enable/disable the microphone accordingly. &lt;/p&gt;&lt;p&gt;The listener is registered in &lt;a href="http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html#onCreate()"&gt;InputMethodService#onCreate&lt;/a&gt;, and you have to unregister it in &lt;a href="http://developer.android.com/reference/android/inputmethodservice/InputMethodService.html#onDestroy()"&gt;InputMethodService#onDestroy&lt;/a&gt;, otherwise you will leak the listener.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;@Override
public void onCreate() {
  super.onCreate();
  ... 
  mVoiceRecognitionTrigger = new VoiceRecognitionTrigger(this);
  mVoiceRecognitionTrigger.register(new VoiceRecognitionTrigger.Listener() {
    @Override
    public void onVoiceImeEnabledStatusChange() {
      updateVoiceImeStatus();
    }
  });
}

...
@Override
public void onDestroy() {
  ...
  if (mVoiceRecognitionTrigger != null) {
    mVoiceRecognitionTrigger.unregister(this);
  }
  super.onDestroy();
}

private void updateVoiceImeStatus() {
  if (mVoiceRecognitionTrigger.isInstalled()) {
    mButton.setVisibility(View.VISIBLE);
    if (mVoiceRecognitionTrigger.isEnabled()) {
      mButton.setEnabled(true);
    } else {
      mButton.setEnabled(false);
    }
  } else {
    mButton.setVisibility(View.GONE);
  }
  mView.invalidate();
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And add this permission into your manifest:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;manifest ... &gt;
  ...
  &amp;lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/&gt;
  ...
&amp;lt;/manifest&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;That&amp;rsquo;s all there is to it&lt;/h3&gt;&lt;p&gt;Voice recognition makes it easy for users to do more with their Android devices, so we appreciate your support in adding it to your IMEs.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1436820868716344333?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=ZmXHrqZ2NQw:_8_W6O147Ew:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=ZmXHrqZ2NQw:_8_W6O147Ew:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=ZmXHrqZ2NQw:_8_W6O147Ew:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/ZmXHrqZ2NQw" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/1436820868716344333?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/1436820868716344333?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/ZmXHrqZ2NQw/add-voice-typing-to-your-ime.html" title="Add Voice Typing To Your IME" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-HXI0a-ADssM/TuZvhNAPSsI/AAAAAAAAA-c/bh9t_h2L_x0/s72-c/voice-modes.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/12/add-voice-typing-to-your-ime.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EASH85cCp7ImA9WhRQE0o.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-2341397490858895372</id><published>2011-12-08T10:46:00.000-08:00</published><updated>2011-12-08T13:27:29.128-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T13:27:29.128-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Android Market" /><title>A Closer Look at 10 Billion Downloads</title><content type="html">&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-style: italic;"&gt;[This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
On Tuesday, we announced that Android Market passed &lt;a href="http://googleblog.blogspot.com/2011/12/10-billion-android-market-downloads-and.html"&gt;10 Billion app downloads&lt;/a&gt;.  We wanted to look a little deeper at that huge number.  First question: which app was lucky number 10 billion?  &lt;a href="https://market.android.com/details?id=com.photobucket.android"&gt;Photobucket Mobile&lt;/a&gt;.  They’ll be getting a great prize package, including tickets to next year’s Google I/O developer conference. &lt;br /&gt;
&lt;br /&gt;
Remember we still have 8 days left to celebrate 10 billion downloads with &lt;a href="https://market.android.com/details?id=apps_timed_promotion&amp;feature=banner#?t=W251bGwsMSwyLDIwMSwibnVsbC10b3BfZmVhdHVyZWRfYXBwc19VU19fMV9wcm9tb18xMzIzMzYzMDMyNDc5Il0."&gt;10-cent apps on Android Market&lt;/a&gt;.  You can follow which apps are promoted each day on &lt;a href="https://plus.google.com/104629412415657030658/posts"&gt;+Android&lt;/a&gt;, our Google+ page.&lt;br /&gt;
&lt;br /&gt;
Here’s a graphical deep dive into 10 billion downloads...&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-1Z-9dpBor4U/TuD56U9KBPI/AAAAAAAAAJI/iPjRoIX3gwk/s1600/10B_2_lg.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="1875" width="500" src="http://4.bp.blogspot.com/-WEP0MluJEMg/TuD6CvX3g2I/AAAAAAAAAJU/kaKaccxPajE/s1600/10B_2_lg.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2341397490858895372?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=Kzcgiss31ho:aW7FSIR3ud8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=Kzcgiss31ho:aW7FSIR3ud8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=Kzcgiss31ho:aW7FSIR3ud8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/Kzcgiss31ho" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2341397490858895372?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2341397490858895372?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/Kzcgiss31ho/closer-look-at-10-billion-downloads.html" title="A Closer Look at 10 Billion Downloads" /><author><name>Dirk Dougherty</name><uri>http://www.blogger.com/profile/06459989880590689562</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-WEP0MluJEMg/TuD6CvX3g2I/AAAAAAAAAJU/kaKaccxPajE/s72-c/10B_2_lg.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/12/closer-look-at-10-billion-downloads.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YASH0_cCp7ImA9WhRQEUQ.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-3857213888421166491</id><published>2011-12-06T10:05:00.000-08:00</published><updated>2011-12-06T10:12:29.348-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-06T10:12:29.348-08:00</app:edited><title>10 Billion Android Market Downloads and Counting</title><content type="html">&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-style: italic;"&gt;[This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ruWPqJXWqZY/Tt5SbJxav-I/AAAAAAAAIxE/m18t_RaOJLk/s1600/10B_shafton.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="50" src="http://1.bp.blogspot.com/-ruWPqJXWqZY/Tt5SbJxav-I/AAAAAAAAIxE/m18t_RaOJLk/s400/10B_shafton.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
One billion is a pretty big number by any measurement. However, when it’s describing the &lt;i&gt;speed&lt;/i&gt; at which something is growing, it’s simply amazing. This past weekend, thanks to Android users around the world, &lt;a href="https://market.android.com/apps"&gt;Android Market&lt;/a&gt; exceeded 10 billion app downloads—with a growth rate of one billion app downloads &lt;b&gt;per month&lt;/b&gt;.  We can’t wait to see where this accelerating growth takes us in 2012.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-2Trw6XxAZMY/Tt5SOyqUwkI/AAAAAAAAIw8/Pl1v7EdRpCE/s1600/graph_only_3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-2Trw6XxAZMY/Tt5SOyqUwkI/AAAAAAAAIw8/Pl1v7EdRpCE/s500/graph_only_3.jpg" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
To celebrate this milestone, we partnered with some of the Android developers who contributed to this milestone to make a bunch of great Android apps available at an amazing price.  Starting today for the next 10 days, we’ll have a new set of awesome apps available each day for only &lt;b&gt;10 cents each&lt;/b&gt;.  Today, we are starting with &lt;a href="https://market.android.com/details?id=com.gameloft.android.ANMP.GloftA6HP"&gt;Asphalt 6 HD&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=tipitap.coloring.phones"&gt;Color &amp;amp; Draw for Kids&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=com.endomondo.android.pro"&gt;Endomondo Sports Tracker Pro&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=com.subatomicstudios"&gt;Fieldrunners HD&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=com.rubicon.dev.glwg"&gt;Great Little War Game&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=com.mojang.minecraftpe"&gt;Minecraft&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=com.dama.papercamera"&gt;Paper Camera&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=com.sketchbook"&gt;Sketchbook Mobile&lt;/a&gt;, &lt;a href="https://market.android.com/details?id=com.melodis.midomiMusicIdentifier"&gt;Soundhound Infinity&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="https://market.android.com/details?id=com.touchtype.swiftkey"&gt;Swiftkey X&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Of course, none of these apps would have existed if it weren’t for the developers who created them. Every day, these developers continue to push the limits on what’s possible and delight us in the process.  For that, we thank them.&lt;br /&gt;
&lt;br /&gt;
Please join us in this 10-day celebration and check in every day to see what new apps our developer partners are making available on &lt;a href="https://market.android.com/"&gt;Android Market&lt;/a&gt;—for only a dime.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3857213888421166491?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=WJPTa9zVJ-I:8ly7aSkW3hU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=WJPTa9zVJ-I:8ly7aSkW3hU:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=WJPTa9zVJ-I:8ly7aSkW3hU:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/WJPTa9zVJ-I" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/3857213888421166491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/3857213888421166491?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/WJPTa9zVJ-I/10-billion-android-market-downloads-and.html" title="10 Billion Android Market Downloads and Counting" /><author><name>Dirk Dougherty</name><uri>http://www.blogger.com/profile/06459989880590689562</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-ruWPqJXWqZY/Tt5SbJxav-I/AAAAAAAAIxE/m18t_RaOJLk/s72-c/10B_shafton.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/12/10-billion-android-market-downloads-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEARXk6fSp7ImA9WhRRFU4.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-675355459180656359</id><published>2011-11-28T18:15:00.000-08:00</published><updated>2011-11-28T18:27:24.715-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-28T18:27:24.715-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Android Market" /><title>Games Coming to Android Market in Korea</title><content type="html">&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-style: italic;"&gt;[This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In the 24 months since the first Android device became available locally, Korea has quickly become one of the top countries in Android device activations. In parallel, we’ve also seen tremendous growth in app downloads from Android Market.  Korea is now the second-largest consumer of apps worldwide. Today we are adding to this momentum by bringing games to Android Market in Korea.&lt;br /&gt;
&lt;br /&gt;
Starting right away, Android users in Korea can explore the many thousands of popular game titles available in Android Market and download them onto their devices. For paid games, purchasing is fast and convenient through &lt;a href="http://android-developers.blogspot.com/2011/09/more-carrier-billing-options-on-android.html"&gt;direct carrier billing&lt;/a&gt;, which lets users in Korea easily charge their purchases to their monthly mobile operator bills.&lt;br /&gt;
&lt;br /&gt;
If you are a game developer, now is the time to localize your game resources, app descriptions, and marketing assets to take advantage of this new opportunity. When you are ready, please visit the Android Market developer console to target your app for distribution in South Korea and set prices in Korean Won (KRW). If you don’t want to distribute to Korea right away, you can also exclude it.&lt;br /&gt;
&lt;br /&gt;
With the huge popularity of games on Android and the convenience of direct carrier billing in Korea, we expect to see a jump in game purchases and downloads in the weeks ahead. For game developers worldwide, it’s “game on” in Korea!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-675355459180656359?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=3kZJ2qrg1E8:wzrsnTxi9Ho:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=3kZJ2qrg1E8:wzrsnTxi9Ho:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=3kZJ2qrg1E8:wzrsnTxi9Ho:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/3kZJ2qrg1E8" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/675355459180656359?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/675355459180656359?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/3kZJ2qrg1E8/games-coming-to-android-market-in-korea.html" title="Games Coming to Android Market in Korea" /><author><name>Dirk Dougherty</name><uri>http://www.blogger.com/profile/06459989880590689562</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><feedburner:origLink>http://android-developers.blogspot.com/2011/11/games-coming-to-android-market-in-korea.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8NR3k9fip7ImA9WhRSGUU.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-1665572372970222288</id><published>2011-11-22T06:45:00.000-08:00</published><updated>2011-11-22T09:44:56.766-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-22T09:44:56.766-08:00</app:edited><title>Making Android Games that Play Nice</title><content type="html">&lt;a href="http://4.bp.blogspot.com/-WZ2VRtoH_lA/TsryB8owaYI/AAAAAAAAA-E/OLtnJm8dE2w/s1600/ian2.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 198px; height: 241px;" src="http://4.bp.blogspot.com/-WZ2VRtoH_lA/TsryB8owaYI/AAAAAAAAA-E/OLtnJm8dE2w/s400/ian2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5677616395524794754" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="https://plus.google.com/109486821799932251955/posts"&gt;Ian Ni-Lewis&lt;/a&gt;,  a Developer Advocate who devotes most of his time to making Android games more awesome.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Making a game on Android is easy. Making a &lt;em&gt;great&lt;/em&gt; game for a mobile, multitasking, often multi-core, multi-purpose system like Android is trickier. Even the best developers frequently make mistakes in the way they interact with the Android system and with other applications — mistakes that don’t affect the quality of gameplay, but which affect the quality of the user’s experience in other ways. &lt;/p&gt;&lt;p&gt;A truly great Android game knows how to play nice: how to fit seamlessly into the system of apps, services, and UI features that run on Android devices. In this multi-part series of posts, Android Developer Relations engineers who specialize in games explain what it takes to make your game play nice.&lt;/p&gt;&lt;h3&gt;I: The Audio Lifecycle (or, why is there music coming from my pants?)&lt;/h3&gt;&lt;p&gt;One of the most awesome things about Android is that it can do so much stuff in the background. But when apps aren’t careful about their background behaviors, it can get annoying. Take my own personal pet peeve: game audio that doesn’t know when to quit.&lt;/p&gt;&lt;h3&gt;The problem &lt;/h3&gt;&lt;p&gt;I’m on the bus to work, passing the time with a great Android game. I’m completely entranced by whatever combination of birds, ropes, and ninjas is popular this week. Suddenly I panic: I’ve almost missed my stop! I leap up, quickly locking my phone as I shove it into a pocket. &lt;/p&gt;&lt;p&gt;I arrive breathless at my first meeting of the day. The boss, perhaps sensing my vulnerability, asks me a tough question. Not tough enough to stump me, though — I’ve got the answer to that right here on my Android phone! I whip out my phone and press the unlock button... and the room dissolves in laughter as a certain well-known game ditty blares out from the device.&lt;/p&gt;&lt;p&gt;The initial embarrassment is bad enough, but what’s this? I can’t even mute the thing! The phone is showing the lock screen and the volume buttons are inactive. My stress level is climbing and it takes me three tries to successfully type in my unlock code. Finally I get the thing unlocked, jam my finger on the home button and breathe a sigh of relief as the music stops. But the damage is done — my boss is glowering and for the rest of the week my co-workers make video game noises whenever they pass my desk.&lt;/p&gt;&lt;h3&gt;What went wrong? &lt;/h3&gt;&lt;p&gt;It’s a common mistake: the developer of the game assumed that if the game received an &lt;a href="http://developer.android.com/reference/android/app/Activity.html#onResume()"&gt;onResume()&lt;/a&gt; message, it was safe to resume audio. The problem is that onResume() doesn’t necessarily mean your app is visible — only that it’s active. In the case of a locked phone, onResume() is sent as soon as the screen turns on, even though the phone’s display is on the lock screen and the volume buttons aren’t enabled. &lt;/p&gt;&lt;p&gt;Fixing this is trickier than it sounds. Some games wait for &lt;a href="http://developer.android.com/reference/android/app/Activity.html#onWindowFocusChanged(boolean)"&gt;onWindowFocusChanged()&lt;/a&gt; instead of onResume(), which works pretty well on Gingerbread. But on Honeycomb and higher, onWindowFocusChanged() is sent when certain foreground windows — like, ironically, the volume control display window — take focus. The result is that when the user changes the volume, all of the sound is muted. Not the developer’s original intent!&lt;/p&gt;&lt;p&gt;Waiting for onResume() &lt;em&gt;and&lt;/em&gt; onFocusChanged() seems like a possible fix, and it works pretty well in a large number of cases. But even this approach has its Achilles’ heel. If the device falls asleep on its own, or if the user locks the phone and then immediately unlocks it, your app may not receive any focus changed messages at all. &lt;/p&gt;&lt;h3&gt;What to do about it&lt;/h3&gt;&lt;p&gt;Here’s the easy two-step way to avoid user embarrassment:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Pause the game (and all sound effects) whenever you receive an &lt;a href="http://developer.android.com/reference/android/app/Activity.html#onPause()"&gt;onPause()&lt;/a&gt; message. When gameplay is interrupted — whether because the phone is locked, or the user received a call, or for some other reason — the game should be paused.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;After the game is paused, require user input to continue. The biggest mistake most game developers make is to automatically restart gameplay and audio as soon as the user returns to the game. This isn’t just a question of solving the “music over lock screen” issue. Users like to come back to a paused game. It’s no fun to switch back to a game, only to realize you’re about to die because gameplay has resumed before you expected it. &lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Some game designers don’t like the idea of pausing the background music when the game is paused. If you absolutely must resume music as soon as your game regains focus, then you should do the following:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Pause playback when you receive onPause().&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;When you receive onResume():&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;If you have previously received an onFocusChanged(false) message, wait for an onFocusChanged(true) message to arrive before resuming playback.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If you have &lt;em&gt;not&lt;/em&gt; previously received an onFocusChanged(false) message, then resume audio immediately.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Test thoroughly! &lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Fixing audio embarrassments is almost always a quick and easy process. Take the time to do it right, and your users will thank you.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1665572372970222288?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=h_wIeDJZpis:rFmfZvlti_8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=h_wIeDJZpis:rFmfZvlti_8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=h_wIeDJZpis:rFmfZvlti_8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/h_wIeDJZpis" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/1665572372970222288?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/1665572372970222288?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/h_wIeDJZpis/making-android-games-that-play-nice.html" title="Making Android Games that Play Nice" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-WZ2VRtoH_lA/TsryB8owaYI/AAAAAAAAA-E/OLtnJm8dE2w/s72-c/ian2.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/11/making-android-games-that-play-nice.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEICQX8zeCp7ImA9WhRSEEg.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-6487068232946048393</id><published>2011-11-11T15:00:00.000-08:00</published><updated>2011-11-11T15:02:40.180-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-11T15:02:40.180-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NDK" /><title>Updated NDK for Android 4.0</title><content type="html">&lt;p&gt;Today we are releasing an updated version of the Android NDK, now in revision 7. The updated NDK lets developers who are using native code get started with the new native APIs available in Android 4.0.&lt;/p&gt;&lt;p&gt;Android NDK r7 includes a number of build system improvements and bug fixes, but most importantly it gives you access to two new sets of APIs:&lt;/p&gt;&lt;dd&gt;&lt;dl&gt;&lt;p&gt;&lt;em&gt;Low-level streaming multimedia:&lt;/em&gt; A new API based on &lt;a href="http://www.khronos.org/openmax/al/"&gt;Khronos OpenMAX AL 1.0.1&lt;/a&gt; provides a direct, efficient path for low-level streaming multimedia. The new path is ideal for applications that need to maintain complete control over media data before passing it to the platform for presentation. For example, media applications can now retrieve data from any source, apply proprietary encryption/decryption, and then send the data to the platform for display.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Audio decoding into PCM:&lt;/em&gt; Extensions to the existing native audio API based on &lt;a href="http://www.khronos.org/opensles/"&gt;Khronos OpenSL ES&lt;/a&gt; let native apps decode compressed audio assets to PCM format.&lt;/p&gt;&lt;/dl&gt;&lt;/dd&gt;&lt;p&gt;For detailed information about how to use these new APIs, please see the documentation included with the Android NDK r7 package. To read about the build system improvements and bug fixes included in this release, check out the &lt;a href="http://developer.android.com/sdk/ndk/index.html"&gt;release notes&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6487068232946048393?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=dOv-Blb2VHQ:9DQTODxCbMo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=dOv-Blb2VHQ:9DQTODxCbMo:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=dOv-Blb2VHQ:9DQTODxCbMo:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/dOv-Blb2VHQ" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/6487068232946048393?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/6487068232946048393?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/dOv-Blb2VHQ/updated-ndk-for-android-40.html" title="Updated NDK for Android 4.0" /><author><name>Xavier Ducrohet, Android SDK Tech Lead</name><uri>http://www.blogger.com/profile/05953032183412177238</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><feedburner:origLink>http://android-developers.blogspot.com/2011/11/updated-ndk-for-android-40.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAAQnc6fip7ImA9WhRRFUQ.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-8379178536336854115</id><published>2011-11-10T15:00:00.000-08:00</published><updated>2011-11-29T10:19:03.916-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-29T10:19:03.916-08:00</app:edited><title>New Layout Widgets: Space and GridLayout</title><content type="html">&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="http://blog.enigmosaurus.net/"&gt;Philip Milne&lt;/a&gt;, who is part of the Android framework team.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Ice Cream Sandwich (ICS) sports two new widgets that have been designed to support the richer user interfaces made possible by larger displays: &lt;a href="http://developer.android.com/reference/android/widget/Space.html"&gt;Space&lt;/a&gt; and &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.html"&gt;GridLayout&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The most commonly used class for layout in Android is &lt;a href="http://developer.android.com/reference/android/widget/LinearLayout.html"&gt;LinearLayout&lt;/a&gt;, which allows its children to be aligned in the usual ways: along either the horizontal or vertical axes. It’s often possible to take a complicated layout and break it down into a set of nested linear layouts and, provided this nesting doesn’t get too deep, this is still a good choice for many simple layouts. &lt;/p&gt;&lt;p&gt;A number of posts and articles (e.g. &lt;a href="http://android-developers.blogspot.com/2009/02/android-layout-tricks-1.html"&gt;Android Layout Tricks #1&lt;/a&gt;, &lt;a href="http://www.androidguys.com/2009/04/24/flattening-the-stack/"&gt;Flattening The Stack&lt;/a&gt;) have highlighted drawbacks of nested layouts; which fall into three basic categories: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Inability to control alignment along both axes simultaneously&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Performance problems in hierarchies that are too deep&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Unsuitability for design tools that support free-form editing &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A simple example of the first problem is the following form: &lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/-v5fdrXd7GNA/TrxWJ35If7I/AAAAAAAAA5Y/4wofsXZwmKs/s1600/milne-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://2.bp.blogspot.com/-v5fdrXd7GNA/TrxWJ35If7I/AAAAAAAAA5Y/4wofsXZwmKs/s400/milne-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5673504358202376114" /&gt;&lt;/a&gt;&lt;p&gt;As the font and the text of the “Email address” label change, we want the label to remain aligned with the &lt;em&gt;baseline&lt;/em&gt; of the component to its right, and aligned with the &lt;em&gt;right&lt;/em&gt; edge of the label below it. It’s not possible to do this with nested LinearLayouts because the label needs to be aligned with other components both horizontally and vertically. &lt;/p&gt;&lt;p&gt;These problems aren’t new to Android, or UI toolkits in general, but we’ve used them to drive our work in enriching platform support for flatter hierarchies. &lt;/p&gt;&lt;h3&gt;GridLayout &lt;/h3&gt;&lt;p&gt;To provide better support for layouts like these we have added a new layout to the Android framework: GridLayout, which can be used to solve the above problems by dividing the container’s real estate into rows and columns: &lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/-ceJ2DjokqHE/TrxWTnrN6yI/AAAAAAAAA5k/1qCEdOM-mqc/s1600/milne-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://2.bp.blogspot.com/-ceJ2DjokqHE/TrxWTnrN6yI/AAAAAAAAA5k/1qCEdOM-mqc/s400/milne-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5673504525647735586" /&gt;&lt;/a&gt;&lt;p&gt;Now the “Email address” label can belong both to a &lt;em&gt;row&lt;/em&gt; that is &lt;em&gt;baseline&lt;/em&gt;-aligned, and a &lt;em&gt;column&lt;/em&gt; that is &lt;em&gt;right&lt;/em&gt;-aligned. &lt;/p&gt;&lt;p&gt;GridLayout uses a grid of infinitely-thin lines to separate its drawing area into: &lt;em&gt;rows&lt;/em&gt;, &lt;em&gt;columns&lt;/em&gt;, and &lt;em&gt;cells&lt;/em&gt;. It supports both row and column &lt;em&gt;spanning&lt;/em&gt;, which together allow a widget to occupy a rectangular range of cells that are next to each other. We’ll use the words &lt;em&gt;row&lt;/em&gt;, &lt;em&gt;column&lt;/em&gt;, and &lt;em&gt;cell&lt;/em&gt; in the text below as shorthand for &lt;em&gt;row group&lt;/em&gt;, &lt;em&gt;column group&lt;/em&gt; and &lt;em&gt;cell group&lt;/em&gt; respectively, where groups have one or more contiguous elements.  &lt;/p&gt;&lt;h4&gt;Similarities with LinearLayout&lt;/h4&gt;&lt;p&gt;Wherever possible, GridLayout uses the same conventions as LinearLayout for all its XML API — so it should be easy to start using GridLayout if you’ve already used LinearLayout. In fact, the APIs are so similar that changing a tag name from LinearLayout to GridLayout in an XML file that uses LinearLayout will often produce a similar UI without requiring any other changes. When it doesn’t, you’ll still generally end up with a good starting point for a two-dimensional layout. &lt;/p&gt;&lt;h3&gt;Getting Started&lt;/h3&gt;&lt;p&gt;Two examples in the samples area of the Android 4.0 SDK show typical use of the programmatic and XML APIs respectively:  &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/GridLayout0.html"&gt;samples/ApiDemos/src/com/example/android/apis/view/GridLayout0.java&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="http://developer.android.com/resources/samples/ApiDemos/res/layout/grid_layout_1.xml"&gt;samples/ApiDemos/res/layout/grid_layout_1.xml&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;[Both examples produce the same UI.] &lt;/p&gt;&lt;p&gt;Here’s a slightly simpler version of the above XML layout. &lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;
&amp;lt;GridLayout
        xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="match_parent"
        android:layout_height="match_parent"

        android:useDefaultMargins="true"
        android:alignmentMode="alignBounds"
        android:columnOrderPreserved="false"

        android:columnCount="4"
        &gt;

    &amp;lt;TextView
            android:text="Email setup"
            android:textSize="32dip"

            android:layout_columnSpan="4"
            android:layout_gravity="center_horizontal"
            /&gt;

    &amp;lt;TextView
            android:text="You can configure email in just a few steps:"
            android:textSize="16dip"

            android:layout_columnSpan="4"
            android:layout_gravity="left"
            /&gt;

    &amp;lt;TextView
            android:text="Email address:"

            android:layout_gravity="right"
            /&gt;

    &amp;lt;EditText
            android:ems="10"
            /&gt;

    &amp;lt;TextView
            android:text="Password:"

            android:layout_column="0"
            android:layout_gravity="right"
            /&gt;

    &amp;lt;EditText
            android:ems="8"
            /&gt;

    &amp;lt;Space
            android:layout_row="4"
            android:layout_column="0"
            android:layout_columnSpan="3"
            android:layout_gravity="fill"
            /&gt;

    &amp;lt;Button
            android:text="Next"

            android:layout_row="5"
            android:layout_column="3"
            /&gt;
&amp;lt;/GridLayout&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The first difference you’ll notice in these examples is the absence of the WRAP_CONTENT and MATCH_PARENT constants that normally adorn Android layout resources. You don’t normally need to use these with GridLayout, for reasons that are described in the API doc for &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.LayoutParams.html"&gt;GridLayout.LayoutParams&lt;/a&gt;. &lt;/p&gt;&lt;h4&gt;Row and Column Indices&lt;/h4&gt;&lt;p&gt;The second thing you may notice in the XML resources is that widgets don’t always explicitly define which cells they are to be placed in. Each widget’s layout parameters have row and column indices that together define where the widget should be placed but when either or both of these values are not specified, GridLayout supplies default values rather than throwing an exception. &lt;/p&gt;&lt;h4&gt;Automatic Index Allocation&lt;/h4&gt;&lt;p&gt;As children are added to a GridLayout, it maintains a cursor position and a “high-water mark” that it uses to place widgets in cells that don’t yet have anything in them. &lt;/p&gt;&lt;a href="http://4.bp.blogspot.com/-nQwSciBv9fw/TrxWZ_T6YRI/AAAAAAAAA5w/mZW4egdPJv4/s1600/milne-3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-nQwSciBv9fw/TrxWZ_T6YRI/AAAAAAAAA5w/mZW4egdPJv4/s400/milne-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5673504635071652114" /&gt;&lt;/a&gt;&lt;p&gt;When GridLayout’s &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:orientation"&gt;orientation&lt;/a&gt; property is &lt;code&gt;horizontal&lt;/code&gt; and a &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:columnCount"&gt;columnCoun&lt;/a&gt;t has been set (to 8 in this example) the high-water mark (shown above in &lt;span style="color: red;"&gt;red&lt;/span&gt;) is maintained as a separate height value for each column. When indices need to be created, GridLayout first determines the size of the cell group (by looking at the &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.LayoutParams.html#attr_android:layout_rowSpan"&gt;rowSpan&lt;/a&gt; and &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.LayoutParams.html#attr_android:layout_columnSpan"&gt;columnSpan&lt;/a&gt; parameters of the new widget) and then, starting at the cursor, goes through the available locations from: left to right, top to bottom, so as to find the row and column indices of the first location that’s free. &lt;/p&gt;&lt;p&gt;When GridLayout’s orientation is &lt;code&gt;vertical&lt;/code&gt;, all of the same principles apply, except that the roles of the horizontal and vertical axes are exchanged. &lt;/p&gt;&lt;p&gt;If you want multiple views to be placed in the same cell, you have to define the indices explicitly, as the default allocation procedure above is designed to place widgets in separate cells. &lt;/p&gt;&lt;h3&gt;Sizes, Margins and Alignment/Gravity &lt;/h3&gt;&lt;p&gt;In GridLayout, specifying sizes and margins is done just as with a LinearLayout. Alignment/gravity also works just like gravity in LinearLayout and uses the same constants: &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#LEFT"&gt;left&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#TOP"&gt;top&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#RIGHT"&gt;right&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#BOTTOM"&gt;bottom&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#CENTER_HORIZONTAL"&gt;center_horizontal&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#CENTER_VERTICAL"&gt;center_vertical&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#CENTER"&gt;center&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#FILL_HORIZONTAL"&gt;fill_horizontal&lt;/a&gt;, &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#FILL_VERTICAL"&gt;fill_vertical&lt;/a&gt; and &lt;a href="http://developer.android.com/reference/android/view/Gravity.html#FILL"&gt;fill&lt;/a&gt;. &lt;/p&gt;&lt;h3&gt;Flexibility&lt;/h3&gt;&lt;p&gt;Unlike most grids in other toolkits, GridLayout does not associate data with rows or columns. Instead, everything to do with alignment and flexibility is associated with the components themselves. GridLayout departs from the norm here to provide a more general system that allows subtle relationships between ancestors in deeply nested layouts to be accommodated in a single layout configuration. &lt;/p&gt;&lt;p&gt;The flexibility of columns is inferred from the gravity of the components inside the column. If every component defines a gravity, the column is taken as flexible, otherwise the column is considered inflexible. Full details are in GridLayout’s &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.html"&gt;API docs&lt;/a&gt;. &lt;/p&gt;&lt;h3&gt;Emulating Features from other Layouts&lt;/h3&gt;&lt;p&gt;GridLayout does not incorporate all of the features of every layout in the Android platform but it has a rich enough feature set that idiomatic use of other layouts can normally be emulated from inside a single GridLayout. &lt;/p&gt;&lt;p&gt;Although &lt;a href="http://developer.android.com/reference/android/widget/LinearLayout.html"&gt;LinearLayout&lt;/a&gt; can be considered a special case of a GridLayout, for the degenerate case when a set of views are aligned in a single row or column, LinearLayout is the better choice when this is all that is required as it clarifies the purpose of the container and may have some (relatively small) performance advantages. &lt;/p&gt;&lt;p&gt;&lt;a href="http://developer.android.com/reference/android/widget/TableLayout.html"&gt;TableLayout&lt;/a&gt; configurations are normally straightforward to accommodate, as GridLayout supports both row and column spanning. &lt;a href="http://developer.android.com/reference/android/widget/TableRow.html"&gt;TableRows&lt;/a&gt; can be removed, as they are not required by GridLayout. For the same UI, a GridLayout will generally be faster and take less memory than than a TableLayout. &lt;/p&gt;&lt;p&gt;Simple &lt;a href="http://developer.android.com/reference/android/widget/RelativeLayout.html"&gt;RelativeLayout&lt;/a&gt; configurations can be written as grids simply by grouping the views that are related to each other into rows and columns. Unlike conventional grids, GridLayout uses a constraints solver to do the heavy lifting of the layout operation. By using GridLayout’s  &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:rowOrderPreserved"&gt;rowOrderPreserved&lt;/a&gt; and &lt;a href="http://developer.android.com/reference/android/widget/GridLayout.html#attr_android:columnOrderPreserved"&gt;columnOrderPreserved&lt;/a&gt; properties it’s possible to free GridLayout from the confines of traditional grid systems and support the majority of RelativeLayout configurations — even ones that require grid lines to pass over each other as children change size.  &lt;/p&gt;&lt;p&gt;Simple &lt;a href="http://developer.android.com/reference/android/widget/FrameLayout.html"&gt;FrameLayout&lt;/a&gt; configurations can be accommodated within the cells of a GridLayout because a single cell can contain multiple views. To switch between two views, place them both in the same cell and use the visibility constant &lt;a href="http://developer.android.com/reference/android/view/View.html#GONE"&gt;GONE&lt;/a&gt; to switch from one to the other from code. As with the LinearLayout case above, if all you need is the functionality described above, FrameLayout is the better choice and may have some small performance advantages. &lt;/p&gt;&lt;p&gt;One key feature that GridLayout lacks is the ability to distribute excess space between rows or columns in specified proportions — a feature that LinearLayout provides by supporting the principle of &lt;a href="http://developer.android.com/reference/android/widget/LinearLayout.LayoutParams.html#attr_android:layout_weight"&gt;weight&lt;/a&gt;. This omission and possible ways around it are discussed in GridLayout’s API docs. &lt;/p&gt;&lt;h3&gt;The Phases of the Layout Operation&lt;/h3&gt;&lt;p&gt;It’s useful to distinguish the allocation phase for cell indices discussed above from the layout operation itself. Normally the phase that allocates indices happens once, if at all, when a UI is initialized. The index-allocation phase only applies when indices have been left unspecified, and is responsible for ensuring that all views have a defined set of cells in which they are to be placed at layout time. &lt;/p&gt;&lt;p&gt;The layout operation happens after this and is recalculated each time a view changes size. GridLayout measures the size of each child during the layout operation so it can calcuate the heights and widths of the rows and columns in the grid. The layout phase completes by using gravity to place each of the components in its cell. &lt;/p&gt;&lt;p&gt;Although index allocation normally only happens once, GridLayout is technically a dynamic layout, meaning that if you change its orientation property or add or remove children after components have been laid out, GridLayout will repeat the above procedure to reallocate indices in a way that is right for the new configuration. &lt;/p&gt;&lt;p&gt;From a performance standpoint, it is worth knowing that the GridLayout implementation has been optimized for the common case, when initialization happens once and layout happens frequently. As a result, the initialization step sets up internal data structures so that the layout operation can complete quickly and without allocating memory. Put another way, changes either to GridLayout’s orientation or the number of children it has are much more expensive than an ordinary layout operation. &lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;GridLayout’s feature set incorporates much of the functionality of the Android framework’s existing general-purpose layouts: LinearLayout, FrameLayout, TableLayout and RelativeLayout. As such, it provides a way to replace many deeply nested view hierarchies with a single highly optimized layout implementation. &lt;/p&gt;&lt;p&gt;If you are starting a UI from scratch and are not familiar with Android layouts, use a GridLayout — it supports most of the features of the other layouts and has a simpler and more general API than either TableLayout or RelativeLayout. &lt;/p&gt;&lt;p&gt;We anticipate that the combination of FrameLayout, LinearLayout and GridLayout together will provide a feature set that’s rich enough to allow most layout problems to be solved without writing layout code by hand. It’s worth spending some time deciding which of these layouts is right for the top of your tree; a good choice will minimize the need for intermediate containers and result in a user interface that is faster and uses less memory. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8379178536336854115?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=UIW08ORGX6E:mtYcjAcOjV8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=UIW08ORGX6E:mtYcjAcOjV8:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=UIW08ORGX6E:mtYcjAcOjV8:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/UIW08ORGX6E" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/8379178536336854115?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/8379178536336854115?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/UIW08ORGX6E/new-layout-widgets-space-and-gridlayout.html" title="New Layout Widgets: Space and GridLayout" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-v5fdrXd7GNA/TrxWJ35If7I/AAAAAAAAA5Y/4wofsXZwmKs/s72-c/milne-1.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/11/new-layout-widgets-space-and-gridlayout.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUINRHo_fSp7ImA9WhRTF0o.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-6428902022448054162</id><published>2011-11-08T10:36:00.000-08:00</published><updated>2011-11-08T10:39:55.445-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-08T10:39:55.445-08:00</app:edited><title>More Android Developer Labs in Asia</title><content type="html">&lt;p&gt;A couple of months ago, we kicked off a series of Android Developer Labs in &lt;a href="http://android-developers.blogspot.com/2011/08/android-developer-labs-2011.html"&gt;Asia, North America and Europe&lt;/a&gt;.  To wrap up the 2011 series, we now have &lt;a href="https://sites.google.com/site/androiddevlabs2011/apac-android-developer-lab"&gt;opened registration&lt;/a&gt; for 2 more locations in Asia.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Taipei — December 2, 2011&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Hong Kong — December 6, 2011&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Remember, this ADL series isn’t another set of introduction-to-Android sessions, nor any other kind of general overview. It's specifically aimed at optimizing Android apps for tablets, in particular creating high-quality tablet apps with an emphasis on polish and user experience.&lt;/p&gt;&lt;p&gt;Registration is a two-step process. Anyone can register, but we can only accommodate a relatively small number of attendees from among the registrants, based on whether they already have an Android app with the potential to be a top-tier tablet app in terms of quality, fit, and finish. The goal is to bring your app to the ADL, and leave equipped to make it into one that makes Android tablet users smile.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6428902022448054162?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=iygJX_V7Po0:WOzP007ammU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=iygJX_V7Po0:WOzP007ammU:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=iygJX_V7Po0:WOzP007ammU:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/iygJX_V7Po0" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/6428902022448054162?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/6428902022448054162?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/iygJX_V7Po0/more-android-developer-labs-in-asia.html" title="More Android Developer Labs in Asia" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><feedburner:origLink>http://android-developers.blogspot.com/2011/11/more-android-developer-labs-in-asia.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4NQHg9eyp7ImA9WhRTE08.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-4948819655425709769</id><published>2011-11-03T07:00:00.000-07:00</published><updated>2011-11-03T07:03:11.663-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T07:03:11.663-07:00</app:edited><title>JNI Local Reference Changes in ICS</title><content type="html">&lt;p&gt;&lt;i&gt;[This post is by Elliott Hughes, a Software Engineer on the Dalvik team.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;If you don’t write native code that uses JNI, you can stop reading now. If you do write native code that uses JNI, you really need to read this.&lt;/p&gt;&lt;h3&gt;What’s changing, and why?&lt;/h3&gt;&lt;p&gt;Every developer wants a good &lt;a href="http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)"&gt;garbage collector&lt;/a&gt;. The best garbage collectors move objects around. This lets them offer very cheap allocation and bulk deallocation, avoids heap fragmentation, and may improve locality. Moving objects around is a problem if you’ve handed out pointers to them to native code. JNI uses types such as &lt;code&gt;jobject&lt;/code&gt; to solve this problem: rather than handing out direct pointers, you’re given an opaque handle that can be traded in for a pointer when necessary. By using handles, when the garbage collector moves an object, it just has to update the handle table to point to the object’s new location. This means that native code won’t be left holding dangling pointers every time the garbage collector runs.&lt;/p&gt;&lt;p&gt;In previous releases of Android, we didn’t use indirect handles; we used direct pointers. This didn’t seem like a problem as long as we didn’t have a garbage collector that moves objects, but it let you write buggy code that still seemed to work. In Ice Cream Sandwich, even though we haven't yet implemented such a garbage collector, we've moved to indirect references so you can start detecting bugs in your native code.&lt;/p&gt;&lt;p&gt;Ice Cream Sandwich features a JNI bug compatibility mode so that as long as your AndroidManifest.xml’s targetSdkVersion is less than Ice Cream Sandwich, your code is exempt. But as soon as you update your targetSdkVersion, your code needs to be correct.&lt;/p&gt;&lt;p&gt;&lt;a href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html"&gt;CheckJNI&lt;/a&gt; has been updated to detect and report these errors, and in Ice Cream Sandwich, CheckJNI is on by default if &lt;code&gt;debuggable="true"&lt;/code&gt; in your manifest.&lt;/p&gt;&lt;h3&gt;A quick primer on JNI references&lt;/h3&gt;&lt;p&gt;In JNI, there are several kinds of reference. The two most important kinds are local references and global references. Any given &lt;code&gt;jobject&lt;/code&gt; can be either local or global. (There are weak globals too, but they have a separate type, &lt;code&gt;jweak&lt;/code&gt;, and aren’t interesting here.)&lt;/p&gt;&lt;p&gt;The global/local distinction affects both lifetime and scope. A global is usable from any thread, using that thread’s &lt;code&gt;JNIEnv*&lt;/code&gt;, and is valid until an explicit call to &lt;code&gt;DeleteGlobalRef()&lt;/code&gt;. A local is only usable from the thread it was originally handed to, and is valid until either an explicit call to &lt;code&gt;DeleteLocalRef()&lt;/code&gt; or, more commonly, until you return from your native method. When a native method returns, all local references are automatically deleted.&lt;/p&gt;&lt;p&gt;In the old system, where local references were direct pointers, local references were never really invalidated. That meant you could use a local reference indefinitely, even if you’d explicitly called &lt;code&gt;DeleteLocalRef()&lt;/code&gt; on it, or implicitly deleted it with &lt;code&gt;PopLocalFrame()&lt;/code&gt;!&lt;/p&gt;&lt;p&gt;Although any given &lt;code&gt;JNIEnv*&lt;/code&gt; is only valid for use on one thread, because Android never had any per-thread state in a &lt;code&gt;JNIEnv*&lt;/code&gt;, it used to be possible to get away with using a &lt;code&gt;JNIEnv*&lt;/code&gt; on the wrong thread. Now there’s a per-thread local reference table, it’s vital that you only use a &lt;code&gt;JNIEnv*&lt;/code&gt; on the right thread.&lt;/p&gt;&lt;p&gt;Those are the bugs that ICS will detect. I’ll go through a few common cases to illustrate these problems, how to spot them, and how to fix them. It’s important that you do fix them, because it’s likely that future Android releases will utilize moving collectors. It will not be possible to offer a bug-compatibility mode indefinitely.&lt;/p&gt;&lt;h3&gt;Common JNI reference bugs&lt;/h3&gt;&lt;h4&gt;Bug: Forgetting to call &lt;code&gt;NewGlobalRef()&lt;/code&gt; when stashing a &lt;code&gt;jobject&lt;/code&gt; in a native peer&lt;/h4&gt;&lt;p&gt;If you have a native peer (a long-lived native object corresponding to a Java object, usually created when the Java object is created and destroyed when the Java object’s finalizer runs), you must not stash a &lt;code&gt;jobject&lt;/code&gt; in that native object, because it won’t be valid next time you try to use it. (Similar is true of &lt;code&gt;JNIEnv*&lt;/code&gt;s. They &lt;em&gt;might&lt;/em&gt; be valid if the next native call happens on the same thread, but they won’t be valid otherwise.)&lt;/p&gt;&lt;pre&gt;&lt;code&gt; class MyPeer {
 public:
   MyPeer(jstring s) {
     str_ = s; // Error: stashing a reference without ensuring it’s global.
   }
   jstring str_;
 };

 static jlong MyClass_newPeer(JNIEnv* env, jclass) {
   jstring local_ref = env-&gt;NewStringUTF("hello, world!");
   MyPeer* peer = new MyPeer(local_ref);
   return static_cast&amp;lt;jlong&gt;(reinterpret_cast&amp;lt;uintptr_t&gt;(peer));
   &lt;span style="color: red;"&gt;// Error: local_ref is no longer valid when we return, but we've stored it in 'peer'.&lt;/span&gt;
 }

 static void MyClass_printString(JNIEnv* env, jclass, jlong peerAddress) {
   MyPeer* peer = reinterpret_cast&amp;lt;MyPeer*&gt;(static_cast&amp;lt;uintptr_t&gt;(peerAddress));
   // Error: peer-&gt;str_ is invalid!
   ScopedUtfChars s(env, peer-&gt;str_);
   std::cout &amp;lt;&amp;lt; s.c_str() &amp;lt;&amp;lt; std::endl;
 }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The fix for this is to only store JNI global references. Because there’s never any automatic cleanup of JNI global references, it’s critically important that you clean them up yourself. This is made slightly awkward by the fact that your destructor won’t have a &lt;code&gt;JNIEnv*&lt;/code&gt;. The easiest fix is usually to have an explicit ‘destroy‘ function for your native peer, called from the Java peer’s finalizer:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; class MyPeer {
 public:
   MyPeer(JNIEnv* env, jstring s) {
     this-&gt;s = env-&gt;NewGlobalRef(s);
   }
   ~MyPeer() {
     assert(s == NULL);
   }
   void destroy(JNIEnv* env) {
     env-&gt;DeleteGlobalRef(s);
     s = NULL;
   }
   jstring s;
 };&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should always have matching calls to &lt;code&gt;NewGlobalRef()&lt;/code&gt;/&lt;code&gt;DeleteGlobalRef()&lt;/code&gt;. CheckJNI will catch global reference leaks, but the limit is quite high (2000 by default), so watch out.&lt;/p&gt;&lt;p&gt;If you do have this class of error in your code, the crash will look something like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;    JNI ERROR (app bug): accessed stale local reference 0x5900021 (index 8 in a table of size 8)
    JNI WARNING: jstring is an invalid local reference (0x5900021)
                 in LMyClass;.printString:(J)V (GetStringUTFChars)
    "main" prio=5 tid=1 RUNNABLE
      | group="main" sCount=0 dsCount=0 obj=0xf5e96410 self=0x8215888
      | sysTid=11044 nice=0 sched=0/0 cgrp=[n/a] handle=-152574256
      | schedstat=( 156038824 600810 47 ) utm=14 stm=2 core=0
      at MyClass.printString(Native Method)
      at MyClass.main(MyClass.java:13)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you’re using another thread’s &lt;code&gt;JNIEnv*&lt;/code&gt;, the crash will look something like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; JNI WARNING: threadid=8 using env from threadid=1
                 in LMyClass;.printString:(J)V (GetStringUTFChars)
    "Thread-10" prio=5 tid=8 NATIVE
      | group="main" sCount=0 dsCount=0 obj=0xf5f77d60 self=0x9f8f248
      | sysTid=22299 nice=0 sched=0/0 cgrp=[n/a] handle=-256476304
      | schedstat=( 153358572 709218 48 ) utm=12 stm=4 core=8
      at MyClass.printString(Native Method)
      at MyClass$1.run(MyClass.java:15)&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Bug: Mistakenly assuming &lt;code&gt;FindClass()&lt;/code&gt; returns global references&lt;/h4&gt;&lt;p&gt;&lt;code&gt;FindClass()&lt;/code&gt; returns local references. Many people assume otherwise. In a system without class unloading (like Android), you can treat jfieldID and jmethodID as if they were global. (They’re not actually references, but in a system with class unloading there are similar lifetime issues.) But jclass is a reference, and &lt;code&gt;FindClass()&lt;/code&gt; returns local references. A common bug pattern is “static jclass”. Unless you’re manually turning your local references into global references, your code is broken. Here’s what correct code should look like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; static jclass gMyClass;
 static jclass gSomeClass;

 static void MyClass_nativeInit(JNIEnv* env, jclass myClass) {
   // ‘myClass’ (and any other non-primitive arguments) are only local references.
   gMyClass = env-&gt;NewGlobalRef(myClass);

   // FindClass only returns local references.
   jclass someClass = env-&gt;FindClass("SomeClass");
   if (someClass == NULL) {
     return; // FindClass already threw an exception such as NoClassDefFoundError.
   }
   gSomeClass = env-&gt;NewGlobalRef(someClass);
 }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you do have this class of error in your code, the crash will look something like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;    JNI ERROR (app bug): attempt to use stale local reference 0x4200001d (should be 0x4210001d)
    JNI WARNING: 0x4200001d is not a valid JNI reference
                 in LMyClass;.useStashedClass:()V (IsSameObject)&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Bug: Calling &lt;code&gt;DeleteLocalRef()&lt;/code&gt; and continuing to use the deleted reference&lt;/h4&gt;&lt;p&gt;It shouldn’t need to be said that it’s illegal to continue to use a reference after calling &lt;code&gt;DeleteLocalRef()&lt;/code&gt; on it, but because it used to work, so you may have made this mistake and not realized. The usual pattern seems to be where native code has a long-running loop, and developers try to clean up every single local reference as they go to avoid hitting the local reference limit, but they accidentally also delete the reference they want to use as a return value!&lt;/p&gt;&lt;p&gt;The fix is trivial: don’t call &lt;code&gt;DeleteLocalRef()&lt;/code&gt; on a reference you’re going to use (where “use” includes “return”).&lt;/p&gt;&lt;h4&gt;Bug: Calling &lt;code&gt;PopLocalFrame()&lt;/code&gt; and continuing to use a popped reference&lt;/h4&gt;&lt;p&gt;This is a more subtle variant of the previous bug. The &lt;code&gt;PushLocalFrame()&lt;/code&gt; and &lt;code&gt;PopLocalFrame()&lt;/code&gt; calls let you bulk-delete local references. When you call &lt;code&gt;PopLocalFrame()&lt;/code&gt;, you pass in the one reference from the frame that you’d like to keep (typically for use as a return value), or NULL. In the past, you’d get away with incorrect code like the following:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; static jobjectArray MyClass_returnArray(JNIEnv* env, jclass) {
   env-&gt;PushLocalFrame(256);
   jobjectArray array = env-&gt;NewObjectArray(128, gMyClass, NULL);
   for (int i = 0; i &amp;lt; 128; ++i) {
       env-&gt;SetObjectArrayElement(array, i, newMyClass(i));
   }
   env-&gt;PopLocalFrame(NULL); &lt;span style="color: red;"&gt;// Error: should pass 'array'.&lt;/span&gt;
   return array; &lt;span style="color: red;"&gt;// Error: array is no longer valid.&lt;/span&gt;
 }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The fix is generally to pass the reference to &lt;code&gt;PopLocalFrame()&lt;/code&gt;. Note in the above example that you don’t need to keep references to the individual array elements; as long as the GC knows about the array itself, it’ll take care of the elements (and any objects they point to in turn) itself.&lt;/p&gt;&lt;p&gt;If you do have this class of error in your code, the crash will look something like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  JNI ERROR (app bug): accessed stale local reference 0x2d00025 (index 9 in a table of size 8)
    JNI WARNING: invalid reference returned from native code
                 in LMyClass;.returnArray:()[Ljava/lang/Object;&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Wrapping up&lt;/h3&gt;&lt;p&gt;Yes, we asking for a bit more attention to detail in your JNI coding, which is extra work.  But we think that you’ll come out ahead on the deal as we roll in better and more sophisticated memory management code.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-4948819655425709769?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=3rY3H2xzEe0:b9zkPVmN2NQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=3rY3H2xzEe0:b9zkPVmN2NQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=3rY3H2xzEe0:b9zkPVmN2NQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/3rY3H2xzEe0" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/4948819655425709769?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/4948819655425709769?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/3rY3H2xzEe0/jni-local-reference-changes-in-ics.html" title="JNI Local Reference Changes in ICS" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><feedburner:origLink>http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04HRX0-fip7ImA9WhRTEUU.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-8414461099127805380</id><published>2011-11-01T07:00:00.000-07:00</published><updated>2011-11-01T16:25:34.356-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-01T16:25:34.356-07:00</app:edited><title>Android 4.0 Graphics and Animations</title><content type="html">&lt;p&gt;&lt;i&gt;[This post is by Romain Guy and Chet Haase, Android engineers who have been known to &lt;a href="http://filthyrichclients.org"&gt;collaborate&lt;/a&gt; on the subject of graphics, UIs, and animation. You can read more from them on their blogs at &lt;a href="http://curious-creature.org"&gt;curious-creature.org&lt;/a&gt; and &lt;a href="http://graphics-geek.blogspot.com"&gt;graphics-geek.blogspot.com&lt;/a&gt;.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Earlier this year, &lt;a href="http://android-developers.blogspot.com/2011/03/android-30-hardware-acceleration.html "&gt;Android 3.0 launched&lt;/a&gt; with a new 2D rendering pipeline designed to support hardware acceleration on tablets. With this new pipeline, all drawing operations performed by the UI toolkit are carried out using the GPU.&lt;/p&gt;&lt;p&gt;You’ll be happy to hear that Android 4.0, Ice Cream Sandwich, brings an improved version of the hardware-accelerated 2D rendering pipeline to phones, starting with &lt;a href="http://www.google.com/nexus"&gt;Galaxy Nexus&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Enabling hardware acceleration&lt;/h3&gt;&lt;p&gt;In Android 4.0 (API level 14), hardware acceleration, for the first time, is on by default for all applications. For applications at lower API levels, you can turn it on by adding &lt;code&gt;android:hardwareAccelerated="true"&lt;/code&gt; to the &lt;code&gt;&amp;lt;application&gt;&lt;/code&gt; tag in your AndroidManifest.xml.&lt;/p&gt;&lt;p&gt;To learn more about the hardware accelerated 2D rendering pipeline visit the official &lt;a href="http://developer.android.com/guide/topics/graphics/hardware-accel.html"&gt;Android developer guide&lt;/a&gt;. This guide explains how to control hardware acceleration at various levels, offers several performance tips and tricks and describes in details the new drawing model.&lt;/p&gt;&lt;p&gt;I also encourage you to watch the &lt;a href="http://www.youtube.com/watch?v=v9S5EO7CLjo"&gt;Android Hardware Accelerated Rendering&lt;/a&gt; talk that we gave at Google I/O 2011.&lt;/p&gt;&lt;h3&gt;Introducing TextureView&lt;/h3&gt;&lt;p&gt;Applications that need to display OpenGL or video content rely today on a special type of UI element called &lt;a href="http://developer.android.com/reference/android/view/SurfaceView.html"&gt;SurfaceView&lt;/a&gt;. This widget works by creating a new window placed behind your application’s window. It then punches a hole through your application’s window to reveal the new window. While this approach is very efficient, since the content of the new window can be refreshed without redrawing the application’s window, it suffers from several important limitations.&lt;/p&gt;&lt;p&gt;Because a SurfaceView’s content does not live in the application’s window, it cannot be transformed (moved, scaled, rotated) efficiently. This makes it difficult to use a SurfaceView inside a ListView or a ScrollView. SurfaceView also cannot interact properly with some features of the UI toolkit such as fading edges or &lt;code&gt;View.setAlpha()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;To solve these problems, Android 4.0 introduces a new widget called &lt;a href="http://developer.android.com/reference/android/view/TextureView.html"&gt;TextureView&lt;/a&gt; that relies on the hardware accelerated 2D rendering pipeline and &lt;a href="http://developer.android.com/reference/android/graphics/SurfaceTexture.html"&gt;SurfaceTexture&lt;/a&gt;. TextureView offers the same capabilities as SurfaceView but, unlike SurfaceView, behaves as a regular view. You can for instance use a TextureView to display an OpenGL scene or a video stream. The TextureView itself can be animated, scrolled, etc.&lt;/p&gt;&lt;p&gt;The following piece of code creates a TextureView to display the video preview from the default camera. The TextureView itself is rotated 45 degrees and semi-transparent.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;public class TextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
    private Camera mCamera;
    private TextureView mTextureView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mTextureView = new TextureView(this);
        mTextureView.setSurfaceTextureListener(this);

        setContentView(mTextureView);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mCamera = Camera.open();

        Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
        mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
                previewSize.width, previewSize.height, Gravity.CENTER));

        try {
            mCamera.setPreviewTexture(surface);
        } catch (IOException t) {
        }

        mCamera.startPreview();
        
        mTextureView.setAlpha(0.5f);
        mTextureView.setRotation(45.0f);
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // Ignored, the Camera does all the work for us
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mCamera.stopPreview();
        mCamera.release();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // Called whenever a new frame is available and displayed in the TextureView
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A TextureView can just as easily be used to embed an OpenGL scene in your application. As of Android 4.0, &lt;a href="http://developer.android.com/reference/javax/microedition/khronos/egl/EGL10.html#eglCreateWindowSurface(javax.microedition.khronos.egl.EGLDisplay,%20javax.microedition.khronos.egl.EGLConfig,%20java.lang.Object,%20int[])"&gt;eglCreateWindowSurface()&lt;/a&gt; can be used to render into a SurfaceTexture object.&lt;/p&gt;&lt;h3&gt;Animation&lt;/h3&gt;&lt;p&gt;There were minor improvements in Android 4.0 to some of the new animation facilities that were added in the 3.x releases.&lt;/p&gt;&lt;p&gt;First, if you're new to the new android.animation package and classes added in 3.0 and 3.1, you might want to read &lt;a href="http://android-developers.blogspot.com/2011/02/animation-in-honeycomb.html"&gt;Animation in Honeycomb&lt;/a&gt; and &lt;a href="http://graphics-geek.blogspot.com/2011/06/introducing-viewpropertyanimator.html"&gt;Introducing ViewPropertyAnimator&lt;/a&gt;. These articles discuss the new APIs added in 3.0 that make animation in Android easier, more powerful, and more flexible. The Android 4.0 improvements discussed below are small additions to these core facilities.&lt;/p&gt;&lt;h3&gt;Properties&lt;/h3&gt;&lt;p&gt;One of the constraints of the Java programming language is the lack of “properties”. There is no way to refer generically to a field or a setter/getter of an object. As long as you know what kind of object you have, this is not a problem, because you then know the set of fields and methods that you can call. But if someone passes you some subclass of Object and you'd like to get or set some value  “foo” on it, you're out of luck. You can use reflection or JNI to get access to the foo field/methods, but there is no way to refer directly to a field or a method unless you know the instance type of the object that has that field/method on it.&lt;/p&gt;&lt;p&gt;This is a constraint that the new animation system works within. Its whole job, you might say, is to get and set values on generic objects that it's been told about. If someone wants to animate the alpha property on a View, they tell the system the target object and the name of that field (“alpha”), and the animation system uses JNI to figure out which method(s) act on a field of that name. Basically, it looks for &lt;code&gt;setAlpha()&lt;/code&gt; and, sometimes, &lt;code&gt;getAlpha()&lt;/code&gt; methods. Then when an animation frame occurs, it calculates the new value and passes it into the setter method that it found.&lt;/p&gt;&lt;p&gt;This seems like a lot of work for what it does, but there's really no way around it. Unless the animation system were specific to View objects, there's no way that it could know that the target object has appropriate setter/getter methods. And even if it did, there's still no way for callers that construct the animations to tell the animator about the property named  “alpha”; there are no function handles like there are in other languages, and there's no way to reference a public field either. (I'm ignoring Reflection here, which has Method and Field objects, because this approach requires much more overhead and processing than the simple function/field references of other languages).&lt;/p&gt;&lt;p&gt;If only there were a way to refer to these properties and to get/set them on generic objects...&lt;/p&gt;&lt;p&gt;Now there is. There is a new Property object in the android.util package that does exactly this. This class offers a &lt;code&gt;set()&lt;/code&gt; and a &lt;code&gt;get()&lt;/code&gt; method. So if someone hands you a Property object, you can safely call the &lt;code&gt;set()&lt;/code&gt; and &lt;code&gt;get()&lt;/code&gt; methods without knowing anything about the target object and it will do the job. Moreover, it will do it much more efficiently than the current JNI or reflection approaches because it can, depending on the implementation of it, set a field or call a method on the target object directly. For example, the new ALPHA property on View calls setAlpha() on the View object.&lt;/p&gt;&lt;p&gt;The Property class is a generic utility that can be used anywhere, not just in animations. But it's animations that benefit enormously from it, in their ability to handle properties in a type-safe and efficient manner.&lt;/p&gt;&lt;p&gt;For example prior to Android 4.0, you might construct a fade-out animation on some object myView like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "alpha", 0);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In Android 4.0, you can use the new ALPHA object on View to construct a Property-based animator instead:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;ObjectAnimator anim = ObjectAnimator.ofFloat(myView, View.ALPHA, 0);&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;ViewPropertyAnimator Additions&lt;/h3&gt;&lt;p&gt;There were minor API additions to the ViewPropertyAnimator class (introduced in Android 3.1) which make this class more flexible and powerful:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;cancel()&lt;/code&gt;: You can now cancel() a running ViewPropertyAnimator.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;setStartDelay()&lt;/code&gt;: You can now set a startDelay on the ViewPropertyAnimator, just like the startDelay of the other Animator classes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;start()&lt;/code&gt;: ViewPropertyAnimators start automatically, but they do so on the next animation frame handled. This allows them to collect several requests and bundle them together, which is much more efficient and makes it easier to synchronize multiple animations together. However, if you just want to run a single animation, or want to make sure it starts immediately, at the time of construction, you can call &lt;code&gt;start()&lt;/code&gt; to avoid that intervening delay.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;LayoutTransition&lt;/h3&gt;&lt;p&gt;LayoutTransition (introduced in Android 3.0) continues to provide functionality that makes some kinds of animations easier, specifically when adding, removing, hiding, and showing views. For example, either this snippet in a layout file:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:id="@+id/container"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or this code added at runtime:&lt;/p&gt;&lt;pre&gt;&lt;code&gt; container.setLayoutTransition(new LayoutTransition());&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;will result in a container that animates the visibility of its children views. So when a view is added to the container, the other children will animate out of the way and then the new one will fade in. Similarly, removing a child from the container will fade it out and then animate the other children around to their final places and sizes.&lt;/p&gt;&lt;p&gt;You can customize the animations and timing behavior of a LayoutTransition object, but the code above allows a very easy way to get reasonable default animation behavior.&lt;/p&gt;&lt;p&gt;One of the constraints in the pre-4.0 version of the class was that it did not account for changes in the bounds of the parent hierarchy. So, for example, if a LinearLayout with horizontal orientation has a layout_width of wrap_content and you want to run a transition that removes an item from that layout, then you might notice the parent snapping to the end size and clipping its children instead of animating all of them into their new positions. The new approach (enabled by default, but disabled by a call to &lt;code&gt;setAnimateParentHierarchy(false))&lt;/code&gt; also animates the layout bounds and scrolling values of the parent layout and its parents, all the way up the view hierarchy. This allows LayoutTransition to account for all layout-related changes due to that view being added or removed from its transitioning container.&lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;The Android 3.0 release saw huge improvements in the visual capabilities of the platform, as we started enabling hardware acceleration and providing new, more flexible animation capabilities. Android 4.0 continues this trend as we continue to work hard on improving the performance, features, and usability of the Android APIs. We’re not done yet, but the enhancements in this release should help you create more exciting Android experiences and applications.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8414461099127805380?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=jD6pgvUvDqE:bKex2kH3E3U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=jD6pgvUvDqE:bKex2kH3E3U:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=jD6pgvUvDqE:bKex2kH3E3U:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/jD6pgvUvDqE" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/8414461099127805380?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/8414461099127805380?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/jD6pgvUvDqE/android-40-graphics-and-animations.html" title="Android 4.0 Graphics and Animations" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><feedburner:origLink>http://android-developers.blogspot.com/2011/11/android-40-graphics-and-animations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MER3k7cCp7ImA9WhdaFkg.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-6569655635880991626</id><published>2011-10-26T12:46:00.000-07:00</published><updated>2011-10-26T13:03:26.708-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-26T13:03:26.708-07:00</app:edited><title>Introducing Android WebDriver</title><content type="html">&lt;a href="http://4.bp.blogspot.com/-1xbHAI0ZXm8/Tqhm98ZSBgI/AAAAAAAAAt0/P0yGyM_ZIys/s1600/dounia.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 213px; height: 320px;" src="http://4.bp.blogspot.com/-1xbHAI0ZXm8/Tqhm98ZSBgI/AAAAAAAAAt0/P0yGyM_ZIys/s320/dounia.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5667893345415988738" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by Dounia Berrada, an engineer on the EngTools team.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Selenium WebDriver is a browser automation tool which provides a lightweight and elegant way for testing web apps. Selenium WebDriver is now available as an SDK extra in the Android SDK, and supports 2.3 (Gingerbread) and onwards!&lt;/p&gt;&lt;p&gt;Whether or not your site is optimized for mobile browsers, you can be sure that users will be accessing it from their phones and tablets. WebDriver makes it easy to write automated tests that ensure your site works correctly when viewed from the Android browser. We’ll walk you through some basics about WebDriver and look at it in action.&lt;/p&gt;&lt;h3&gt;WebDriver Basics&lt;/h3&gt;&lt;p&gt;WebDriver tests are end-to-end tests that exercise the web application just like a real user would. WebDriver models user interactions with a web page such as finger flicks, finger scrolls and long presses. It can rotate the display and interact with HTML5 features such as local storage, session storage and the application cache. Those tests run as part of an &lt;a href="http://developer.android.com/guide/topics/testing/testing_android.html"&gt;Android tests project&lt;/a&gt; and are based on Junit. They can be &lt;a href="http://developer.android.com/resources/tutorials/testing/helloandroid_test.html"&gt;launched from Eclipse&lt;/a&gt; or the command line. WebDriver tests can be wired with a continuous integration system and can run on phone and tablet emulators or real devices. Once the test starts, WebDriver opens a WebView configured like the Android browser and runs the tests against it. &lt;/p&gt;&lt;p&gt;WebDriver is an Android SDK extra and can be installed following &lt;a href="http://code.google.com/p/selenium/wiki/AndroidDriver?ts=1318649352&amp;amp;updated=AndroidDriver#Using_the_Android_Test_Framework"&gt;these instructions&lt;/a&gt;. Once you’ve done that you’ll be ready to write tests! There is a comprehensive WebDriver &lt;a href="http://seleniumhq.org/docs/03_webdriver.html"&gt;user guide&lt;/a&gt; on the Selenium site, but let’s start with a basic example using &lt;a href="http://www.google.com/"&gt;www.google.com&lt;/a&gt; to give you a taste of what’s possible.&lt;/p&gt;&lt;h3&gt;Getting Started&lt;/h3&gt;&lt;p&gt;First, create an Android project containing an empty activity with no layout.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;public class SimpleAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then create the Android test project that will contain the tests. WebDriver will create the WebView and set the layout automatically in the main Activity.&lt;/p&gt;&lt;p&gt;Let’s write a test that opens the Google home page on Android and issues a query for “weather in San Francisco”. The test will verify that Google returns search results, and that the first result returned is giving the weather in San Francisco.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;public class SimpleGoogleTest extends ActivityInstrumentationTestCase2&amp;lt;SimpleAppActivity&gt; {

    public void testGoogleShouldWork() {
      // Create a WebDriver instance with the activity in which we want the test to run
      WebDriver driver = new AndroidDriver(getActivity());
      // Let’s open a web page
      driver.get("http://www.google.com");

      // Lookup for the search box by its name
      WebElement searchBox = driver.findElement(By.name("q"));

      // Enter a search query and submit
      searchBox.sendKeys("weather in san francisco");
      searchBox.submit();

      // Making sure that Google shows 11 results
      WebElement resultSection = driver.findElement(By.id("ires"));
      List&amp;lt;WebElement&gt; searchResults = resultSection.findElements(By.tagName("li"));
      assertEquals(11, searchResults.size());

      // Let’s ensure that the first result shown is the weather widget
      WebElement weatherWidget = searchResults.get(0);
      assertTrue(weatherWidget.getText().contains("Weather for San Francisco, CA"));
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let’s see our test in action! WebDriver will create a WebView with the same configuration as the Android browser in the main UI thread, i.e. the activity thread. The activity will display the WebView on the screen, allowing you to see your web application as the test code is executing. &lt;/p&gt;&lt;h3&gt;Interaction Testing&lt;/h3&gt;&lt;p&gt;We’ve mentioned that WebDriver supports creating advanced gestures to interact with the device. Let’s use WebDriver to throw an image across the screen by flicking horizontally, and ensure that the next image in the gallery is displayed.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;WebElement toFlick = driver.findElement(By.id("image"));
// 400 pixels left at normal speed
Action flick = getBuilder(driver).flick(toFlick, 0, -400, FlickAction.SPEED_NORMAL)
        .build();
flick.perform();
WebElement secondImage = driver.findElement(“secondImage”);
assertTrue(secondImage.isDisplayed());&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, let’s rotate the screen and ensure that the image displayed on screen is resized.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;assertEquals(landscapeSize, secondImage.getSize())
((Rotatable) driver).rotate(ScreenOrientation.PORTRAIT);
assertEquals(portraitSize, secondImage.getSize());&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What if your test reveals a bug? You can easily take a screenshot for help in future debugging: &lt;/p&gt;&lt;pre&gt;&lt;code&gt;File tempFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Find Out More&lt;/h3&gt;&lt;p&gt;If this has whetted your appetite and you’d like to know more, go ahead and install the Android WebDriver, take a look at the documentation on the &lt;a href="http://code.google.com/p/selenium/wiki/AndroidDriver"&gt;Selenium project’s wiki&lt;/a&gt;, or just &lt;a href="http://selenium.googlecode.com/svn/trunk/docs/api/java/index.html"&gt;browse the javadocs&lt;/a&gt;. For questions and feedback not only of the Android WebDriver but also its desktop brethren, please join &lt;a href="http://groups.google.com/group/webdriver/"&gt;webdriver@googlegroups.com&lt;/a&gt;. For announcements keep an eye on &lt;a href="http://seleniumhq.wordpress.com/"&gt;http://seleniumhq.wordpress.com/&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6569655635880991626?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=qW-DHwT9R7c:GY5zSx0os6s:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=qW-DHwT9R7c:GY5zSx0os6s:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=qW-DHwT9R7c:GY5zSx0os6s:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/qW-DHwT9R7c" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/6569655635880991626?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/6569655635880991626?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/qW-DHwT9R7c/introducing-android-webdriver.html" title="Introducing Android WebDriver" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-1xbHAI0ZXm8/Tqhm98ZSBgI/AAAAAAAAAt0/P0yGyM_ZIys/s72-c/dounia.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/10/introducing-android-webdriver.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEFRXg5fSp7ImA9WhdaFUs.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-3823126010432939653</id><published>2011-10-25T11:30:00.000-07:00</published><updated>2011-10-25T11:33:34.625-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-25T11:33:34.625-07:00</app:edited><title>Changes to Library Projects in Android SDK Tools, r14</title><content type="html">&lt;p&gt;Last week, we released the SDK for Android 4.0 and a new set of developer tools, now in revision 14. The updated tools include a lot of build changes, many that improve build performance. Also included is an under-the-hood change in how libraries are used by main projects &amp;mdash; a first step in improving library support and code reusability. While the change should have little impact on existing projects, some developers have had issues when migrating to the updated tools. Please read below for more information about the change to library projects and how to solve migration issues.&lt;/p&gt;&lt;p&gt;Previously, library projects were handled as extra resource and source code folders to be used when compiling the resources and the application’s source respectively. While this worked fine for most cases, there were two issues.&lt;/p&gt;&lt;p&gt;1. Developers asked us for the ability to distribute a library as a single jar file that included both compiled code and resources. The nature of Android resources, with their compiled IDs prevented this.&lt;/p&gt;&lt;p&gt;2. The implementation of the library projects was extremely fragile in Eclipse. Adding extra source folders outside of the project folders is non-trivial when it needs to be handled automatically, in a way that doesn’t expose a user’s local installation path (which is required for people working in teams through a source control system such as SVN or git).&lt;/p&gt;&lt;p&gt;For r14, we decided to fix both issues at once, by moving to a compiled-code based library mechanism. This solves the implementation fragility in Eclipse and will allow us to, later, enable distribution of libraries as a single jar file.&lt;/p&gt;&lt;p&gt;As you might have seen in the release notes, moving to this new mechanism can affect existing projects in some cases, but there are simple fixes.&lt;/p&gt;&lt;p&gt;The first impact of this change is that the new library project requires the resource IDs generated by libraries to be non final. This prevents the Java compiler from inlining the values in the library code, and therefore prevents usage of the &lt;code&gt;switch&lt;/code&gt; statement in the library code. To address such occurrences in your code, Eclipse provides a refactoring action to convert from &lt;code&gt;switch&lt;/code&gt; statements to &lt;code&gt;if/else&lt;/code&gt; (see &lt;a href="http://tools.android.com/tips/non-constant-fields"&gt;here&lt;/a&gt;).&lt;/p&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 243px; height: 311px;" src="http://1.bp.blogspot.com/-qK9QkteqkOI/Tqb8ThWOSuI/AAAAAAAAAAc/ih9nrdQFauY/s320/Picture%2B7%2Bcopy.png" alt="" id="BLOGGER_PHOTO_ID_5667494593391643362" border="0" /&gt;&lt;p&gt;Second, some projects may not have been properly migrated to the new mechanism, resulting in projects that fail to compile, with errors such as duplicated classes being added in the dex build step. ADT 14 should have migrated older projects to the new mechanism but the fragility of the old mechanism may have prevented it from happening. This makes projects reference the libraries twice, using both the old and new mechanisms, which then triggers the libraries classes being packaged twice. If you see this in your projects, look in the Package Explorer for extraneous source folders named with the pattern &lt;code&gt;&amp;lt;libraryname&amp;gt;_src&lt;/code&gt;. The screenshot to the right shows an example of this.&lt;/p&gt;&lt;p&gt;To fix the project, you must remove the extraneous source folders with the following steps:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Right click source folder and choose Build Path &amp;gt; Remove from Build path&lt;/li&gt;&lt;li&gt;A dialog will pop up. In it, make sure to check “Also unlink the folder from the project” to completely remove the folder.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;With this change to library projects, we pave the way to better support for reusable components. We will continue working to make components easier to create, work with, and manage. Our goal is to make it easy for developers to create apps with great user experiences that easily adapt to all form factors.&lt;/p&gt;&lt;p&gt;Some developers have also told us that they only use library projects internally, that they don’t need to distribute binary versions and would prefer to continue with a source-based mechanism. We are investigating how we could support this alongside the new mechanism.&lt;/p&gt;&lt;p&gt;Finally, I wanted to point out that we are tracking a few known issues (and workaround for them) in the current r14 tools at this page: &lt;a href="http://tools.android.com/knownissues"&gt;http://tools.android.com/knownissues&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;We are working on a tools update that will include fixes for most of these. We are hoping to have it out shortly.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3823126010432939653?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=ahof9B8Zw44:nOpPpraJhS4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=ahof9B8Zw44:nOpPpraJhS4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=ahof9B8Zw44:nOpPpraJhS4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/ahof9B8Zw44" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/3823126010432939653?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/3823126010432939653?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/ahof9B8Zw44/changes-to-library-projects-in-android.html" title="Changes to Library Projects in Android SDK Tools, r14" /><author><name>Xavier Ducrohet, Android SDK Tech Lead</name><uri>http://www.blogger.com/profile/05953032183412177238</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-qK9QkteqkOI/Tqb8ThWOSuI/AAAAAAAAAAc/ih9nrdQFauY/s72-c/Picture%2B7%2Bcopy.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/10/changes-to-library-projects-in-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMHSXY5cSp7ImA9WhdaEUk.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-1775949760892875753</id><published>2011-10-20T10:20:00.000-07:00</published><updated>2011-10-20T14:33:58.829-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-20T14:33:58.829-07:00</app:edited><title>New Public APIs in ICS</title><content type="html">&lt;p&gt;Since Android is open-source, anyone can look at the code and see how it works inside.  If you do this, you’ll notice that most but not all of the APIs are &lt;a href="http://developer.android.com/"&gt;publicly documented&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If they’re publicly documented, they’re part of what we consider the Android Application Framework.  This means their tests appear in the &lt;a href="http://source.android.com/compatibility/cts-intro.html"&gt;Compatibility Test Suite (CTS)&lt;/a&gt; so that our hardware partners have to prove that the APIs work, and that we promise to try very hard not to change them and thus break your code.&lt;/p&gt;&lt;p&gt;In almost every case, there’s only one reason for leaving APIs undocumented: We’re not sure that what we have now is the best solution, and we think we might have to improve it, and we’re not prepared to make those commitments to testing and preservation.&lt;/p&gt;&lt;p&gt;We’re not claiming that they’re “Private”  or “Secret”&amp;nbsp;&amp;mdash;&amp;nbsp;How could they be, when anyone in the world can discover them?  We’re also not claiming they’re forbidden: If you use them, your code will compile and probably run.  And in fact we know of quite a few apps out there whose developers have used undocumented APIs, often to good effect.  It’s hard to get too upset about this in cases where there’s a useful API that we haven’t gotten around to stabilizing.&lt;/p&gt;&lt;p&gt;But the developers who use those APIs have to be prepared to deal with the situation that arises when we move them from the undocumented outside into the Android Application Framework.  Fortunately, this is reasonably straightforward.  Also we take a close look at Android Market, using our in-house analytics tools, to get a feel for the impact when we know one of these changes is coming.&lt;/p&gt;&lt;p&gt;There are a few such changes coming up in the Android 4.0 &amp;ldquo;Ice Cream Sandwich&amp;rdquo; (ICS) release of Android.  We wanted to take the opportunity to combine these words on undocumented APIs with some specifics about the changes.&lt;/p&gt;&lt;h3&gt;Calendars&lt;/h3&gt;&lt;p&gt;Let’s start with the good news: As of ICS, the Android Framework will include a fully-worked-out &lt;a href="http://developer.android.com/reference/android/provider/CalendarContract.html"&gt;set of APIs&lt;/a&gt; for accessing Calendar data.  You can guess the bad news: Quite a few developers have built apps (including many good ones) using the undocumented Calendar APIs, some using fairly low-level access to the calendar database.  Unfortunately, these integrations were unsupported, and prone to breakage by platform updates or OEM customization of calendar features.&lt;/p&gt;&lt;p&gt;We want to see lots of good calendar apps and extensions that work reliably across Android devices, and aren't broken by platform updates. So we decided to create a clean API, including a comprehensive set of Intents, to manage calendar data in ICS. Now anyone can code against these new APIs and know that Android is committed to supporting them, and that partners have to support these APIs as part of CTS. &lt;/p&gt;&lt;p&gt;Once the new APIs arrive, you’re going to have to update your apps before they’ll run correctly on ICS while still working on older releases.  There are a variety of techniques for doing that, many of which have been featured on this blog, including &lt;a href="http://android-developers.blogspot.com/2009/04/backward-compatibility-for-android.html"&gt;reflection&lt;/a&gt; and &lt;a href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html"&gt;lazy loading&lt;/a&gt;.  Recently, we introduced &lt;a href="http://android-developers.blogspot.com/2011/07/multiple-apk-support-in-android-market.html"&gt;Multiple-APK support&lt;/a&gt;, which could also be used to help with this sort of transition.&lt;/p&gt;&lt;h3&gt;Text To Speech&lt;/h3&gt;&lt;p&gt;Android has never really had a text-to-speech API at the Framework level, but there was unofficial access at the C++ level.  With ICS, we will have a fully-thought-through &lt;a href="http://developer.android.com/reference/android/speech/tts/TextToSpeech.html"&gt;application-level API&lt;/a&gt; running on Dalvik, so you can access it with ordinary Java-language application code.  &lt;/p&gt;&lt;p&gt;The old C++ API will no longer be supported, but we’ll have a compatibility layer that you can use to bridge from it to the new API.  We think it should be easy to update for ICS with very little work.&lt;/p&gt;&lt;h3&gt;Doing the Right Thing&lt;/h3&gt;&lt;p&gt;We recognize that this means some work for developers affected by these changes, but we’re confident that Android programs in general, and both Calendar and TTS apps in particular, will come out ahead.  And we also think that most developers know that when they use undocumented APIs, they’re making a commitment to doing the right thing when those APIs change.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-1775949760892875753?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=vIJqUs2l2jc:qAY3xUH9z78:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=vIJqUs2l2jc:qAY3xUH9z78:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=vIJqUs2l2jc:qAY3xUH9z78:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/vIJqUs2l2jc" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/1775949760892875753?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/1775949760892875753?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/vIJqUs2l2jc/ics-and-non-public-apis.html" title="New Public APIs in ICS" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><feedburner:origLink>http://android-developers.blogspot.com/2011/10/ics-and-non-public-apis.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QNRHo9eip7ImA9WhdbGUQ.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-7571970047251223725</id><published>2011-10-18T20:00:00.000-07:00</published><updated>2011-10-18T20:36:35.462-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-18T20:36:35.462-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Android 4.0" /><category scheme="http://www.blogger.com/atom/ns#" term="SDK updates" /><category scheme="http://www.blogger.com/atom/ns#" term="Announcements" /><title>Android 4.0 Platform and Updated SDK Tools</title><content type="html">&lt;img style="float: right; margin: 0 10px 10px 0; cursor: pointer;width: 267px; height: 200px;" src="http://1.bp.blogspot.com/-ebqT6DKrawQ/Tp3Xwy-G78I/AAAAAAAAAAQ/6u4Vf0oslIk/s320/ICS.png" alt="ICS logo" id="BLOGGER_PHOTO_ID_5664921139617918914" border="0" /&gt;&lt;p&gt;Today we are announcing Android 4.0, Ice Cream Sandwich &amp;mdash; a new version of the platform that brings a refined, unified user experience for phones, tablets, and more.&lt;/p&gt;&lt;p&gt;Android 4.0 builds on the things people love most about Android &amp;mdash; efficient multitasking, rich notifications, customizable home screens, resizable widgets, and deep interactivity &amp;mdash; and adds powerful new ways of communicating and sharing. It includes many great features for users, including social and sharing integration, network data usage control, innovative connectivity and camera options, and an updated set of standard apps.&lt;/p&gt;&lt;p&gt;For developers, Android 4.0 introduces many new capabilities and APIs. Here are some highlights:&lt;/p&gt;&lt;dd&gt;&lt;br /&gt;
&lt;dl&gt;&lt;p&gt;&lt;em&gt;Unified UI toolkit:&lt;/em&gt; A single set of UI components, styles, and capabilities for phones, tablets, and other devices.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Rich communication and sharing:&lt;/em&gt; New social and calendar APIs, Android Beam for NFC-based instant sharing, Wi-Fi Direct support, Bluetooth Health Device Profile support.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Deep interactivity and customization:&lt;/em&gt; Improved notifications, lockscreen with camera and music controls, and improved app management in the launcher.&lt;/p&gt;&lt;p&gt;&lt;em&gt;New graphics, camera, and media capabilities:&lt;/em&gt; Image and video effects, precise camera metering and face detection, new media codecs and containers.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Interface and input:&lt;/em&gt; Hardware-accelerated 2D drawing, new grid-based layout, improved soft keyboard, spell-checker API, stylus input support, and better mouse support.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Improved accessibility:&lt;/em&gt; New accessibility APIs and  text-to-speech APIs for writing new engines.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Enhancements for enterprise:&lt;/em&gt; Keychain and VPN APIs for managing credentials and connections, a new administrator policy for disabling the camera.&lt;/p&gt;&lt;/dl&gt;&lt;/dd&gt;&lt;p&gt;For a complete overview of what’s new for users and developers, please read the &lt;a onclick="javascript: pageTracker._trackPageview('/outgoing/sdk-4.0-blogpost/highlights-4.0');" href="http://developer.android.com/sdk/android-4.0-highlights.html" title="Android 4.0 Platform Highlights"&gt;Android 4.0 Platform Highlights&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Alongside the new Android platform, we are releasing new versions of the SDK Tools (r14) and ADT Plugin (14.0) for Eclipse. Among the highlights are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Improved build performance in Ant and Eclipse&lt;/li&gt;
&lt;li&gt;Improved layout and XML editors&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;To get started developing on Android 4.0, visit the &lt;a onclick="javascript: pageTracker._trackPageview('/outgoing/sdk-4.0-blogpost/android-dev');" href="http://developer.android.com/sdk/index.html" title="Android Developers site"&gt;Android Developers&lt;/a&gt; site for information about the &lt;a onclick="javascript: pageTracker._trackPageview('/outgoing/sdk-4.0-blogpost/android-4.0');" href="http://developer.android.com/sdk/android-4.0.html" title="Android 4.0 Platform"&gt;Android 4.0 platform&lt;/a&gt;, the &lt;a onclick="javascript: pageTracker._trackPageview('/outgoing/sdk-4.0-blogpost/tools-notes');" href="http://developer.android.com/sdk/tools-notes.html" title="SDK Tools"&gt;SDK Tools&lt;/a&gt;, and the &lt;a onclick="javascript: pageTracker._trackPageview('/outgoing/sdk-4.0-blogpost/adt');" href="http://developer.android.com/sdk/eclipse-adt.html" title="ADT Plugin"&gt;ADT Plugin&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you have already developed and published apps, we encourage you to download the Android 4.0 platform now, to begin testing your app before devices arrive in stores.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Check out the video below for a closer look at Android 4.0 in action.&lt;/p&gt;&lt;p style="text-align: center;"&gt;&lt;object style="height: 344px; width:425px"&gt;&lt;param name="movie" value="http://www.youtube.com/v/-F_ke3rxopc?version=3"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/-F_ke3rxopc?version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="360"&gt;&lt;/object&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7571970047251223725?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=_P-tzLggUZg:5LeK8X_7qkk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=_P-tzLggUZg:5LeK8X_7qkk:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=_P-tzLggUZg:5LeK8X_7qkk:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/_P-tzLggUZg" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/7571970047251223725?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/7571970047251223725?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/_P-tzLggUZg/android-40-platform-and-updated-sdk.html" title="Android 4.0 Platform and Updated SDK Tools" /><author><name>Xavier Ducrohet, Android SDK Tech Lead</name><uri>http://www.blogger.com/profile/05953032183412177238</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-ebqT6DKrawQ/Tp3Xwy-G78I/AAAAAAAAAAQ/6u4Vf0oslIk/s72-c/ICS.png" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/10/android-40-platform-and-updated-sdk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4BQHc5fip7ImA9WhdbEE0.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-687446965502713273</id><published>2011-10-05T08:38:00.000-07:00</published><updated>2011-10-07T08:22:31.926-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-07T08:22:31.926-07:00</app:edited><title>Android Market Featured-Image Guidelines</title><content type="html">&lt;a href="http://3.bp.blogspot.com/-3TWKMFw919Q/ToymcLyETfI/AAAAAAAAAtE/YkZ9y7DTTrI/s1600/NataschaBock254.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 174px;" src="http://3.bp.blogspot.com/-3TWKMFw919Q/ToymcLyETfI/AAAAAAAAAtE/YkZ9y7DTTrI/s200/NataschaBock254.jpg" border="0" id="BLOGGER_PHOTO_ID_5660081834827206130" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by Natascha Bock, a Product Marketing Manager on Android.&amp;nbsp;&amp;mdash;&amp;nbsp;Tim&amp;nbsp;Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;With the latest &lt;a href="http://android-developers.blogspot.com/2011/07/new-android-market-for-phones.html"&gt;Android Market update&lt;/a&gt;, our editorial team can use your 1024 x 500 “Featured Image” to promote your app on tablets, phones, and the Web.  The image can be used on the home page on all versions of Android Market (Web, tablet and phone), on your product page in the Web and tablet versions, and on current and future top-level Android Market pages on phones.&lt;/p&gt;&lt;p&gt;Creating a Featured Image that will do a great job of highlighting your app requires special design consideration.  &lt;/p&gt;&lt;h3&gt;Not Really Optional&lt;/h3&gt;&lt;p&gt;While many promotional assets are listed as “optional” for the publishing site, we strongly recommend treating them as required.  To start with, a Featured Image is required if your app is to be featured anywhere within Android Market.  They’re a good idea anyhow; they enhance your product page, making your game or app more attractive to end-users (and more likely to be considered for featuring by our editorial team).&lt;/p&gt;&lt;p&gt;There’s nothing optional about the size, either; it has to be 1024 x 500 pixels.&lt;/p&gt;&lt;h3&gt;Do’s and Dont’s&lt;/h3&gt;&lt;p&gt;Your graphic is not an ad, it’s a teaser.  It’s a place for bold, creative promotional images.&lt;/p&gt;&lt;p&gt;Vivid background colors work best.  Black and white are problems because those are the backgrounds used by the mobile-device and Web versions of Android Market.&lt;/p&gt;&lt;p&gt;Limit Text to your app name and maybe a few additional descriptive words. Anything else will be unreadable on phones, anyhow.&lt;/p&gt;&lt;table frame="void" rules="none"  style="div.nbp {margin: 0px 40px 0 40px;}  table {text-align: center;}"&gt;&lt;tr valign="top" align="left"&gt;&lt;td&gt;&lt;img src="http://1.bp.blogspot.com/-z3zf4G4XASw/ToojUEM07TI/AAAAAAAAAr8/uxwgC51i08w/s1600/unicorn_good_small.jpg"/&gt;&lt;/td&gt;&lt;td&gt;&lt;img src="http://4.bp.blogspot.com/-fdWjRen-4Ms/ToojgJanoxI/AAAAAAAAAsE/bzHaOdzXj10/s400/unicorn_bad_small.jpg"/&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr valign="bottom" align="left"&gt;&lt;td&gt;&lt;div class="nbp"&gt;&lt;b&gt;Do:&lt;/b&gt; Make the graphic fun&lt;br/&gt;and enticing.&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div class="nbp"&gt;&lt;b&gt;Don't:&lt;/b&gt; Create a text-heavy&lt;br/&gt; advertising-style graphic.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr valign="bottom" align="left"&gt;&lt;td&gt;&lt;div class="nbp"&gt;&lt;b&gt;Do:&lt;/b&gt; Use colors that stand out on&lt;br/&gt;black or white backgrounds.&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div class="nbp"&gt;&lt;b&gt;Don't:&lt;/b&gt; Let the graphic fade into&lt;br/&gt;the background.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr valign="bottom" align="left"&gt;&lt;td&gt;&lt;div class="nbp"&gt;&lt;b&gt;Do:&lt;/b&gt; Promote your brand prominently.&lt;/div&gt;&lt;/td&gt;&lt;td&gt;&lt;div class="nbp"&gt;&lt;b&gt;Don't:&lt;/b&gt; Overload the graphic with details.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;h3&gt;Scaling&lt;/h3&gt;&lt;p&gt;Your image has to be designed to scale; it will need to look good both in a full-size Web browser and on a little handset.  You can rely on the aspect ratio being constant, but not the size. Here’s a tip: Try resizing your image down to 1 inch in width. If it still looks good and conveys your brand message, you have a winner.  &lt;/p&gt;&lt;p&gt;On the Web:&lt;/p&gt;&lt;img src="http://3.bp.blogspot.com/-mW6qBQ8Bszs/ToyX1nZOjOI/AAAAAAAAAsM/P0HJ3moNgWU/s1600/unicorn_good_large.jpg" border="0" id="BLOGGER_PHOTO_ID_5660065779061525730" /&gt;&lt;p&gt;&lt;br/&gt;On a tablet:&lt;/p&gt;&lt;img  src="http://4.bp.blogspot.com/-e29k-os_U0Q/ToyYBd-QMRI/AAAAAAAAAsU/IH7ztHjBm2E/s400/unicorn_good_medium.jpg" border="0" id="BLOGGER_PHOTO_ID_5660065982690898194" /&gt;
&lt;p&gt;&lt;br/&gt;On a big phone:&lt;/p&gt;&lt;img  src="http://2.bp.blogspot.com/-gjBc_e77uDc/ToyYLp0FzYI/AAAAAAAAAsc/d26iOEY80HM/s400/unicorn_good_small.jpg" border="0" id="BLOGGER_PHOTO_ID_5660066157668191618" /&gt;
&lt;p&gt;&lt;br/&gt;On a small phone:&lt;/p&gt;&lt;img src="http://1.bp.blogspot.com/-tLNR7MzNdEc/ToyYS1d3l1I/AAAAAAAAAsk/MUoJ6v5VPWQ/s400/unicorn_good_extrasmall.jpg" border="0" id="BLOGGER_PHOTO_ID_5660066281055295314" /&gt;&lt;h3&gt;More Dont’s&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Device imagery is tempting, but becomes dated fast, and may be inappropriate if your user’s device looks entirely different.&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;&lt;p&gt;In-app screenshots are inappropriate because your product page already includes a place for these.  &lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Just using your app icon is a failure of imagination.  You have more room; put it to good use!&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Consider the Context&lt;/h3&gt;&lt;p&gt;Given the size of the form factor, the phone is the most challenging channel for your image.  Below we have both the “good” and “bad” sample images in that context:&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/-a5pXADMla6w/ToyoF-681iI/AAAAAAAAAtM/YpLR3wrik94/s1600/Market_home_home_mock2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 400px;" src="http://2.bp.blogspot.com/-a5pXADMla6w/ToyoF-681iI/AAAAAAAAAtM/YpLR3wrik94/s400/Market_home_home_mock2.jpg" border="0" id="BLOGGER_PHOTO_ID_5660083652440938018" /&gt;&lt;/a&gt;&lt;h3&gt;Don’t Forget&lt;/h3&gt;&lt;p&gt;A 1024 x 500 Featured Image is &lt;em&gt;required&lt;/em&gt; for feature placement consideration. Don't miss out on the opportunity!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-687446965502713273?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=QCVO3eXemQ0:rb9JWMgCGiA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=QCVO3eXemQ0:rb9JWMgCGiA:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=QCVO3eXemQ0:rb9JWMgCGiA:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/QCVO3eXemQ0" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/687446965502713273?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/687446965502713273?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/QCVO3eXemQ0/android-market-featured-image.html" title="Android Market Featured-Image Guidelines" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-3TWKMFw919Q/ToymcLyETfI/AAAAAAAAAtE/YkZ9y7DTTrI/s72-c/NataschaBock254.jpg" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/10/android-market-featured-image.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QBQHg_cSp7ImA9WhdUFE0.&quot;"><id>tag:blogger.com,1999:blog-6755709643044947179.post-2415412611315413372</id><published>2011-09-29T09:17:00.000-07:00</published><updated>2011-09-30T09:49:11.649-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-30T09:49:11.649-07:00</app:edited><title>Android’s HTTP Clients</title><content type="html">&lt;a href="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s1600/jessehawaii.jpg"&gt;&lt;img style="border: 5px solid #ddd; float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 199px;" src="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s200/jessehawaii.jpg" border="0" alt="Jesse Wilson" id="BLOGGER_PHOTO_ID_5657543353414584562" /&gt;&lt;/a&gt;&lt;p&gt;&lt;i&gt;[This post is by &lt;a href="http://www.publicobject.com/"&gt;Jesse Wilson&lt;/a&gt; from the Dalvik team. —Tim Bray]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Most network-connected Android apps will use HTTP to send and receive data. Android includes two HTTP clients: HttpURLConnection and Apache HTTP Client. Both support HTTPS, streaming uploads and downloads, configurable timeouts, IPv6 and connection pooling.&lt;/p&gt;&lt;h3&gt;Apache HTTP Client&lt;/h3&gt;&lt;p&gt;&lt;a href="http://developer.android.com/reference/org/apache/http/impl/client/DefaultHttpClient.html "&gt;DefaultHttpClient&lt;/a&gt; and its sibling &lt;a href="http://developer.android.com/reference/android/net/http/AndroidHttpClient.html"&gt;AndroidHttpClient&lt;/a&gt; are extensible HTTP clients suitable for web browsers. They have large and flexible APIs. Their implementation is stable and they have few bugs. &lt;/p&gt;&lt;p&gt;But the large size of this API makes it difficult for us to improve it without breaking compatibility. The Android team is not actively working on Apache HTTP Client.&lt;/p&gt;&lt;h3&gt;HttpURLConnection&lt;/h3&gt;&lt;p&gt;&lt;a href="http://developer.android.com/reference/java/net/HttpURLConnection.html"&gt;HttpURLConnection&lt;/a&gt; is a general-purpose, lightweight HTTP client suitable for most applications. This class has humble beginnings, but its focused API has made it easy for us to improve steadily.&lt;/p&gt;&lt;p&gt;Prior to Froyo, HttpURLConnection had some frustrating bugs. In particular, calling &lt;code&gt;close()&lt;/code&gt; on a readable InputStream could &lt;a href="http://code.google.com/p/android/issues/detail?id=2939"&gt;poison the connection pool&lt;/a&gt;. Work around this by disabling connection pooling:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;private void disableConnectionReuseIfNecessary() {
    // HTTP connection reuse which was buggy pre-froyo
    if (Integer.parseInt(Build.VERSION.SDK) &amp;lt; Build.VERSION_CODES.FROYO) {
        System.setProperty("http.keepAlive", "false");
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In Gingerbread, we added transparent response compression. HttpURLConnection will automatically add this header to outgoing requests, and handle the corresponding response:&lt;/p&gt;&lt;p&gt;&lt;code&gt;Accept-Encoding: gzip&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Take advantage of this by configuring your Web server to compress responses for clients that can support it. If response compression is problematic, the &lt;a href="http://developer.android.com/reference/java/net/HttpURLConnection.html"&gt;class documentation&lt;/a&gt; shows how to disable it.&lt;/p&gt;&lt;p&gt;Since HTTP’s &lt;code&gt;Content-Length&lt;/code&gt; header returns the compressed size, it is an error to use &lt;a href="http://developer.android.com/reference/java/net/URLConnection.html#getContentLength() "&gt;getContentLength()&lt;/a&gt; to size buffers for the uncompressed data. Instead, read bytes from the response until &lt;a href="http://developer.android.com/reference/java/io/InputStream.html#read(byte[])"&gt;InputStream.read()&lt;/a&gt; returns -1.&lt;/p&gt;&lt;p&gt;We also made several improvements to HTTPS in Gingerbread. &lt;a href="http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html"&gt;HttpsURLConnection&lt;/a&gt; attempts to connect with &lt;a href="http://en.wikipedia.org/wiki/Server_Name_Indication"&gt;Server Name Indication&lt;/a&gt; (SNI) which allows multiple HTTPS hosts to share an IP address. It also enables compression and session tickets. Should the connection fail, it is automatically retried without these features. This makes HttpsURLConnection efficient when connecting to up-to-date servers, without breaking compatibility with older ones.&lt;/p&gt;&lt;p&gt;In Ice Cream Sandwich, we are adding a response cache. With the cache installed, HTTP requests will be satisfied in one of three ways:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Fully cached responses are served directly from local storage. Because no network connection needs to be made such responses are available immediately. &lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Conditionally cached responses must have their freshness validated by the webserver. The client sends a request like “Give me /foo.png if it changed since yesterday” and the server replies with either the updated content or a &lt;code&gt;304&amp;nbsp;Not&amp;nbsp;Modified&lt;/code&gt; status. If the content is unchanged it will not be downloaded!&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Uncached responses are served from the web. These responses will get stored in the response cache for later.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Use reflection to enable HTTP response caching on devices that support it. This sample code will turn on the response cache on Ice Cream Sandwich without affecting earlier releases:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;private void enableHttpResponseCache() {
    try {
        long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
        File httpCacheDir = new File(getCacheDir(), "http");
        Class.forName("android.net.http.HttpResponseCache")
            .getMethod("install", File.class, long.class)
            .invoke(null, httpCacheDir, httpCacheSize);
    } catch (Exception httpResponseCacheNotAvailable) {
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should also configure your Web server to set cache headers on its HTTP responses.&lt;/p&gt;&lt;h3&gt;Which client is best?&lt;/h3&gt;&lt;p&gt;Apache HTTP client has fewer bugs on Eclair and Froyo. It is the best choice for these releases.&lt;/p&gt;&lt;p&gt;For Gingerbread and better, HttpURLConnection is the best choice. Its simple API and small size makes it great fit for Android. Transparent compression and response caching reduce network use, improve speed and save battery. New applications should use &lt;a href="http://developer.android.com/reference/java/net/HttpURLConnection.html"&gt;HttpURLConnection&lt;/a&gt;; it is where we will be spending our energy going forward.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2415412611315413372?l=android-developers.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=66uCQtyHwU4:8Nz1oGm4ZLw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/blogspot/hsDu?a=66uCQtyHwU4:8Nz1oGm4ZLw:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/blogspot/hsDu?i=66uCQtyHwU4:8Nz1oGm4ZLw:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/hsDu/~4/66uCQtyHwU4" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2415412611315413372?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6755709643044947179/posts/default/2415412611315413372?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/hsDu/~3/66uCQtyHwU4/androids-http-clients.html" title="Android’s HTTP Clients" /><author><name>Tim Bray</name><uri>http://www.blogger.com/profile/00036641002026688852</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/_GTM_W5mVPTU/S9df2UvUAWI/AAAAAAAAAAM/XTF3Fh51McM/S220/Tim.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-vhNi2_GZQ9U/ToOhtHmmCPI/AAAAAAAAAr0/kfHjHZKQdVE/s72-c/jessehawaii.jpg" height="72" width="72" /><feedburner:origLink>http://android-developers.blogspot.com/2011/09/androids-http-clients.html</feedburner:origLink></entry></feed>

