<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Google Data &#187; Romain Guy</title>
	<atom:link href="/author/romain-guy/feed/" rel="self" type="application/rss+xml" />
	<link>https://googledata.org</link>
	<description>Everything Google: News, Products, Services, Content, Culture</description>
	<lastBuildDate>Fri, 03 Apr 2015 21:58:02 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.1</generator>
	<item>
		<title>Live wallpapers</title>
		<link>https://googledata.org/google-android/live-wallpapers/</link>
		<comments>https://googledata.org/google-android/live-wallpapers/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 17:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[With the introduction of live wallpapers in Android 2.1, users can now enjoy richer, animated, interactive backgrounds on their home screen. A live wallpaper is very similar to a normal Android application and has access to all the facilities of the pl...]]></description>
				<content:encoded><![CDATA[<p>With the introduction of live wallpapers in <a href="http://d.android.com/sdk/android-2.1.html">Android 2.1</a>, users can now enjoy richer, animated, interactive backgrounds on their home screen. A live wallpaper is very similar to a normal Android application and has access to all the facilities of the platform: SGL (2D drawing), OpenGL (3D drawing), GPS, accelerometers, network access, etc.  The live wallpapers included on Nexus One demonstrate the use of some of these APIs to create fun and interesting user experiences. For instance, the Grass wallpaper uses the phone's location to compute sunrise and sunset times in order to display the appropriate sky.</p><p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9l0GmPwgCzk/S2vKMD1cJYI/AAAAAAAAAFM/c_eUv0HcN_Y/s1600-h/live_wallpapers_small.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 162px;" src="http://2.bp.blogspot.com/_9l0GmPwgCzk/S2vKMD1cJYI/AAAAAAAAAFM/c_eUv0HcN_Y/s400/live_wallpapers_small.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5434659683889325442" /></a></p><p>Creating your own live wallpaper is easy, especially if you have had previous experience with <code>SurfaceView</code> or <code>Canvas</code>. To learn how to create a live wallpaper, you should check out the <code>CubeLiveWallpaper</code> sample provided with the Android 2.1 SDK; you will find it in the directory <code>platforms/android-2.1/samples/CubeLiveWallpaper</code>.</p><p>A live wallpaper is very similar to a regular Android service. The only difference is the addition of a new method, <a href="http://d.android.com/reference/android/service/wallpaper/WallpaperService.html#onCreateEngine%28%29">onCreateEngine()</a> whose goal is to create a <a href="http://d.android.com/reference/android/service/wallpaper/WallpaperService.Engine.html">WallpaperService.Engine.</a> The engine is responsible for handling the lifecycle and the drawing of a wallpaper. The system provides you with a surface on which you can draw, just like you would with a <code>SurfaceView</code>. Drawing a wallpaper can be very expensive so you should optimize your code as much as possible to avoid using too much CPU, not only for battery life but also to avoid slowing down the rest of the system. That is also why the most important part of the lifecycle of a wallpaper is <a href="http://d.android.com/reference/android/service/wallpaper/WallpaperService.Engine.html#onVisibilityChanged%28boolean%29">when it becomes invisible</a>. When invisible, for instance because the user launched an application that covers the home screen, a wallpaper must stop all activity.</p><p>The engine can also implement several methods to interact with the user or the home application. For instance, if you want your wallpaper to scroll along when the user swipes from one home screen to another, you can use <a href="http://d.android.com/reference/android/service/wallpaper/WallpaperService.Engine.html#onOffsetsChanged%28float,%20float,%20float,%20float,%20int,%20int%29">onOffsetsChanged()</a>. To react to touch events, simply implement <a href="http://d.android.com/reference/android/service/wallpaper/WallpaperService.Engine.html#onTouchEvent%28android.view.MotionEvent%29">onTouchEvent(MotionEvent)</a>. Finally, applications can send arbitrary commands to the live wallpaper. Currently, only the standard home application sends commands to the <a href="http://d.android.com/reference/android/service/wallpaper/WallpaperService.Engine.html#onCommand%28java.lang.String,%20int,%20int,%20int,%20android.os.Bundle,%20boolean%29">onCommand()</a> method of the live wallpaper:</p><ul><li><code>android.wallpaper.tap</code>: When the user taps an empty space on the workspace. This command is interpreted by the Nexus and Water live wallpapers to make the wallpaper react to user interaction. For instance, if you tap an empty space on the Water live wallpaper, new ripples appear under your finger.</li><li><code>android.home.drop</code>: When the user drops an icon or a widget on the workspace. This command is also interpreted by the Nexus and Water live wallpapers.</li></ul><p>Please note that live wallpaper is an Android 2.1 feature. To ensure that only users with devices that support this feature can download your live wallpaper, remember to add the following to your manifest before releasing to Android Market:</p><ul><li><code>&lt;uses-sdk android:minSdkVersion="7" /&gt;</code>, which lets Android Market and the platform know that your application is using the Android 2.1 version.</li><li><code>&lt;uses-feature android:name="android.software.live_wallpaper" /&gt;</code>, which lets the Android Market and the platform know that your application is a live wallpaper.</li></ul><p>Many great live wallpapers are already available on Android Market and we can't wait to see more!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5277070185509747896?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/live-wallpapers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Optimize your layouts</title>
		<link>https://googledata.org/google-android/optimize-your-layouts/</link>
		<comments>https://googledata.org/google-android/optimize-your-layouts/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 20:18:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[<br/>
Writing user interface layouts for Android applications is easy, but it can sometimes be difficult to optimize them. Most often, heavy modifications made to existing XML layouts, like shuffling views around or changing the type of a container, lead to inefficiencies that go unnoticed.<div>
</div><div>Starting with the <a href="http://d.android.com/sdk/tools-notes.html">SDK Tools Revision 3</a> you can use a tool called <a href="http://d.android.com/guide/developing/tools/layoutopt.html"><span>layoutopt</span></a> to automatically detect common problems. This tool is currently only available from the command line and its use is very simple - just open a terminal and launch the <span>layoutopt</span> command with a list of directories or XML files to analyze:</div><div>
</div><br/><pre><span><span><span>$ layoutopt samples/
samples/compound.xml
</span><span>  7:23 The root-level &#60;FrameLayout/&#62; can be replaced with &#60;merge/&#62;
  11:21 This LinearLayout layout or its FrameLayout parent is useless samples/simple.xml
  7:7 The root-level &#60;FrameLayout/&#62; can be replaced with &#60;merge/&#62;
samples/too_deep.xml
</span><span>  -1:-1 This layout has too many nested layouts: 13 levels, it should have &#60;= 10!
  20:81 This LinearLayout layout or its LinearLayout parent is useless
  24:79 This LinearLayout layout or its LinearLayout parent is useless
  28:77 This LinearLayout layout or its LinearLayout parent is useless
  32:75 This LinearLayout layout or its LinearLayout parent is useless
  36:73 This LinearLayout layout or its LinearLayout parent is useless
  40:71 This LinearLayout layout or its LinearLayout parent is useless
  44:69 This LinearLayout layout or its LinearLayout parent is useless
  48:67 This LinearLayout layout or its LinearLayout parent is useless
  52:65 This LinearLayout layout or its LinearLayout parent is useless
  56:63 This LinearLayout layout or its LinearLayout parent is useless
samples/too_many.xml
</span><span>  7:413 The root-level &#60;FrameLayout/&#62; can be replaced with &#60;merge/&#62;
  -1:-1 This layout has too many views: 81 views, it should have &#60;= 80! samples/useless.xml
  7:19 The root-level &#60;FrameLayout/&#62; can be replaced with &#60;merge/&#62;
  11:17 This LinearLayout layout or its FrameLayout parent is useless
</span></span></span></pre><div>For each analyzed file, the tool will indicate the line numbers of each tag that could potentially be optimized. In some cases, layoutopt will also offer a possible solution.</div><div>
</div><div>The current version of layoutopt contains a dozen rules used to analyze your layout files and future versions will contain more. Future plans for this tool also include the ability to create and use your own analysis rules, to automatically modify the layouts with optimized XML, and to use it from within Eclipse and/or a standalone user interface.</div><br/>
<div><strong>Windows users</strong>: to start layoutopt, open the file called <code>layoutopt.bat</code> in the tools directory of the SDK and on the last line, replace <code>%jarpath%</code> with <code>-jar %jarpath%</code>.</div><div><img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/6755709643044947179-3212925535534548306?l=android-developers.blogspot.com" alt="" /></div>]]></description>
				<content:encoded><![CDATA[<br/>
<style type="text/css"><br />/* Stylesheet generated from TextMate theme<br /> *<br /> * Mac Classic<br /> * <br /> *<br /> */<br /><br />/* Mostly to improve view within the TextMate HTML viewer */<br />body {<br /> margin: 0;<br /> padding: 0;<br />}<br /><br />pre.textmate-source {<br /> margin: 0;<br /> padding: 0 0 0 2px;<br /> font-family: Monaco, monospace;<br /> font-size: 11px;<br /> line-height: 1.3em;<br /> word-wrap: break-word;<br /> white-space: pre;<br /> white-space: pre-wrap;<br /> white-space: -moz-pre-wrap;<br /> white-space: -o-pre-wrap;<br />}<br /><br />pre.textmate-source.mac_classic {<br /> color: #000000;<br /> background-color: #FFFFFF;<br />}<br /><br />pre.textmate-source .linenum {<br /> width: 75px;<br /> padding: 0.1em 1em 0.2em 0;<br /> color: #888;<br /> background-color: #eee;<br />}<br />pre.textmate-source.mac_classic span {<br />   padding-top: 0.2em;<br />   padding-bottom: 0.1em;<br />}<br />pre.textmate-source.mac_classic ::selection {<br /> background-color: rgba(77, 151, 255, 0.33);<br />}<br />/* Comment */<br />pre.textmate-source.mac_classic .comment {<br /> color: #0066FF;<br /> font-style: italic;<br />}<br /><br />/* Keyword */<br />pre.textmate-source.mac_classic .keyword, pre.textmate-source.mac_classic .storage {<br /> color: #0000FF;<br /> font-weight: bold;<br />}<br /><br />/* Number */<br />pre.textmate-source.mac_classic .constant_numeric {<br /> color: #0000CD;<br />}<br /><br />/* User-defined constant */<br />pre.textmate-source.mac_classic .constant {<br /> color: #C5060B;<br /> font-weight: bold;<br />}<br /><br />/* Built-in constant */<br />pre.textmate-source.mac_classic .constant_language {<br /> color: #585CF6;<br /> font-weight: bold;<br />}<br /><br />/* Variable */<br />pre.textmate-source.mac_classic .variable_language, pre.textmate-source.mac_classic .variable_other {<br /> color: #318495;<br />}<br /><br />/* String */<br />pre.textmate-source.mac_classic .string {<br /> color: #036A07;<br />}<br /><br />/* String interpolation */<br />pre.textmate-source.mac_classic .constant_character_escape, pre.textmate-source.mac_classic .string .source {<br /> color: #26B31A;<br />}<br /><br />/* Preprocessor line */<br />pre.textmate-source.mac_classic .meta_preprocessor {<br /> color: #1A921C;<br />}<br /><br />/* Preprocessor directive */<br />pre.textmate-source.mac_classic .keyword_control_import {<br /> color: #0C450D;<br /> font-weight: bold;<br />}<br /><br />/* Function name */<br />pre.textmate-source.mac_classic .entity_name_function, pre.textmate-source.mac_classic .support_function_any-method {<br /> color: #0000A2;<br /> font-weight: bold;<br />}<br /><br />/* Type name */<br />pre.textmate-source.mac_classic .entity_name_type {<br /> text-decoration: underline;<br />}<br /><br />/* Inherited class name */<br />pre.textmate-source.mac_classic .entity_other_inherited-class {<br /> font-style: italic;<br />}<br /><br />/* Function parameter */<br />pre.textmate-source.mac_classic .variable_parameter {<br /> font-style: italic;<br />}<br /><br />/* Function argument and result types */<br />pre.textmate-source.mac_classic .storage_type_method {<br /> color: #70727E;<br />}<br /><br />/* Section */<br />pre.textmate-source.mac_classic .meta_section .entity_name_section, pre.textmate-source.mac_classic .declaration_section .entity_name_section {<br /> font-style: italic;<br />}<br /><br />/* Library function */<br />pre.textmate-source.mac_classic .support_function {<br /> color: #3C4C72;<br /> font-weight: bold;<br />}<br /><br />/* Library object */<br />pre.textmate-source.mac_classic .support_class, pre.textmate-source.mac_classic .support_type {<br /> color: #6D79DE;<br /> font-weight: bold;<br />}<br /><br />/* Library constant */<br />pre.textmate-source.mac_classic .support_constant {<br /> color: #06960E;<br /> font-weight: bold;<br />}<br /><br />/* Library variable */<br />pre.textmate-source.mac_classic .support_variable {<br /> color: #21439C;<br /> font-weight: bold;<br />}<br /><br />/* JS: Operator */<br />pre.textmate-source.mac_classic .keyword_operator_js {<br /> color: #687687;<br />}<br /><br />/* Invalid */<br />pre.textmate-source.mac_classic .invalid {<br /> color: #FFFFFF;<br /> background-color: #990000;<br />}<br /><br />/* Invalid trailing whitespace */<br />pre.textmate-source.mac_classic .invalid_deprecated_trailing-whitespace {<br /> background-color: #FFD0D0;<br />}<br /><br />/* Embedded source */<br />pre.textmate-source.mac_classic .text .source, pre.textmate-source.mac_classic .string_unquoted {<br /> background-color: rgba(0, 0, 0, 0.05);<br />}<br /><br />/* Embedded embedded source */<br />pre.textmate-source.mac_classic .text .source .string_unquoted, pre.textmate-source.mac_classic .text .source .text .source {<br /> background-color: rgba(0, 0, 0, 0.06);<br />}<br /><br />/* Markup XML declaration */<br />pre.textmate-source.mac_classic .meta_tag_preprocessor_xml {<br /> color: #68685B;<br />}<br /><br />/* Markup DOCTYPE */<br />pre.textmate-source.mac_classic .meta_tag_sgml_doctype, pre.textmate-source.mac_classic .meta_tag_sgml_doctype .entity, pre.textmate-source.mac_classic .meta_tag_sgml_doctype .string, pre.textmate-source.mac_classic .meta_tag_preprocessor_xml, pre.textmate-source.mac_classic .meta_tag_preprocessor_xml .entity, pre.textmate-source.mac_classic .meta_tag_preprocessor_xml .string {<br /> color: #888888;<br />}<br /><br />/* Markup DTD */<br />pre.textmate-source.mac_classic .string_quoted_docinfo_doctype_DTD {<br /> font-style: italic;<br />}<br /><br />/* Markup tag */<br />pre.textmate-source.mac_classic .meta_tag, pre.textmate-source.mac_classic .declaration_tag {<br /> color: #1C02FF;<br />}<br /><br />/* Markup name of tag */<br />pre.textmate-source.mac_classic .entity_name_tag {<br /> font-weight: bold;<br />}<br /><br />/* Markup tag attribute */<br />pre.textmate-source.mac_classic .entity_other_attribute-name {<br /> font-style: italic;<br />}<br /><br />/* Markup: Heading */<br />pre.textmate-source.mac_classic .markup_heading {<br /> color: #0C07FF;<br /> font-weight: bold;<br />}<br /><br />/* Markup: Quote */<br />pre.textmate-source.mac_classic .markup_quote {<br /> color: #000000;<br /> font-style: italic;<br />}<br /><br />/* Markup: List */<br />pre.textmate-source.mac_classic .markup_list {<br /> color: #B90690;<br />}<br /></style>Writing user interface layouts for Android applications is easy, but it can sometimes be difficult to optimize them. Most often, heavy modifications made to existing XML layouts, like shuffling views around or changing the type of a container, lead to inefficiencies that go unnoticed.<div>
</div><div>Starting with the <a href="http://d.android.com/sdk/tools-notes.html">SDK Tools Revision 3</a> you can use a tool called <a href="http://d.android.com/guide/developing/tools/layoutopt.html"><span class="Apple-style-span"  style="font-family:'courier new';">layoutopt</span></a> to automatically detect common problems. This tool is currently only available from the command line and its use is very simple - just open a terminal and launch the <span class="Apple-style-span"  style="font-family:'courier new';">layoutopt</span> command with a list of directories or XML files to analyze:</div><div>
</div><br/><pre class="textmate-source mac_classic"><span class="text text_blog"><span class="text text_plain"><span class="meta meta_paragraph meta_paragraph_text">$ layoutopt samples/
samples/compound.xml
</span><span class="meta meta_paragraph meta_paragraph_text">  7:23 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
  11:21 This LinearLayout layout or its FrameLayout parent is useless samples/simple.xml
  7:7 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
samples/too_deep.xml
</span><span class="meta meta_paragraph meta_paragraph_text">  -1:-1 This layout has too many nested layouts: 13 levels, it should have &lt;= 10!
  20:81 This LinearLayout layout or its LinearLayout parent is useless
  24:79 This LinearLayout layout or its LinearLayout parent is useless
  28:77 This LinearLayout layout or its LinearLayout parent is useless
  32:75 This LinearLayout layout or its LinearLayout parent is useless
  36:73 This LinearLayout layout or its LinearLayout parent is useless
  40:71 This LinearLayout layout or its LinearLayout parent is useless
  44:69 This LinearLayout layout or its LinearLayout parent is useless
  48:67 This LinearLayout layout or its LinearLayout parent is useless
  52:65 This LinearLayout layout or its LinearLayout parent is useless
  56:63 This LinearLayout layout or its LinearLayout parent is useless
samples/too_many.xml
</span><span class="meta meta_paragraph meta_paragraph_text">  7:413 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
  -1:-1 This layout has too many views: 81 views, it should have &lt;= 80! samples/useless.xml
  7:19 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
  11:17 This LinearLayout layout or its FrameLayout parent is useless
</span></span></span></pre><div>For each analyzed file, the tool will indicate the line numbers of each tag that could potentially be optimized. In some cases, layoutopt will also offer a possible solution.</div><div>
</div><div>The current version of layoutopt contains a dozen rules used to analyze your layout files and future versions will contain more. Future plans for this tool also include the ability to create and use your own analysis rules, to automatically modify the layouts with optimized XML, and to use it from within Eclipse and/or a standalone user interface.</div><br/>
<div><strong>Windows users</strong>: to start layoutopt, open the file called <code>layoutopt.bat</code> in the tools directory of the SDK and on the last line, replace <code>%jarpath%</code> with <code>-jar %jarpath%</code>.</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3212925535534548306?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/optimize-your-layouts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UI framework changes in Android 1.6</title>
		<link>https://googledata.org/google-android/ui-framework-changes-in-android-1-6/</link>
		<comments>https://googledata.org/google-android/ui-framework-changes-in-android-1-6/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 21:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Android 1.6 introduces numerous enhancements and bug fixes in the UI framework. Today, I'd like to highlight three two improvements in particular.Optimized drawingThe UI toolkit introduced in Android 1.6 is aware of which views are opaque and can use t...]]></description>
				<content:encoded><![CDATA[<p>Android 1.6 introduces numerous enhancements and bug fixes in the UI framework. Today, I'd like to highlight <strike>three</strike> two improvements in particular.</p><h3>Optimized drawing</h3><p>The UI toolkit introduced in Android 1.6 is aware of which views are opaque and can use this information to avoid drawing views that the user will not be able to see. Before Android 1.6, the UI toolkit would sometimes perform unnecessary operations by drawing a window background when it was obscured by a full-screen opaque view. A <a href="http://android-developers.blogspot.com/2009/03/window-backgrounds-ui-speed.html" title="workaround">workaround</a> was available to avoid this, but the technique was limited and required work on your part. With Android 1.6, the UI toolkit determines whether a view is opaque by simply querying the opacity of the background drawable.  <strike>If you know that your view is going to be opaque but that information does not depend on the background drawable, you can simply override the method called isOpaque():</strike></p><pre><strike>@Override
public boolean isOpaque() {
    return true;
}</strike></pre><p><strike>The value returned by isOpaque() does not have to be constant and can change at any time. For instance, the implementation of ListView in Android 1.6 indicates that a list is opaque only when the user is scrolling it.</strike></p><p><strong>Updated</strong>: Our apologies&mdash;we spoke to soon about isOpaque(). It will be available in a future update to the Android platform.</p><h3>More flexible, more robust RelativeLayout</h3><p>RelativeLayout is the most versatile layout offered by the Android UI toolkit and can be successfully used to reduce the number of views created by your applications. This layout used to suffer from various bugs and limitations, sometimes making it difficult to use without having some knowledge of its implementation. To make your life easier, Android 1.6 comes with a revamped RelativeLayout. This new implementation not only fixes all known bugs in RelativeLayout (<a href="http://b.android.com/" title="let us know">let us know</a> when you find new ones) but also addresses its major limitation: the fact that views had to be declared in a particular order. Consider the following XML layout:</p><pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;

&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="64dip"
    android:padding="6dip"&gt;

    &lt;TextView
        android:id="@+id/band"  
        android:layout_width="fill_parent" 
        android:layout_height="26dip" 

        android:layout_below="@+id/track"
        android:layout_alignLeft="@id/track"
        android:layout_alignParentBottom="true"

        android:gravity="top"
        android:text="The Airborne Toxic Event" /&gt;

    &lt;TextView
        android:id="@id/track"  
        android:layout_marginLeft="6dip"
        android:layout_width="fill_parent"
        android:layout_height="26dip"

        android:layout_toRightOf="@+id/artwork"

        android:textAppearance="?android:attr/textAppearanceMedium"
        android:gravity="bottom"
        android:text="Sometime Around Midnight" /&gt;
        
    &lt;ImageView
        android:id="@id/artwork"
        android:layout_width="56dip"
        android:layout_height="56dip"
        android:layout_gravity="center_vertical"

        android:src="@drawable/artwork" /&gt;
        
&lt;/RelativeLayout&gt;</pre><p>This code builds a very simple layout&mdash;an image on the left with two lines of text stacked vertically. This XML layout is perfectly fine and contains no errors. Unfortunately, Android 1.5's RelativeLayout is incapable of rendering it correctly, as shown in the screenshot below.</p><p style="text-align: left;"><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_2fx9rdhqc_b" style="width: 320px; height: 480px;"></p><p>The problem is that this layout uses forward references. For instance, the "band" TextView is positioned below the "track" TextView but "track" is declared after "band" and, in Android 1.5, RelativeLayout does not know how to handle this case. Now look at the exact same layout running on Android 1.6:</p><p style="text-align: left;"><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_3dcwcmnfj_b" style="width: 320px; height: 480px;"></p><p>As you can see Android 1.6 is now better able to handle forward reference. The result on screen is exactly what you would expect when writing the layout.</p><h3>Easier click listeners</h3><p>Setting up a click listener on a button is very common task, but it requires quite a bit of boilerplate code:</p><pre>findViewById(R.id.myButton).setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        // Do stuff
    }
});</pre><p>One way to reduce the amount of boilerplate is to share a single click listener between several buttons. While this technique reduces the number of classes, it still requires a fair amount of code and it still requires giving each button an id in your XML layout file:</p><pre>View.OnClickListener handler = View.OnClickListener() {
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.myButton: // doStuff
                break;
            case R.id.myOtherButton: // doStuff
                break;
        }
    }
}

findViewById(R.id.myButton).setOnClickListener(handler);
findViewById(R.id.myOtherButton).setOnClickListener(handler);</pre><p>With Android 1.6, none of this is necessary. All you have to do is declare a public method in your Activity to handle the click (the method <i>must</i> have one View argument):</p><pre>class MyActivity extends Activity {
    public void myClickHandler(View target) {
        // Do stuff
    }
}</pre><p>And then reference this method from your XML layout:</p><pre>&lt;Button android:onClick="myClickHandler" /&gt;</pre><p>This new feature reduces both the amount of Java and XML you have to write, leaving you more time to concentrate on your application.</p><p>The Android team is committed to helping you write applications in the easiest and most efficient way possible. We hope you find these improvements useful and we're excited to see your applications on Android Market.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2669477647071983497?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/ui-framework-changes-in-android-1-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Support for additional screen resolutions and densities in Android</title>
		<link>https://googledata.org/google-android/support-for-additional-screen-resolutions-and-densities-in-android/</link>
		<comments>https://googledata.org/google-android/support-for-additional-screen-resolutions-and-densities-in-android/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 01:53:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[You may have heard that one of the key changes introduced in Android 1.6 is support for new screen sizes.  This is one of the things that has me very excited about Android 1.6 since it means Android will start becoming available on so many more devices...]]></description>
				<content:encoded><![CDATA[<p>You may have heard that <a href="http://android-developers.blogspot.com/2009/09/android-16-sdk-is-here.html">one of the key changes</a> introduced in Android 1.6 is support for new screen sizes.  This is one of the things that has me very excited about Android 1.6 since it means Android will start becoming available on so many more devices. However, as a developer, I know this also means a bit of additional work. That's why we've spent quite a bit of time making it as easy as possible for you to update your apps to work on these new screen sizes.</p><p>To date, all Android devices (such as the T-Mobile G1 and Samsung I7500, among others) have had HVGA (320x480) screens. The essential change in Android 1.6 is that we've expanded support to include three different classes of screen sizes:</p><ul><li>small: devices with a screen size smaller than the T-Mobile G1 or Samsung I7500, for example the recently announced HTC Tattoo</li><li>normal: devices with a screen size roughly the same as the G1 or I7500.</li><li>large: devices with a screen size larger than the G1 or I7500 (such as a tablet-style device.)</li></ul><p>Any given device will fall into one of those three groups.  As a developer, you can control if and how your app appears to devices in each group by using a few tools we've introduced in the Android framework APIs and SDK.  <a href="http://d.android.com/guide/practices/screens_support.html">The documentation at the developer site</a> describes each of these tools in detail, but here they are in a nutshell:</p><ul><li>new attributes in AndroidManifest for an application to specify what kind of screens it supports,</li><li>framework-level support for using image drawables/layouts correctly regardless of screen size,</li><li>a compatibility mode for existing applications, providing a pseudo-HVGA environment, and descriptions of compatible device resolutions and minimum diagonal sizes.</li></ul><p>The documentation also provides a quick checklist and testing tips for developers to ensure their apps will run correctly on devices of any screen size.</p><p>Once you've upgraded your app using Android 1.6 SDK, you'll need to make sure your app is only available to users whose phones can properly run it.  To help you with that, we've also added some new tools to Android Market.</p><p>Until the next time you upload a new version of your app to Android Market, we will assume that it works for normal-class screen sizes. This means users with normal-class and large-class screens will have access to these apps. Devices with "large" screens simply run these apps in a compatibility mode, which simulates an HVGA environment on the larger screen.</p><p>Devices with small-class screens, however, will only be shown apps which explicitly declare (via the AndroidManifest) that they will run properly on small screens.  In our studies, we found that "squeezing" an app designed for a larger screen onto a smaller screen often produces a bad result. To prevent users with small screens from getting a bad impression of your app (and reviewing it negatively!), Android Market makes sure that they can't see it until you upload a new version that declares itself compatible.</p><p>We expect small-class screens, as well as devices with additional resolutions in <a href="http://d.android.com/guide/practices/screens_support.html">Table 1 in the developer document</a> to hit the market in time for the holiday season. Note that not all devices will be upgraded to Android 1.6 at the same time.  There will be significant number of users still with Android 1.5 devices. To use the same apk to target Android 1.5 devices and Android 1.6 devices, build your apps using Android 1.5 SDK and test your apps on both Android 1.5 and 1.6 system images to make sure they continue to work well on both types of devices. If you want to target small-class devices like HTC Tattoo, please build your app using the Android 1.6 SDK. Note that if your application requires Android 1.6 features, but does not support a screen class, you need to set the appropriate attributes to false. To use optimized assets for normal-class, high density devices like WVGA, or for low density devices please use the Android 1.6 SDK.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8010134788877108883?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/support-for-additional-screen-resolutions-and-densities-in-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gestures on Android 1.6</title>
		<link>https://googledata.org/google-android/gestures-on-android-1-6/</link>
		<comments>https://googledata.org/google-android/gestures-on-android-1-6/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 17:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Touch screens are a great way to interact with applications on mobile devices. With a touch screen, users can easily tap, drag, fling, or slide to quickly perform actions in their favorite applications. But it's not always that easy for developers. Wit...]]></description>
				<content:encoded><![CDATA[<p>Touch screens are a great way to interact with applications on mobile devices. With a touch screen, users can easily tap, drag, fling, or slide to quickly perform actions in their favorite applications. But it's not always that easy for developers. With Android, it's easy to recognize simple actions, like a swipe, but it's much more difficult to handle complicated gestures, which also require developers to write a lot of code. That's why we have decided to introduce a new gestures API in Android 1.6. This API, located in the new package <code>android.gesture</code>, lets you store, load, draw and recognize gestures. In this post I will show you how you can use the <code>android.gesture</code> API in your applications. Before going any further, you should download the <a href="http://code.google.com/p/apps-for-android/downloads/detail?name=GesturesDemos.zip&can=2&q=#makechanges" >source code of the examples</a>.</p><h3>Creating a gestures library</h3><p>The Android 1.6 SDK comes with a new application pre-installed on the emulator, called Gestures Builder. You can use this application to create a set of pre-defined gestures for your own application. It also serves as an example of how to let the user define his own gestures in your applications. You can find the source code of Gestures Builders in the samples directory of Android 1.6. In our example we will use Gestures Builder to generate a set of gestures for us (make sure to create an AVD with an SD card image to use Gestures Builder.)  The screenshot below shows what the application looks like after adding a few gestures:</p><p><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_5d97vb6ft_b" style="width: 320px; height: 480px;"></p><p>As you can see, a gesture is always associated with a name. That name is very important because it identifies each gesture within your application. The names do not have to be unique. Actually it can be very useful to have several gestures with the same name to increase the precision of the recognition. Every time you add or edit a gesture in the Gestures Builder, a file is generated on the emulator's SD card, <code>/sdcard/gestures</code>. This file contains the description of all the gestures, and you will need to package it inside your application inside the resources directory, in <code>/res/raw</code>.</p><h3>Loading the gestures library</h3><p>Now that you have a set of pre-defined gestures, you must load it inside your application. This can be achieved in several ways but the easiest is to use the <code>GestureLibraries</code> class:</p><pre class="prettyprint">mLibrary = GestureLibraries.fromRawResource(this, R.raw.spells);
if (!mLibrary.load()) {
    finish();
}</pre><p>In this example, the gesture library is loaded from the file <code>/res/raw/spells</code>. You can easily load libraries from other sources, like the SD card, which is very important if you want your application to be able to save the library; a library loaded from a raw resource is read-only and cannot be modified. The following diagram shows the structure of a library:</p><p><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_6dvdb38c9_b" style="width: 600px; height: 512px;"></p><h3>Recognizing gestures</h3><p>To start recognizing gestures in your application, all you have to do is add a <code>GestureOverlayView</code> to your XML layout:</p><pre>&lt;android.gesture.GestureOverlayView
    android:id=&quot;@+id/gestures&quot;
    android:layout_width=&quot;fill_parent&quot; 
    android:layout_height=&quot;0dip&quot;
    android:layout_weight=&quot;1.0&quot; /&gt;</pre><p>Notice that the <code>GestureOverlayView</code> is not part of the usual android.widget package. Therefore, you must use its fully qualified name. A gesture overlay acts as a simple drawing board on which the user can draw his gestures. You can tweak several visual properties, like the color and the width of the stroke used to draw gestures, and register various listeners to follow what the user is doing. The most commonly used listener is <code>GestureOverlayView.OnGesturePerformedListener</code> which fires whenever a user is done drawing a gesture:</p><pre>GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
gestures.addOnGesturePerformedListener(this);</pre><p>When the listener fires, you can ask the <code>GestureLibrary</code> to try to recognize the gesture. In return, you will get a list of Prediction instances, each with a name - the same name you entered in the Gestures Builder - and a score. The list is sorted by descending scores; the higher the score, the more likely the associated gesture is the one the user intended to draw. The following code snippet demonstrates how to retrieve the name of the first prediction:</p><pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    ArrayList<Prediction> predictions = mLibrary.recognize(gesture);

    // We want at least one prediction
    if (predictions.size() > 0) {
        Prediction prediction = predictions.get(0);
        // We want at least some confidence in the result
        if (prediction.score > 1.0) {
            // Show the spell
            Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
        }
    }
}</pre><p>In this example, the first prediction is taken into account only if it's score is greater than 1.0. The threshold you use is entirely up to you but know that scores lower than 1.0 are typically poor matches. And this is all the code you need to create a simple application that can recognize pre-defined gestures (see the source code of the project GesturesDemo):</p><p><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_7jv4jj7ck_b" style="width: 320px; height: 480px;"></p><h3>Gestures overlay</h3><p>In the example above, the <code>GestureOverlayView</code> was used as a normal view, embedded inside a <font class="Apple-style-span" face="'Courier New'">LinearLayout</font>. However, as its name suggests, it can also be used as an overlay on top of other views. This can be useful to recognize gestures in a game or just anywhere in the UI of an application. In the second example, called GesturesListDemo, we'll create an overlay on top of a list of contacts. We start again in Gestures Builder to create a new set of pre-defined gestures:</p><p><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_88zfgzrgv_b" style="width: 320px; height: 480px;"></p><p>And here is what the XML layout looks like:</p><pre>&lt;android.gesture.GestureOverlayView
    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:id=&quot;@+id/gestures&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;fill_parent&quot;
    
    android:gestureStrokeType=&quot;multiple&quot;
    android:eventsInterceptionEnabled=&quot;true&quot;
    android:orientation=&quot;vertical&quot;&gt;

    &lt;ListView
        android:id=&quot;@android:id/list&quot;  
        android:layout_width=&quot;fill_parent&quot; 
        android:layout_height=&quot;fill_parent&quot;  /&gt;

&lt;/android.gesture.GestureOverlayView&gt;</pre><p>In this application, the gestures view is an overlay on top of a regular ListView. The overlay also specifies a few properties that we did not need before:</p><ul><li><code>gestureStrokeType</code>: indicates whether we want to recognize gestures made of a single stroke or multiple strokes. Since one of our gestures is the "+" symbol, we need multiple strokes</li><li><code>eventsInterceptionEnabled</code>: when set to true, this property tells the overlay to steal the events from its children as soon as it knows the user is really drawing a gesture. This is useful when there's a scrollable view under the overlay, to avoid scrolling the underlying child as the user draws his gesture </li><li><code>orientation</code>: indicates the scroll orientation of the views underneath. In this case the list scrolls vertically, which means that any horizontal gestures (like <code>action_delete</code>) can immediately be recognized as a gesture. Gestures that start with a vertical stroke must contain at least one horizontal component to be recognized. In other words, a simple vertical line cannot be recognized as a gesture since it would conflict with the list's scrolling.</li></ul><p>The code used to load and set up the gestures library and overlay is exactly the same as before. The only difference is that we now check the name of the predictions to know what the user intended to do:</p><pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    ArrayList&lt;Prediction&gt; predictions = mLibrary.recognize(gesture);
    if (predictions.size() &gt; 0 &amp;&amp; predictions.get(0).score &gt; 1.0) {
        String action = predictions.get(0).name;
        if (&quot;action_add&quot;.equals(action)) {
            Toast.makeText(this, &quot;Adding a contact&quot;, Toast.LENGTH_SHORT).show();
        } else if (&quot;action_delete&quot;.equals(action)) {
            Toast.makeText(this, &quot;Removing a contact&quot;, Toast.LENGTH_SHORT).show();
        } else if (&quot;action_refresh&quot;.equals(action)) {
            Toast.makeText(this, &quot;Reloading contacts&quot;, Toast.LENGTH_SHORT).show();
        }
    }
}</pre><p>The user is now able to draw his gestures on top of the list without interfering with the scrolling:</p><p><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_9g5mpqzfg_b" style="width: 320px; height: 480px;"></p><p>The overlay even gives visual clues as to whether the gesture is considered valid for recognition. In the case of a vertical overlay, for instance, a single vertical stroke cannot be recognized as a gesture and is therefore drawn with a translucent color:</p><p><img src="http://docs.google.com/a/google.com/File?id=cf49fh6b_10ctk8g384_b" style="width: 320px; height: 480px;"></p><h3>It's your turn</h3><p>Adding support for gestures in your application is easy and can be a valuable addition. The gestures API does not even have to be used to recognize complex shapes; it will work equally well to recognize simple swipes. We are very excited by the possibilities the gestures API offers, and we're eager to see what cool applications the community will create with it.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7511647241234048472?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/gestures-on-android-1-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Painless threading</title>
		<link>https://googledata.org/google-android/painless-threading/</link>
		<comments>https://googledata.org/google-android/painless-threading/#comments</comments>
		<pubDate>Wed, 06 May 2009 16:30:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Whenever you first start an Android application, a thread called "main" is automatically created. The main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widgets and this includ...]]></description>
				<content:encoded><![CDATA[<p>Whenever you first start an Android application, a thread called "main" is automatically created. The main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widgets and this includes the drawing events. It is also the thread you interact with Android widgets on. For instance, if you touch the a button on screen, the UI thread dispatches the touch event to the widget which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget to redraw itself.</p><p>This single thread model can yield poor performance in Android applications that do not consider the implications. Since everything happens on a single thread performing long operations, like network access or database queries, on this thread will block the whole user interface. No event can be dispatched, including drawing events, while the long operation is underway. From the user's perspective, the application appears hung. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "<a href="http://developer.android.com/guide/practices/design/responsiveness.html">application not responding</a>" (ANR) dialog.</p><p>If you want to see how bad this can look, write a simple application with a button that invokes <code>Thread.sleep(2000)</code> in its <a href="http://developer.android.com/reference/android/view/View.OnClickListener.html">OnClickListener</a>. The button will remain in its pressed state for about 2 seconds before going back to its normal state. When this happens, it is very easy for the user to <em>perceive</em> the application as slow.</p><p>Now that you know you <em>must</em> avoid lengthy operations on the UI thread, you will probably use extra threads (<em>background</em> or <em>worker</em> threads) to perform these operations, and rightly so. Let's take the example of a click listener downloading an image over the network and displaying it in an <a href="http://developer.android.com/reference/android/widget/ImageView.html">ImageView</a>:</p><pre class="prettyprint">public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      Bitmap b = loadImageFromNetwork();
      mImageView.setImageBitmap(b);
    }
  }).start();
}</pre><p>At first, this code seems to be a good solution to your problem, as it does not block the UI thread. Unfortunately, it violates the single thread model: the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread. In this piece of code, the <code>ImageView</code> is manipulated on a worker thread, which can cause really weird problems. Tracking down and fixing such bugs can be difficult and time-consuming.</p><p>Android offers several ways to access the UI thread from other threads. You may already be familiar with some of them but here is a comprehensive list:</p><ul><li><a href="http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)">Activity.runOnUiThread(Runnable)</a></li><li><a href="http://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable)">View.post(Runnable)</a></li><li><a href="http://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable,%20long)">View.postDelayed(Runnable, long)</a></li><li><a href="http://developer.android.com/reference/android/os/Handler.html">Handler</a></li></ul><p>Any of these classes and methods could be used to correct our previous code example:</p><pre class="prettyprint">public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      final Bitmap b = loadImageFromNetwork();
      mImageView.post(new Runnable() {
        public void run() {
          mImageView.setImageBitmap(b);
        }
      });
    }
  }).start();
}</pre><p>Unfortunately, these classes and methods also tend to make your code more complicated and more difficult to read. It becomes even worse when your implement complex operations that require frequent UI updates. To remedy this problem, Android 1.5 offers a new utility class, called <a href="http://developer.android.com/reference/android/os/AsyncTask.html">AsyncTask</a>, that simplifies the creation of long-running tasks that need to communicate with the user interface.</p><p><a href="http://developer.android.com/reference/android/os/AsyncTask.html">AsyncTask</a> is also available for Android 1.0 and 1.1 under the name <a href="http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/util/UserTask.java">UserTask</a>. It offers the exact same API and all you have to do is copy its source code in your application.</p><p>The goal of <code>AsyncTask</code> is to take care of thread management for you. Our previous example can easily be rewritten with <code>AsyncTask</code>:</p><pre class="prettyprint">public void onClick(View v) {
  new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
     protected Bitmap doInBackground(String... urls) {
         return loadImageFromNetwork(urls[0]);
     }

     protected void onPostExecute(Bitmap result) {
         mImageView.setImageBitmap(result);
     }
 }</pre><p>As you can see, <code>AsyncTask</code> <em>must</em> be used by subclassing it. It is also very important to remember that an <code>AsyncTask</code> instance has to be created on the UI thread and can be executed only once. You can read the <a href="http://developer.android.com/reference/android/os/AsyncTask.html">AsyncTask documentation</a> for a full understanding on how to use this class, but here is a quick overview of how it works:</p><ul><li>You can specify the type, using generics, of the parameters, the progress values and the final value of the task</li><li>The method <a href="http://developer.android.com/reference/android/os/AsyncTask.html#doInBackground(Params...)">doInBackground()</a> executes automatically on a worker thread</li><li><a href="http://developer.android.com/reference/android/os/AsyncTask.html#onPreExecute()">onPreExecute()</a>, <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)">onPostExecute()</a> and <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)">onProgressUpdate()</a> are all invoked on the UI thread</li><li>The value returned by <a href="http://developer.android.com/reference/android/os/AsyncTask.html#doInBackground(Params...)">doInBackground()</a> is sent to <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)">onPostExecute()</a></li><li>You can call <a href="http://developer.android.com/reference/android/os/AsyncTask.html#publishProgress(Progress...)">publishProgress()</a> at anytime in <a href="http://developer.android.com/reference/android/os/AsyncTask.html#doInBackground(Params...)">doInBackground()</a> to execute <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)">onProgressUpdate()</a> on the UI thread</li><li>You can cancel the task at any time, from any thread</li></ul><p>In addition to the official documentation, you can read several complex examples in the source code of Shelves (<a href="http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/activity/ShelvesActivity.java">ShelvesActivity.java</a> and <a href="http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/activity/AddBookActivity.java">AddBookActivity.java</a>) and Photostream (<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/LoginActivity.java">LoginActivity.java</a>, <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java">PhotostreamActivity.java</a> and <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/ViewPhotoActivity.java">ViewPhotoActivity.java</a>). I highly recommend reading the source code of <a href="http://code.google.com/p/shelves/">Shelves</a> to see how to persist tasks across configuration changes and how to cancel them properly when the activity is destroyed.</p><p>Regardless of whether or not you use <a href="http://developer.android.com/reference/android/os/AsyncTask.html">AsyncTask</a>, always remember these two rules about the single thread model: do not block the UI thread and make sure the Android UI toolkit is only accessed on the UI thread. <a href="http://developer.android.com/reference/android/os/AsyncTask.html">AsyncTask</a> just makes it easier to do both of these things.</p><p>If you want to learn more cool techniques, come join us at <a href="http://code.google.com/events/io/">Google I/O</a>. Members of the Android team will be there to give a <a href="http://code.google.com/events/io/sessions.html#android">series of in-depth technical sessions</a> and answer all your questions.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2021514946948968931?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/painless-threading/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Drawable mutations</title>
		<link>https://googledata.org/google-android/drawable-mutations/</link>
		<comments>https://googledata.org/google-android/drawable-mutations/#comments</comments>
		<pubDate>Mon, 04 May 2009 23:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Android's drawables are extremely useful to easily build applications. A Drawable is a pluggable drawing container that is usually associated with a View. For instance, a BitmapDrawable is used to display images, a ShapeDrawable to draw shapes and grad...]]></description>
				<content:encoded><![CDATA[<p>Android's drawables are extremely useful to easily build applications. A <a href="http://developer.android.com/reference/android/graphics/drawable/Drawable.html">Drawable</a> is a pluggable drawing container that is usually associated with a View. For instance, a <a href="http://developer.android.com/reference/android/graphics/drawable/BitmapDrawable.html">BitmapDrawable</a> is used to display images, a <a href="http://developer.android.com/reference/android/graphics/drawable/ShapeDrawable.html">ShapeDrawable</a> to draw shapes and gradients, etc. You can even combine them to create complex renderings.</p><p>Drawables allow you to easily customize the rendering of the widgets without subclassing them. As a matter of fact, they are so convenient that most of the default Android apps and widgets are built using drawables; there are about 700 drawables used in the core Android framework. Because drawables are used so extensively throughout the system, Android optimizes them when they are loaded from resources. For instance, every time you create a <a href="http://developer.android.com/reference/android/widget/Button.html">Button</a>, a new drawable is loaded from the framework resources (<code>android.R.drawable.btn_default</code>). This means all buttons across all the apps use a different drawable instance as their background. However, all these drawables share a common state, called the "constant state." The content of this state varies according to the type of drawable you are using, but it usually contains all the properties that can be defined by a resource. In the case of a button, the constant state contains a bitmap image. This way, all buttons across all applications share the same bitmap, which saves a lot of memory.</p><p>The following diagram shows what entities are created when you assign the same image resource as the background of two different views. As you can see, two drawables are created but they both share the same constant state, hence the same bitmap:</p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 307px; height: 400px;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/Sf0SgfbQcVI/AAAAAAAAAD8/xKcxTQCAxn0/s400/shared_states.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5331437883277472082" /><p>This state sharing feature is great to avoid wasting memory but it can cause problems when you try to modify the properties of a drawable. Imagine an application with a list of books. Each book has a star next to its name, totally opaque when the user marks the book as a favorite, and translucent when the book is not a favorite. To achieve this effect, you would probably write the following code in your list adapter's <code>getView()</code> method:</p><pre>Book book = ...;
TextView listItem = ...;

listItem.setText(book.getTitle());

Drawable star = context.getResources().getDrawable(R.drawable.star);
if (book.isFavorite()) {
  star.setAlpha(255); // opaque
} else {
  star.setAlpha(70); // translucent
}</pre><p>Unfortunately, this piece of code yields a rather strange result, all the drawables have the same opacity:</p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://4.bp.blogspot.com/_9l0GmPwgCzk/Sf0TgPCgubI/AAAAAAAAAEE/xP3FxmTfOgg/s400/all_drawables_changed.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5331438978390342066" /><p>This result is explained by the constant state. Even though we are getting a new drawable instance for each list item, the constant state remains the same and, in the case of BitmapDrawable, the opacity is part of the constant state. Thus, changing the opacity of one drawable instance changes the opacity of all the other instances. Even worse, working around this issue was not easy with Android 1.0 and 1.1.</p><p>Android 1.5 offers a very way to solve this issue with a the new <a href="http://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate()">mutate() method</a>. When you invoke this method on a drawable, the constant state of the drawable is duplicated to allow you to change any property without affecting other drawables. Note that bitmaps are still shared, even after mutating a drawable. The diagram below shows what happens when you invoke <code>mutate()</code> on a drawable:</p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 307px; height: 400px;" src="http://3.bp.blogspot.com/_9l0GmPwgCzk/Sf0UkFtP6PI/AAAAAAAAAEM/2ywQ5XZlpP4/s400/mutated_states.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5331440144116345074" /><p>Let's update our previous piece of code to make use of <code>mutate()</code>:</p><pre>Drawable star = context.getResources().getDrawable(R.drawable.star);
if (book.isFavorite()) {
  star.mutate().setAlpha(255); // opaque
} else {
  star. mutate().setAlpha(70); // translucent
}</pre><p>For convenience, <code>mutate()</code> returns the drawable itself, which allows to chain method calls. It does not however create a new drawable instance. With this new piece of code, our application now behaves correctly:</p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://4.bp.blogspot.com/_9l0GmPwgCzk/Sf0VHyzBWlI/AAAAAAAAAEU/9wdeSyWHo4M/s400/correct_drawables.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5331440757515573842" /><p>If you want to learn more cool techniques, come join us at <a href="http://code.google.com/events/io/">Google I/O</a>. Members of the Android team will be there to give a <a href="http://code.google.com/events/io/sessions.html#android">series of in-depth technical sessions</a> and answer all your questions.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2432088149258057512?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/drawable-mutations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Live folders</title>
		<link>https://googledata.org/google-android/live-folders/</link>
		<comments>https://googledata.org/google-android/live-folders/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 16:30:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Live folders have been introduced in Android 1.5 and let you display any source of data on the Home screen without forcing the user to launch an application. A live folder is simply a real-time view of a ContentProvider. As such, a live folder can be u...]]></description>
				<content:encoded><![CDATA[<p>Live folders have been introduced in Android 1.5 and let you display any source of data on the Home screen without forcing the user to launch an application. A live folder is simply a real-time view of a <a href="http://developer.android.com/reference/android/content/ContentProvider.html">ContentProvider</a>. As such, a live folder can be used to display all your contacts, your bookmarks, your email, your playlists, an RSS feed, etc. The possibilities are endless! Android 1.5 ships with a few stock live folders to display your contacts. For instance, the screenshot below shows the content of the live folders that displays all my contacts with a phone number:</p><p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/SeAeChYUuII/AAAAAAAAADk/ZrYbwiYT1II/s400/contacts.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5323287788220889218" /></p><p>If a contacts sync happens in the background while I'm browsing this live folder, I will see the change happen in real-time. Live folders are not only useful but it's also very easy to modify your application to make it provider a live folder. In this article, I will show you how to add a live folder to the <a href="http://code.google.com/p/shelves">Shelves</a> application. You can download its source code and modify it by following my instructions to better understand how live folders work.</p><p>To give the user the option to create a new live folder, you first need to create a new activity with an intent filter who action is <code>android.intent.action.CREATE_LIVE_FOLDER</code>. To do so, simply open <code>AndroidManifest.xml</code> and add something similar to this:</p><pre>&lt;activity
    android:name=".activity.BookShelfLiveFolder"
    android:label="BookShelf"&gt;
    &lt;intent-filter&gt;
        &lt;action android:name="android.intent.action.CREATE_LIVE_FOLDER" /&gt;
        &lt;category android:name="android.intent.category.DEFAULT" /&gt;
    &lt;/intent-filter&gt;
&lt;/activity&gt;</pre><p>The label and icon of this activity are what the user will see on the Home screen when choosing a live folder to create:</p><p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/SeAfVu4IazI/AAAAAAAAADs/ZZYmkwOOYTk/s400/device.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5323289217773103922" /></p><p>Since you just need an intent filter, it is possible, and sometimes advised, to reuse an existing activity. In the case of Shelves, we will create a new activity, <code>org.curiouscreature.android.shelves.activity.BookShelfLiveFolder</code>. The role of this activity is to send an <code>Intent</code> result to Home containing the description of the live folder: its name, icon, display mode and content URI. The content URI is very important as it describes what <code>ContentProvider</code> will be used to populate the live folder. The code of the activity is very simple as you can see here:</p><pre>public class BookShelfLiveFolder extends Activity {
    public static final Uri CONTENT_URI = Uri.parse("content://shelves/live_folders/books");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Intent intent = getIntent();
        final String action = intent.getAction();

        if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
            setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
                    "Books", R.drawable.ic_live_folder));
        } else {
            setResult(RESULT_CANCELED);
        }

        finish();
    }

    private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) {
        final Intent intent = new Intent();

        intent.setData(uri);
        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
                Intent.ShortcutIconResource.fromContext(context, icon));
        intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);

        return intent;
    }
}</pre><p>This activity, when invoked with the<code>ACTION_CREATE_LIVE_FOLDER</code> intent, returns an intent with a URI, <code>content://shelves/live_folders/books</code>, and three extras to describe the live folder. There are other extras and constants you can use and you should refer to the documentation of <code>android.provider.LiveFolders</code> for more details. When Home receives this intent, a new live folder is created on the user's desktop, with the name and icon you provided. Then, when the user clicks on the live folder to open it, Home queries the content provider referenced by the provided URI.</p><p>Live folders' content providers must obey specific naming rules. The <code>Cursor</code> returned by the <code>query()</code> method must have at least two columns named <code>LiveFolders._ID</code> and <code>LiveFolders.NAME</code>. The first one is the unique identifier of each item in the live folder and the second one is the name of the item. There are other column names you can use to specify an icon, a description, the intent to associate with the item (fired when the user clicks that item), etc. Again, refer to the documentation of <code>android.provider.LiveFolders</code> for more details.</p><p>In our example, all we need to do is modify the existing provider in Shelves called <code>org.curiouscreature.android.shelves.provider.BooksProvider</code>. First, we need to modify the <code>URI_MATCHER</code> to recognize our <code>content://shelves/live_folders/books</code> content URI:</p><pre>private static final int LIVE_FOLDER_BOOKS = 4;
// ...
URI_MATCHER.addURI(AUTHORITY, "live_folders/books", LIVE_FOLDER_BOOKS);</pre><p>Then we need to create a new projection map for the cursor. A projection map can be used to "rename" columns. In our case, we will replace <code>BooksStore.Book._ID</code>, <code>BooksStore.Book.TITLE</code> and <code>BooksStore.Book.AUTHORS</code> with <code>LiveFolders._ID</code>, <code>LiveFolders.TITLE</code> and <code>LiveFolders.DESCRIPTION</code>:</p><pre>private static final HashMap<String, String> LIVE_FOLDER_PROJECTION_MAP;
static {
    LIVE_FOLDER_PROJECTION_MAP = new HashMap<String, String>();
    LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders._ID, BooksStore.Book._ID +
            " AS " + LiveFolders._ID);
    LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.NAME, BooksStore.Book.TITLE +
            " AS " + LiveFolders.NAME);
    LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.DESCRIPTION, BooksStore.Book.AUTHORS +
            " AS " + LiveFolders.DESCRIPTION);
}</pre><p>Because we are providing a title and a description for each row, Home will automatically display each item of the live folder with two lines of text. Finally, we implement the <code>query()</code> method by supplying our projection map to the SQL query builder:</p><pre>public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {

    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

    switch (URI_MATCHER.match(uri)) {
        // ...
        case LIVE_FOLDER_BOOKS:
            qb.setTables("books");
            qb.setProjectionMap(LIVE_FOLDER_PROJECTION_MAP);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
    }

    SQLiteDatabase db = mOpenHelper.getReadableDatabase();
    Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, BooksStore.Book.DEFAULT_SORT_ORDER);
    c.setNotificationUri(getContext().getContentResolver(), uri);

    return c;
}</pre><p>You can now compile and deploy the application, go to the Home screen and try to add a live folder. I added a books live folder to my Home screen and when I open it, I can see the list of all of my books, with their titles and authors, and all it took was a few lines of code:</p><p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://2.bp.blogspot.com/_9l0GmPwgCzk/SeAjRo5pECI/AAAAAAAAAD0/zfgdXMfQ2LE/s400/device.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5323293545495859234" /></p><p>The live folders API is extremely simple and relies only on intents and content URI. If you want to see more examples of live folders implementation, you can read the source code of the <a href="http://android.git.kernel.org/?p=platform/packages/apps/Contacts.git;a=tree;h=refs/heads/cupcake;hb=cupcake">Contacts application</a> and of the <a href="http://android.git.kernel.org/?p=platform/packages/providers/ContactsProvider.git;a=tree;h=refs/heads/cupcake;hb=cupcake">Contacts provider</a>.</p><p>You can also download the result of our exercise, the <a href="http://jext.free.fr/CupcakeShelves.zip">modified version of Shelves with live folders support</a>.</p><hr style="align: center; width: 66%; border: none 0; border-top: 1px dashed #000;" /><p><em>Learn about Android 1.5 and more at <a href="http://code.google.com/events/io/">Google I/O</a>. Members of the Android team will be there to give a series of <a href="http://code.google.com/events/io/sessions.html#android">in-depth technical sessions</a> and to field your toughest questions.</em></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8270401365504867796?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/live-folders/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>UI framework changes in Android 1.5</title>
		<link>https://googledata.org/google-android/ui-framework-changes-in-android-1-5/</link>
		<comments>https://googledata.org/google-android/ui-framework-changes-in-android-1-5/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 06:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[On Monday, we released an early look at the Android 1.5 SDK. Not only does this platform update contain numerous new features, APIs, and bug fixes, but Android 1.5 also brings a new default look for the Android UI framework. After Android 1.0 and 1.1, ...]]></description>
				<content:encoded><![CDATA[<p>On Monday, we released an <a href="http://developer.android.com/sdk/preview/">early look at the Android 1.5 SDK</a>. Not only does this platform update contain <a href="http://developer.android.com/sdk/preview/features.html">numerous new features</a>, APIs, and bug fixes, but Android 1.5 also brings a new default look for the Android UI framework. After Android 1.0 and 1.1, our designers worked hard to refine and polish the appearance of the system. The screenshots below show the same activity (creating a new contact) on Android 1.1 and Android 1.5:</p><p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 277px;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/Sd-YpjNpaEI/AAAAAAAAADM/8G0-yahXrSo/s400/android.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5323141124169754690" /></p><p>You can see in this example that the buttons and checkboxes have a new appearance. Even though these changes do not affect binary nor source compatibility, they might still break the UI of your apps. As part of the UI refresh, the minimum size of some of the widgets has changed. For instance, Android 1.1 buttons have a minimum size of 44x48 pixels whereas Android 1.5 buttons now have a minimum size of 24x48 pixels. The image below compares the sizes of Android 1.1 buttons with Android 1.5 buttons:</p><p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 100px; height: 130px;" src="http://4.bp.blogspot.com/_9l0GmPwgCzk/Sd-c0Wvd8eI/AAAAAAAAADU/2X2YwR6Rxvc/s400/buttons.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5323145707847021026" /></p><p>If you rely on the button's minimum size, then the layout of your application may not be the same in Android 1.5 as it was in Android 1.1 because of this change. This would happen for instance if you created a grid of buttons using <code>LinearLayout</code> and relying on the minimum size yielded by <code>wrap_content</code> to align the buttons properly:</p><p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 277px;" src="http://2.bp.blogspot.com/_9l0GmPwgCzk/Sd-e2fnrTlI/AAAAAAAAADc/bgt_QYsnxCs/s400/grid.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5323147943613255250" /></p><p>This layout could easily be fixed by using the <code>android:layout_weight</code> attribute or by replacing the <code>LinearLayout</code> containers with a <code>TableLayout</code>.</p><p>This example is probably the worst-case UI issue you may encounter when running your application on Android 1.5.  Other changes introduced in Android 1.5, especially bug fixes in the layout views, may also impact your application&mdash;especially if it is relying on faulty/buggy behavior of the UI framework.</p><p>If you encounter issues when running your application on Android 1.5, please <a href="http://developer.android.com/community/index.html">join us on the Google groups or IRC</a> so that we and the Android community can help you fix your application.</p><p>Happy coding!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-7891860032686230519?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/ui-framework-changes-in-android-1-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Layout Tricks #3: Optimize with stubs</title>
		<link>https://googledata.org/google-android/android-layout-tricks-3-optimize-with-stubs/</link>
		<comments>https://googledata.org/google-android/android-layout-tricks-3-optimize-with-stubs/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 21:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Sharing and reusing layouts is very easy with Android thanks to the &#60;include /&#62; tag, sometimes even too easy and you might end up with user interfaces that contain a large number of views, some of which are rarely used. Thankfully, Android offers...]]></description>
				<content:encoded><![CDATA[<p>Sharing and reusing layouts is very easy with Android thanks to the <a href="http://www.curious-creature.org/2009/02/25/android-layout-trick-2-include-to-reuse/">&lt;include /&gt;</a> tag, sometimes even too easy and you might end up with user interfaces that contain a large number of views, some of which are rarely used. Thankfully, Android offers a very special widget called <a href="http://d.android.com/reference/android/view/ViewStub.html">ViewStub</a>, which brings you all the benefits of the <code>&lt;include /&gt;</code> without polluting your user interface with rarely used views.</p><p>A <code>ViewStub</code> is a dumb and lightweight view. It has no dimension, it does not draw anything and does not participate in the layout in any way. This means a <code>ViewStub</code> is very cheap to inflate and very cheap to keep in a view hierarchy. A <code>ViewStub</code> can be best described as a <em>lazy include</em>. The layout referenced by a <code>ViewStub</code> is inflated and added to the user interface only when you decide so.</p><p>The following screenshot comes from the <a href="http://code.google/p/shelves">Shelves</a> application. The main purpose of the activity shown in the screenshot is to present the user with a browsable list of books:</p><img style="display:block; margin:0px auto 10px; text-align:center;" src="http://2.bp.blogspot.com/_9l0GmPwgCzk/Sb9CqClYIjI/AAAAAAAAACc/1ijy-Ab7oOE/s1600/viewstub1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5314039375336055346" /><p>The same activity is also used when the user adds or imports new books. During such an operation, Shelves shows extra bits of user interface. The screenshot below shows the progress bar and cancel button that appear at the bottom of the screen during an import:</p><img style="display:block; margin:0px auto 10px; text-align:center;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/Sb9DCwlwvZI/AAAAAAAAACk/ETR67WJ5XTw/s1600/viewstub2.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5314039800002559378" /><p>Because importing books is not a common operation, at least when compared to browsing the list of books, the import panel is originally represented by a <code>ViewStub</code>:</p><img style="display:block; margin:0px auto 10px; text-align:center;" src="http://4.bp.blogspot.com/_9l0GmPwgCzk/Sb9Dh16nq9I/AAAAAAAAACs/5cAKaaUCq84/s1600/viewstub3.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5314040334008167378" /><p>When the user initiates the import process, the <code>ViewStub</code> is inflated and replaced by the content of the layout file it references:</p><img style="display:block; margin:0px auto 10px; text-align:center;;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/Sb9DzlKN-FI/AAAAAAAAAC0/BH9Nv-Z1eqI/s1600/viewstub4.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5314040638747834450" /><p>To use a <code>ViewStub</code> all you need is to specify an <code>android:id</code> attribute, to later inflate the stub, and an <code>android:layout</code> attribute, to reference what layout file to include and inflate. A stub lets you use a third attribute, <code>android:inflatedId</code>, which can be used to override the id of the root of the included file. Finally, the layout parameters specified on the stub will be applied to the roof of the included layout. Here is an example:</p><pre class="prettyprint">&lt;ViewStub
  android:id="@+id/stub_import"
  android:inflatedId="@+id/panel_import"

  android:layout="@layout/progress_overlay"

  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_gravity="bottom" /&gt;</pre><p>When you are ready to inflate the stub, simply invoke the <a href="http://d.android.com/reference/android/view/ViewStub.html#inflate()">inflate()</a> method. You can also simply change the visibility of the stub to <a href="http://d.android.com/reference/android/view/View.html#VISIBLE">VISIBLE</a> or <a href="http://d.android.com/reference/android/view/View.html#INVISIBLE">INVISIBLE</a> and the stub will inflate. Note however that the <code>inflate()</code> method has the benefit of returning the root <code>View</code> of the inflate layout:</p><pre class="prettyprint">((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// or
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();</pre><p>It is very important to remember that after the stub is inflated, the stub is <em>removed</em> from the view hierarchy. As such, it is unnecessary to keep a long-lived reference, for instance in an class instance field, to a <code>ViewStub</code>.</p><p>A <code>ViewStub</code> is a great compromise between ease of programming and efficiency. Instead of inflating views manually and adding them at runtime to your view hierarchy, simply use a <code>ViewStub</code>. It's cheap and easy. The only drawback of <code>ViewStub</code> is that it currently does <em>not</em> support the <a href="http://www.curious-creature.org/2009/03/01/android-layout-tricks-3-optimize-part-1/">&lt;merge /&gt; tag</a>.</p><p>Happy coding!</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8792365559562607541?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-layout-tricks-3-optimize-with-stubs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Window Backgrounds &amp; UI Speed</title>
		<link>https://googledata.org/google-android/window-backgrounds-ui-speed/</link>
		<comments>https://googledata.org/google-android/window-backgrounds-ui-speed/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 16:30:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Some Android applications require to squeeze every bit of performance out of the UI toolkit and there are many ways to do so. In this article, you will discover how to speed up the drawing and the perceived startup time of your activities. Both these t...]]></description>
				<content:encoded><![CDATA[<p>Some Android applications require to squeeze every bit of performance out of the UI toolkit and there are many ways to do so. In this article, you will discover how to speed up the drawing and the <em>perceived</em> startup time of your activities. Both these techniques rely on a single feature, the window's background drawable.</p><p>The term <em>window background</em> is a bit misleading however. When you setup your user interface by calling <code>setContentView()</code> on an <a href="http://d.android.com/reference/android/app/Activity.html">Activity</a>, Android adds your views to the <code>Activity</code>'s window. The window however does not contain only your views, but a few others created for you. The most important one is, in the current implementation used on the T-Mobile G1, the <code>DecorView</code>, highlighted in the view hierarchy below:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/window_background_root.png" alt="A typical Android view hierarchy" /></div><p>The <code>DecorView</code> is the view that actually holds the window's background drawable. Calling <a href="http://d.android.com/reference/android/view/Window.html#setBackgroundDrawable(android.graphics.drawable.Drawable)">getWindow().setBackgroundDrawable()</a> from your <code>Activity</code> changes the background of the window by changing the <code>DecorView</code>'s background drawable. As mentioned before, this setup is very specific to the current implementation of Android and can change in a future version or even on another device.</p><p>If you are using the standard Android themes, a default background drawable is set on your activities. The standard theme currently used on the T-Mobile G1 uses for instance a <a href="http://d.android.com/reference/android/graphics/drawable/ColorDrawable.html">ColorDrawable</a>. For most applications, this background drawable works just fine and can be left alone. It can however impacts your application's drawing performance. Let's take the example of an application that always draws a full screen opaque picture:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/window_background.png" alt="An opaque user interface doesn't need a window background" /></div><p>You can see on this screenshot that the window's background is invisible, entirely covered by an <code>ImageView</code>. This application is setup to redraw as fast as it can and draws at about 44 frames per second, or 22 milliseconds per frame (<strong>note:</strong> the number of frames per second used in this article were obtained on a T-Mobile G1 with my finger on the screen so as to reduce the drawing speed which would otherwise be capped at 60 fps.) An easy way to make such an application draw faster is to <em>remove</em> the background drawable. Since the user interface is entirely opaque, drawing the background is simply wasteful. Removing the background improves the performance quite nicely:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/window_background_null.png" alt="Remove the background for faster drawing" /></div><p>In this new version of the application, the drawing speed went up to 51 frames per second, or 19 milliseconds per frame. The difference of 3 milliseconds per is easily explained by the speed of the memory bus on the T-Mobile G1: it is exactly the time it takes to move the equivalent of a screenful of pixels on the bus. The difference could be even greater if the default background was using a more expensive drawable.</p><p>Removing the window's background can be achieved very easily by using a custom theme. To do so, first create a file called <code>res/values/theme.xml</code> containing the following:</p><pre class="prettyprint">&lt;resources&gt;
    &lt;style name="Theme.NoBackground" parent="android:Theme"&gt;
        &lt;item name="android:windowBackground"&gt;@null&lt;/item&gt;
    &lt;/style&gt;
&lt;/resources&gt;</pre><p>You then need to apply the theme to your activity by adding the attribute <code>android:theme="@style/Theme.NoBackground"</code> to your <code>&lt;activity /&gt;</code> or <code>&lt;application /&gt;</code> tag. This trick comes in very handy for any app that uses a <code>MapView</code>, a <code>WebView</code> or any other full screen opaque view.</p><p><strong>Opaque views and Android</strong>: this optimization is currently necessary because the Android UI toolkit is not smart enough to prevent the drawing of views hidden by opaque children. The main reason why this optimization was not implemented is simply because there are usually very few opaque views in Android applications. This is however something that I definitely plan on implementing as soon as possible and I can only apologize for not having been able to do this earlier.</p><p>Using a theme to change the window's background is also a fantastic way to improve the <em>perceived</em> startup performance of some of your activities. This particular trick can only be applied to activities that use a custom background, like a texture or a logo. The <a href="http://code.google.com/p/shelves">Shelves</a> application is a good example:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/shelves2.png" alt="Textured backgrounds are good candidates for window's background" /></div><p>If this application simply set the wooden background in the XML layout or in <code>onCreate()</code> the user would see the application startup with the default theme and its dark background. The wooden texture would only appear after the inflation of the content view and the first layout/drawing pass. This causes a jarring effect and gives the user the impression that the application takes time to load (which can actually be the case.) Instead, the application defines the wooden background in a theme, picked up by the system as soon as the application starts. The user never sees the default theme and gets the impression that the application is up and running right away. To limit the memory and disk usage, the background is a tiled texture defined in <code>res/drawable/background_shelf.xml</code>:</p><pre class="prettyprint">&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/shelf_panel"
    android:tileMode="repeat" /&gt;</pre><p>This drawable is simply referenced by the theme:</p><pre class="prettyprint">&lt;resources&gt;
    &lt;style name="Theme.Shelves" parent="android:Theme"&gt;
        &lt;item name="android:windowBackground"&gt;@drawable/background_shelf&lt;/item&gt;
        &lt;item name="android:windowNoTitle"&gt;true&lt;/item&gt;
    &lt;/style&gt;
&lt;/resources&gt;</pre><p>The same exact trick is used in the <em>Google Maps application that ships with the T-Mobile G1. When the application is launched, the user immediately sees the loading tiles of <code>MapView</code>. This is only a trick, the theme is simply using a tiled background that looks exactly like the loading tiles of <code>MapView</code>.</em></p><p>Sometimes the best tricks are also the simplest so the next time you create an activity with an opaque UI or a custom background, remember to change the window's background.</p><p><a href="http://progx.org/users/Gfx/android/WindowBackground">Download the source code of the first example</a>.</p><p><a href="http://code.google.com/p/shelves/">Download the source code of Shelves</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3542064214007631934?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/window-backgrounds-ui-speed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Layout Tricks #3: Optimize by merging</title>
		<link>https://googledata.org/google-android/android-layout-tricks-3-optimize-by-merging/</link>
		<comments>https://googledata.org/google-android/android-layout-tricks-3-optimize-by-merging/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 16:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[In the previous installment of Android Layout Tricks, I showed you how to use the &#60;include /&#62; tag in XML layout to reuse and share your layout code. I  also mentioned the &#60;merge /&#62; and it's now time to learn how to use it.The &#60;merge /&#038;gt...]]></description>
				<content:encoded><![CDATA[<p>In the previous installment of <em>Android Layout Tricks</em>, I showed you <a href="http://www.curious-creature.org/2009/02/25/android-layout-trick-2-include-to-reuse/">how to use the <code>&lt;include /&gt;</code> tag</a> in XML layout to reuse and share your layout code. I  also mentioned the <code>&lt;merge /&gt;</code> and it's now time to learn how to use it.</p><p>The <code>&lt;merge /&gt;</code> was created for the purpose of optimizing Android layouts by reducing the number of levels in view trees. It's easier to understand the problem this tag solves by looking at an example. The following XML layout declares a layout that shows an image with its title on top of it. The structure is fairly simple; a <a href="http://developer.android.com/reference/android/widget/FrameLayout.html">FrameLayout</a> is used to stack a <a href="http://developer.android.com/reference/android/widget/TextView.html">TextView</a> on top of an <a href="http://developer.android.com/reference/android/widget/ImageView.html">ImageView</a>:</p><pre class="prettyprint">&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"&gt;

    &lt;ImageView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
    
        android:scaleType="center"
        android:src="@drawable/golden_gate" /&gt;
    
    &lt;TextView
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_marginBottom="20dip"
        android:layout_gravity="center_horizontal|bottom"

        android:padding="12dip"
        
        android:background="#AA000000"
        android:textColor="#ffffffff"
        
        android:text="Golden Gate" /&gt;

&lt;/FrameLayout&gt;</pre><p>This layout renders nicely as we expected and nothing seems wrong with this layout:</p>

<div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/merge1.jpg" alt="A FrameLayout is used to overlay a title on top of an image" /></div>

<p>Things get more interesting when you inspect the result with <a href="http://developer.android.com/guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a>. If you look closely at the resulting tree you will notice that the <code>FrameLayout</code> defined in our XML file (highlighted in blue below) is the sole child of another <code>FrameLayout</code>:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/merge2.png" alt="A layout with only one child of same dimensions can be removed" /></div><p>Since our <code>FrameLayout</code> has the same dimension as its parent, by the virtue of using the <code>fill_parent</code> constraints, and does not define any background, extra padding or a gravity, it is <em>totally useless</em>. We only made the UI more complex for no good reason. But how could we get rid of this <code>FrameLayout</code>? After all, XML documents require a root tag and tags in XML layouts always represent view instances.</p><p>That's where the <code>&lt;merge /&gt;</code> tag comes in handy. When the  <a href="http://developer.android.com/reference/android/view/LayoutInflater.html">LayoutInflater</a> encounters this tag, it skips it and adds the <code>&lt;merge /&gt;</code> children to the <code>&lt;merge /&gt;</code> parent. Confused? Let's rewrite our previous XML layout by replacing the <code>FrameLayout</code> with <code>&lt;merge /&gt;</code>:</p><pre class="prettyprint">&lt;merge xmlns:android="http://schemas.android.com/apk/res/android"&gt;

    &lt;ImageView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
    
        android:scaleType="center"
        android:src="@drawable/golden_gate" /&gt;
    
    &lt;TextView
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_marginBottom="20dip"
        android:layout_gravity="center_horizontal|bottom"

        android:padding="12dip"
        
        android:background="#AA000000"
        android:textColor="#ffffffff"
        
        android:text="Golden Gate" /&gt;

&lt;/merge&gt;</pre><p>With this new version, both the <code>TextView</code> and the <code>ImageView</code> will be added directly to the top-level <code>FrameLayout</code>. The result will be visually the same but the view hierarchy is simpler:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/merge3.png" alt="Optimized view hierarchy using the merge tag" /></div><p>Obviously, using <code>&lt;merge /&gt;</code> works in this case because the parent of an activity's content view is always a <code>FrameLayout</code>. You could not apply this trick if your layout was using a <code>LinearLayout</code> as its root tag for instance. The <code>&lt;merge /&gt;</code> can be useful in other situations though. For instance, it works perfectly when combined with the <code>&lt;include /&gt;</code> tag. You can also use <code>&lt;merge /&gt;</code> when you create a custom composite view. Let's see how we can use this tag to create a new view called <code>OkCancelBar</code> which simply shows two buttons with customizable labels. You can also <a href="http://progx.org/users/Gfx/android/MergeLayout.zip">download the complete source code of this example</a>. Here is the XML used to display this custom view on top of an image:</p><pre class="prettyprint">&lt;merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge"&gt;

    &lt;ImageView  
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
    
        android:scaleType="center"
        android:src="@drawable/golden_gate" /&gt;
    
    &lt;com.example.android.merge.OkCancelBar
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_gravity="bottom"

        android:paddingTop="8dip"
        android:gravity="center_horizontal"
        
        android:background="#AA000000"
        
        okCancelBar:okLabel="Save"
        okCancelBar:cancelLabel="Don't save" /&gt;

&lt;/merge&gt;</pre><p>This new layout produces the following result on a device:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/merge4.jpg" alt="Creating a custom view with the merge tag" /></div><p>The source code of <code>OkCancelBar</code> is very simple because the two buttons are defined in an external XML file, loaded using a <code>LayoutInflate</code>. As you can see in the following snippet, the XML layout <code>R.layout.okcancelbar</code> is inflated with the <code>OkCancelBar</code> as the parent:</p><pre class="prettyprint">public class OkCancelBar extends LinearLayout {
    public OkCancelBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOrientation(HORIZONTAL);
        setGravity(Gravity.CENTER);
        setWeightSum(1.0f);
        
        LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true);
        
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0);
        
        String text = array.getString(R.styleable.OkCancelBar_okLabel);
        if (text == null) text = "Ok";
        ((Button) findViewById(R.id.okcancelbar_ok)).setText(text);
        
        text = array.getString(R.styleable.OkCancelBar_cancelLabel);
        if (text == null) text = "Cancel";
        ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text);
        
        array.recycle();
    }
}</pre><p>The two buttons are defined in the following XML layout. As you can see, we use the <code>&lt;merge /&gt;</code> tag to add the two buttons directly to the <code>OkCancelBar</code>. Each button is included from the same external XML layout file to make them easier to maintain; we simply override their id:</p><pre class="prettyprint">&lt;merge xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    &lt;include
        layout="@layout/okcancelbar_button"
        android:id="@+id/okcancelbar_ok" /&gt;
        
    &lt;include
        layout="@layout/okcancelbar_button"
        android:id="@+id/okcancelbar_cancel" /&gt;
&lt;/merge&gt;</pre><p>We have created a flexible and easy to maintain custom view that generates an efficient view hierarchy:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/merge5.png" alt="The resulting hierarchy is simple and efficient" /></div><p>The <code>&lt;merge /&gt;</code> tag is extremely useful and can do wonders in your code. However, it suffers from a couple of limitation:</p><ul><li><code>&lt;merge /&gt;</code> can only be used as the root tag of an XML layout</li>
<li>When inflating a layout starting with a <code>&lt;merge /&gt;</code>, you <strong>must</strong> specify a parent <code>ViewGroup</code> and you must set <code>attachToRoot</code> to <code>true</code> (see the documentation of the <a href="http://developer.android.com/reference/android/view/LayoutInflater.html#inflate(int,%20android.view.ViewGroup,%20boolean)">inflate()</a> method)</li></ul><p>In the next installment of <em>Android Layout Tricks</em> you will learn about <code>ViewStub</code>, a powerful variation of <code>&lt;include /&gt;</code> that can help you further optimize your layouts without sacrificing features.</p><p><a href="http://progx.org/users/Gfx/android/MergeLayout.zip">Download the complete source code of this example</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5845204995564817095?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-layout-tricks-3-optimize-by-merging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Layout Tricks #2: Reusing layouts</title>
		<link>https://googledata.org/google-android/android-layout-tricks-2-reusing-layouts/</link>
		<comments>https://googledata.org/google-android/android-layout-tricks-2-reusing-layouts/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 06:31:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Android comes with a wide variety of widgets, small visual construction blocks you can glue together to present the users with complex and useful interfaces. However applications often need higher level visual components. A component can be seen as a c...]]></description>
				<content:encoded><![CDATA[<p>Android comes with a wide variety of <em>widgets</em>, small visual construction blocks you can glue together to present the users with complex and useful interfaces. However applications often need higher level visual <em>components</em>. A component can be seen as a complex widget made of several simple stock widgets. You could for instance reuse a panel containing a progress bar and a cancel button, a panel containing two buttons (positive and negative actions), a panel with an icon, a title and a description, etc. Creating new components can be done easily by writing a custom <code>View</code> but it can be done even more easily using only XML.</p><p>In Android XML layout files, each tag is mapped to an actual class instance (the class is always a subclass of <a href="http://developer.android.com/reference/android/view/View.html">View</a>.) The UI toolkit lets you also use three special tags that are not mapped to a <code>View</code> instance: <code>&lt;requestFocus /&gt;</code>, <code>&lt;merge /&gt;</code> and <code>&lt;include /&gt;</code>. The latter, <code>&lt;include /&gt;</code>, can be used to create pure XML visual components. (Note: I will present the <code>&lt;merge /&gt;</code> tag in the next installment of <em>Android Layout Tricks</em>.)</p><p>The <code>&lt;include /&gt;</code> does exactly what its name suggests; it includes another XML layout. Using this tag is straightforward as shown in the following example, taken straight from <a href="http://android.git.kernel.org/?p=platform/packages/apps/Launcher.git;a=tree;h=refs/heads/master;hb=master">the source code of the Home application</a> that currently ships with Android:</p><pre class="prettyprint">&lt;com.android.launcher.Workspace
    android:id="@+id/workspace"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"

    launcher:defaultScreen="1"&gt;

    &lt;include android:id="@+id/cell1" layout="@layout/workspace_screen" /&gt;
    &lt;include android:id="@+id/cell2" layout="@layout/workspace_screen" /&gt;
    &lt;include android:id="@+id/cell3" layout="@layout/workspace_screen" /&gt;

&lt;/com.android.launcher.Workspace&gt;</pre><p>In the <code>&lt;include /&gt;</code> only the <code>layout</code> attribute is required. This attribute, without the <code>android</code> namespace prefix, is a reference to the layout file you wish to include. In this example, the same layout is included three times in a row. This tag also lets you override a few attributes of the included layout. The above example shows that you can use <code>android:id</code> to specify the id of the root view of the included layout; it will also override the id of the included layout if one is defined. Similarly, you can override all the layout parameters. This means that any <code>android:layout_*</code> attribute can be used with the <code>&lt;include /&gt;</code> tag. Here is an example:</p><pre class="prettyprint">&lt;include android:layout_width="fill_parent" layout="@layout/image_holder" /&gt;
&lt;include android:layout_width="256dip" layout="@layout/image_holder" /&gt;
</pre><p>This tag is particularly useful when you need to customize only part of your UI depending on the device's configuration. For instance, the main layout of your activity can be placed in the <code>layout/</code> directory and can include another layout which exists in two flavors, in <code>layout-land/</code> and <code>layout-port/</code>. This allows you to share most of the UI in portrait and landscape.</p><p>Like I mentioned earlier, my next post will explain the <code>&lt;merge /&gt;</code>, which can be particularly powerful when combined with <code>&lt;include /&gt;</code>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-6818169768557965035?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-layout-tricks-2-reusing-layouts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Layout Tricks #1</title>
		<link>https://googledata.org/google-android/android-layout-tricks-1/</link>
		<comments>https://googledata.org/google-android/android-layout-tricks-1/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 22:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[The Android UI toolkit offers several layout managers that are rather easy to use and, most of the time, you only need the basic features of these layout managers to implement a user interface. Sticking to the basic features is unfortunately not the mo...]]></description>
				<content:encoded><![CDATA[<p>The Android UI toolkit offers several layout managers that are rather easy to use and, most of the time, you only need the basic features of these layout managers to implement a user interface. Sticking to the basic features is unfortunately not the most efficient way to create user interfaces. A common example is the abuse of <a href="http://developer.android.com/reference/android/widget/LinearLayout.html">LinearLayout</a>, which leads to a proliferation of views in the view hierarchy. Every view, or worse every layout manager, you add to your application comes at a cost: initialization, layout and drawing become slower. The layout pass can be especially expensive when you nest several LinearLayout that use the <a href="http://developer.android.com/reference/android/widget/LinearLayout.LayoutParams.html#attr_android:layout_weight">weight</a> parameter, which requires the child to be measured twice.</p><p>Let's consider a very simple and common example of a layout: a list item with an icon on the left, a title at the top and an optional description underneath the title. Here is what such an item looks like:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/relativelayout_1.png" alt="Simple list item" /></div><p>To clearly understand how the views, one <a href="http://developer.android.com/reference/android/widget/ImageView.html">ImageView</a> and two <a href="http://developer.android.com/reference/android/widget/TextView.html">TexView</a>, are positioned with respect to each other, here is the wireframe of the layout as captured by <a href="http://developer.android.com/guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a>:<div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/relativelayout_wire_1.png" alt="Wireframe of the simple list item" /></div><p>Implementing this layout is straightforward with LinearLayout. The item itself is a horizontal LinearLayout with an ImageView and a vertical LinearLayout, which contains the two TextViews. The source code of this layout is the following:</p><pre class="prettyprint">&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    
    android:padding="6dip"&gt;
    
    &lt;ImageView
        android:id="@+id/icon"
        
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_marginRight="6dip"
        
        android:src="@drawable/icon" /&gt;

    &lt;LinearLayout
        android:orientation="vertical"
    
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent"&gt;

        &lt;TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
                    
            android:gravity="center_vertical"
            android:text="My Application" /&gt;
            
        &lt;TextView  
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1" 
            
            android:singleLine="true"
            android:ellipsize="marquee"
            android:text="Simple application that shows how to use RelativeLayout" /&gt;
            
    &lt;/LinearLayout&gt;

&lt;/LinearLayout&gt;</pre><p>This layout works but can be wasteful if you instantiate it for every list item of a <a href="http://developer.android.com/reference/android/widget/ListView.html">ListView</a>. The same layout can be rewritten using a single <a href="http://developer.android.com/reference/android/widget/RelativeLayout.html">RelativeLayout</a>, thus saving one view, and even better one level in view hierarchy, per list item. The implementation of the layout with a RelativeLayout remains simple:</p><pre class="prettyprint">&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    
    android:padding="6dip"&gt;
    
    &lt;ImageView
        android:id="@+id/icon"
        
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="6dip"
        
        android:src="@drawable/icon" /&gt;

    &lt;TextView  
        android:id="@+id/secondLine"

        android:layout_width="fill_parent"
        android:layout_height="26dip" 
        
        android:layout_toRightOf="@id/icon"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        
        android:singleLine="true"
        android:ellipsize="marquee"
        android:text="Simple application that shows how to use RelativeLayout" /&gt;

    &lt;TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        
        android:layout_toRightOf="@id/icon"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_above="@id/secondLine"
        android:layout_alignWithParentIfMissing="true"
                
        android:gravity="center_vertical"
        android:text="My Application" /&gt;

&lt;/RelativeLayout&gt;</pre><p>This new implementation behaves exactly the same way as the previous implementation, except in one case. The list item we want to display has two lines of text: the title and an <em>optional</em> description. When a description is not available for a given list item, the application would simply set the visibility of the second TextView to <a href="http://developer.android.com/reference/android/view/View.html#GONE">GONE</a>. This works perfectly with the LinearLayout implementation but not with the RelativeLayout version:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/relativelayout_2.png" alt="RelativeLayout and description GONE" /></div>
<div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/relativelayout_wire_2.png" alt="RelativeLayout and description GONE" /></div><p>In a RelativeLayout, views are aligned either with their parent, the RelativeLayout itself, or other views. For instance, we declared that the description is aligned with the bottom of the RelativeLayout and that the title is positioned above the description and anchored to the parent's top. With the description GONE, RelativeLayout doesn't know where to position the title's bottom edge. To solve this problem, you can use a very special layout parameter called <a href="http://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_alignWithParentIfMissing">alignWithParentIfMissing</a>.</p><p>This boolean parameter simply tells RelativeLayout to use its own edges as anchors when a constraint target is missing. For instance, if you position a view to the right of a GONE view and set alignWithParentIfMissing to true, RelativeLayout will instead anchor the view to its left edge. In our case, using alignWithParentIfMissing will cause RelativeLayout to align the title's bottom with its own bottom. The result is the following:</p><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/relativelayout_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing" /></div><div style="text-align: center;"><img src="http://progx.org/users/Gfx/android/relativelayout_wire_3.png" alt="RelativeLayout, description GONE and alignWithParentIfMissing" /></div><p>The behavior of our layout is now perfect, even when the description is GONE. Even better, the hierarchy is simpler and because we are not using LinearLayout's weights it's also more efficient. The difference between the two implementations becomes obvious when comparing the view hierarchies in HierarchyViewer:</p><div style="text-align: center;"><a href="http://progx.org/users/Gfx/android/layouts_comparison.png"><img src="http://progx.org/users/Gfx/android/layouts_comparison_small.png" alt="LinearLayout vs RelativeLayout" /></a></div><p>Again, the difference will be much more important when you use such a layout for every item in a ListView for instance. Hopefully this simple example showed you that getting to know your layouts is the best way to learn how to optimize your UI.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-966053216188501940?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-layout-tricks-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Faster screen orientation change</title>
		<link>https://googledata.org/google-android/faster-screen-orientation-change/</link>
		<comments>https://googledata.org/google-android/faster-screen-orientation-change/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 17:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Android is a mobile operating system meant to be run on a wide array of devices, with very different hardware configurations. Some devices, like the T-Mobile G1, can change their hardware configuration at runtime. For instance, when you open the keyboa...]]></description>
				<content:encoded><![CDATA[<p>Android is a mobile operating system meant to be run on a wide array of devices, with very different hardware configurations. Some devices, like the T-Mobile G1, can change their hardware configuration at runtime. For instance, when you open the keyboard, the screen change from the portrait orientation to the landscape orientation. To make Android applications development easier, the OS automatically handles configuration changes and restart the current activity with the new configuration. This is the default behavior that lets you declare resources like layouts and drawables based on the orientation, screen size, locale, etc. If you are not familiar with the way Android handles resources, I highly suggest you to <a href="http://d.android.com/guide/topics/resources/resources-i18n.html">read the official documentation on resources</a>.</p><p>While this behavior is really powerful, since your application adapts automatically to the device's configuration at runtime, it is sometimes confusing for new Android developers who wonder why their activity is destroyed and recreated. Facing this "issue," some developers choose to handle configuration changes themselves which is, in my opinion, a short-term solution that will complicate their life when other devices come out or when the application becomes more complex. The automatic resource handling is a very efficient and easy way to adapt your application's user interface to various devices and devices configurations. It sometimes comes at a price though.</p><p>When your application displays a lot of data, or data that is expensive to fetch, the automatic destruction/creation of the activities can be lead to a painful user experience. Take the example of <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/">Photostream</a>, a simple Flickr browsing application I wrote for the release of Android 1.0. After you launch the application and choose a Flickr account, the application downloads a set of 6 photos (on a T-Mobile G1) from the Flickr servers and displays them on screen. To improve the user experience, I also use slightly different layouts and drawables in portrait and landscape, and this is what the result looks like:</p><p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9l0GmPwgCzk/SZoGyJyg6-I/AAAAAAAAACU/ItuVwhegPb8/s1600-h/photostream_landscape.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 214px;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/SZoGyJyg6-I/AAAAAAAAACU/ItuVwhegPb8/s320/photostream_landscape.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5303558969873198050" /></a></p><p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9l0GmPwgCzk/SZoGx4I-QlI/AAAAAAAAACM/-GkZR5MUKhY/s1600-h/photostream_portrait.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://2.bp.blogspot.com/_9l0GmPwgCzk/SZoGx4I-QlI/AAAAAAAAACM/-GkZR5MUKhY/s320/photostream_portrait.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5303558965135557202" /></a></p><p>Photostream lets Android take care of the configuration change when the screen is rotated. However, can you imagine how painful it would be for the user to see all the images being downloaded again? The obvious solution to this problem is to temporarily cache the images. They could be cached on the SD card (if there's one), in the Application object, in a static field, etc. None of these techniques is adapted to the current situation: why should we bother caching the images when the screen is not rotated? Fortunately for us, Android offers a great API exactly for that purpose.</p><p>The Activity class has a special method called <a href="http://d.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance()">onRetainNonConfigurationInstance()</a>. This method can be used to pass an arbitrary object <em>your future self</em> and Android is smart enough to call this method only when needed. In the case of Photostream, I <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java#226">used this method</a> to pass the downloaded images to the future activity on orientation change. The implementation can be summarized like so:</p><pre class="prettyprint">@Override
public Object onRetainNonConfigurationInstance() {
    final LoadedPhoto[] list = new LoadedPhoto[numberOfPhotos];
    keepPhotos(list);
    return list;
}
</pre><p>In the new activity, in <code>onCreate()</code>, all you have to do to get your object back is to call <a href="http://d.android.com/reference/android/app/Activity.html#getLastNonConfigurationInstance()"> getLastNonConfigurationInstance()</a>. In Photostream, <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java#251">this method is invoked</a> and if the returned value is not null, the grid is loaded with the list of photos from the previous activity:</p><pre class="prettyprint">private void loadPhotos() {
    final Object data = getLastNonConfigurationInstance();
    
    // The activity is starting for the first time, load the photos from Flickr
    if (data == null) {
        mTask = new GetPhotoListTask().execute(mCurrentPage);
    } else {
        // The activity was destroyed/created automatically, populate the grid
        // of photos with the images loaded by the previous activity
        final LoadedPhoto[] photos = (LoadedPhoto[]) data;
        for (LoadedPhoto photo : photos) {
            addPhoto(photo);
        }
    }
}
</pre><p>Be very careful with the object you pass through <code>onRetainNonConfigurationChange()</code> though. If the object you pass is for some reason tied to the Activity/Context, <a href="http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/">you will leak</a> all the views and resources of the activity. This means you should never pass a View, a Drawable, an Adapter, etc. Photostream for instance extracts the bitmaps from the drawables and pass the bitmaps only, not the drawables. Finally, remember that <code>onRetainNonConfigurationChange()</code> should be used only to retain data that is expensive to load. Otherwise, keep it simple and let Android do everything.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8949884833105332305?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/faster-screen-orientation-change/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Track memory allocations</title>
		<link>https://googledata.org/google-android/track-memory-allocations/</link>
		<comments>https://googledata.org/google-android/track-memory-allocations/#comments</comments>
		<pubDate>Thu, 12 Feb 2009 18:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Despite the impressive hardware of the first Android phones (T-Mobile G1 and ADP1) writing efficient mobile applications is not always straightforward. Android applications rely on automatic memory management handled by Dalvik's garbage collector which...]]></description>
				<content:encoded><![CDATA[<p>Despite the impressive hardware of the first Android phones (T-Mobile G1 and ADP1) writing efficient mobile applications is not always straightforward. Android applications rely on automatic memory management handled by Dalvik's garbage collector which can sometimes cause performance issues if you are not careful with memory allocations.</p><p>In a performance sensitive code path, like the layout or drawing method of a view or the logic code of a game, any allocation comes at a price. After too many allocations, the garbage collector will kick in and stop your application to let it free some memory. Most of the time, garbage collections happen fast enough for you not to notice. However, if a collection happens while you are scrolling through a list of items or while you are trying to defeat a foe in a game, you may suddenly see a drop in performance/responsiveness of the application. It's not unusual for a garbage collection to take 100 to 200 ms. For comparison, a smooth animation needs to draw each frame in 16 to 33 ms. If the animation is suddenly interrupted for 10 frames, you can be certain that your users will notice.</p><p>Most of the time, garbage collection occurs because of tons of small, short-lived objects and some garbage collectors, like generational garbage collectors, can optimize the collection of these objects so that the application does not get interrupted too often. The Android garbage collector is unfortunately not able to perform such optimizations and the creation of short-lived objects in performance critical code paths is thus very costly for your application.</p><p>To help you avoid frequent garbage collections, the Android SDK ships with a very useful tool called <em>allocation tracker</em>. This tool is part of DDMS, which you must have already used for debugging purposes. To start using the allocation tracker, you must first launch the standalone version of DDMS, which can be found in the <code>tools/</code> directory of the SDK. The version of DDMS included in the Eclipse plugin does not offer you ability to use the allocation tracker yet.</p><p>Once DDMS is running, simply select your application process and then click the <em>Allocation Tracker</em> tab. In the new view, click <em>Start Tracking</em> and then use your application to make it execute the code paths you want to analyze. When you are ready, click <em>Get Allocations</em>. A list of allocated objects will be shown in the first table. By clicking on a line you can see, in the second table, the stack trace that led to the allocation. Not only you will know what type of object was allocated, but also in which thread, in which class, in which file and at which line. The following screenshot shows the allocations performed by <a href="http://code.google.com/p/shelves">Shelves</a> while scrolling a ListView.</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9l0GmPwgCzk/SY-EGKmIm4I/AAAAAAAAACE/6YjUq_Rnne0/s1600-h/ddms_allocation_tracker.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 250px;" src="http://2.bp.blogspot.com/_9l0GmPwgCzk/SY-EGKmIm4I/AAAAAAAAACE/6YjUq_Rnne0/s320/ddms_allocation_tracker.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5300600527896746882" /></a><p>Even though it is not necessary, or sometimes not possible, to remove all allocations for your performance critical code paths. the allocation tracker will help you identify important issues in your code. For instance, a common mistake I have seen in many applications is to create a new <code>Paint</code> object on every draw. Moving the paint into an instance field is a simple fix that helps performance a lot. I highly encourage you to peruse the <a href="http://source.android.com">Android source code</a> to see how we reduce allocations in performance critical code paths. You will also thus discover the APIs Android provide to help you reuse objects.</p><p>Note: this article was originally posted on my <a href="http://www.curious-creature.org/">personal blog</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-8939970428473155351?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/track-memory-allocations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Avoiding memory leaks</title>
		<link>https://googledata.org/google-android/avoiding-memory-leaks/</link>
		<comments>https://googledata.org/google-android/avoiding-memory-leaks/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 06:09:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Android applications are, at least on the T-Mobile G1, limited to 16 MB of heap. It's both a lot of memory for a phone and yet very little for what some developers want to achieve. Even if you do not plan on using all of this memory, you should use as ...]]></description>
				<content:encoded><![CDATA[<p>Android applications are, at least on the T-Mobile G1, limited to 16 MB of heap. It's both a lot of memory for a phone and yet very little for what some developers want to achieve. Even if you do not plan on using all of this memory, you should use as little as possible to let other applications run without getting them killed. The more applications Android can keep in memory, the faster it will be for the user to switch between his apps. As part of my job, I ran into memory leaks issues in Android applications and they are most of the time due to the same mistake: keeping a long-lived reference to a <a href="http://code.google.com/android/reference/android/content/Context.html">Context</a>.</p>

<p>On Android, a <code>Context</code> is used for many operations but mostly to load and access resources. This is why all the widgets receive a <code>Context</code> parameter in their constructor. In a regular Android application, you usually have two kinds of <code>Context</code>, <a href="http://code.google.com/android/reference/android/app/Activity.html">Activity</a> and <a href="http://code.google.com/android/reference/android/app/Application.html">Application</a>. It's usually the first one that the developer passes to classes and methods that need a <code>Context</code>:</p>

<pre class="prettyprint">
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
  
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
  
  setContentView(label);
}
</pre>

<p>This means that views have a reference to the entire activity and therefore to anything your activity is holding onto; usually the entire View hierarchy and all its resources. Therefore, if you leak the <code>Context</code> ("leak" meaning you keep a reference to it thus preventing the GC from collecting it), you leak a lot of memory. Leaking an entire activity can be really easy if you're not careful.</p>

<p>When the screen orientation changes the system will, by default, destroy the current activity and create a new one while preserving its state. In doing so, Android will reload the application's UI from the resources. Now imagine you wrote an application with a large bitmap that you don't want to load on every rotation. The easiest way to keep it around and not having to reload it on every rotation is to keep in a static field:</p>

<pre class="prettyprint">
private static Drawable sBackground;

@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
  
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
  
  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);
  
  setContentView(label);
}
</pre>

<p>This code is very fast and also very wrong; it leaks the first activity created upon the first screen orientation change. When a <a href="http://code.google.com/android/reference/android/graphics/drawable/Drawable.html">Drawable</a> is attached to a view, the view is set as a <a href="http://code.google.com/android/reference/android/graphics/drawable/Drawable.html#setCallback(android.graphics.drawable.Drawable.Callback)">callback</a> on the drawable. In the code snippet above, this means the drawable has a reference to the <code>TextView</code> which itself has a reference to the activity (the <code>Context</code>) which in turns has references to pretty much anything (depending on your code.)</p>

<p>This example is one of the simplest cases of leaking the <code>Context</code> and you can see how we worked around it in the <a href="http://android.git.kernel.org/?p=platform/packages/apps/Launcher.git;a=blob;f=src/com/android/launcher/LauncherModel.java;h=0ef2a806b767142b28b2ff3b37f21f4ca16c355d;hb=cupcake">Home screen's source code</a> (look for the <code>unbindDrawables()</code> method) by setting the stored drawables' callbacks to null when the activity is destroyed. Interestingly enough, there are cases where you can create a chain of leaked contexts, and they are bad. They make you run out of memory rather quickly.</p>

<p>There are two easy ways to avoid context-related memory leaks. The most obvious one is to avoid escaping the context outside of its own scope. The example above showed the case of a static reference but inner classes and their implicit reference to the outer class can be equally dangerous. The second solution is to use the <code>Application</code> context. This context will live as long as your application is alive and does not depend on the activities life cycle. If you plan on keeping long-lived objects that need a context, remember the application object. You can obtain it easily by calling <a href="http://code.google.com/android/reference/android/content/Context.html#getApplicationContext()">Context.getApplicationContext()</a> or <a href="http://code.google.com/android/reference/android/app/Activity.html#getApplication()">Activity.getApplication()</a>.</p>

<p>In summary, to avoid context-related memory leaks, remember the following:</p>
<ul>
<li>Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)</li>
<li>Try using the context-application instead of a context-activity</li>
<li>Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. The solution to this issue is to use a static inner class with a <a href="http://code.google.com/android/reference/java/lang/ref/WeakReference.html">WeakReference</a> to the outer class, as done in <a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/ViewRoot.java;h=9d7a124cb01ab94bf53e34f6e5e8a07f81e2423c;hb=master">ViewRoot</a> and its W inner class for instance</li>
<li>A garbage collector is not an insurance against memory leaks</li>
</ul>

<p><span style="font-weight:bold;">Note</span>: This article was originally posted on my <a href="http://www.curious-creature.org">personal blog</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2713380255164474040?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/avoiding-memory-leaks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why is my list black? An Android optimization</title>
		<link>https://googledata.org/google-android/why-is-my-list-black-an-android-optimization/</link>
		<comments>https://googledata.org/google-android/why-is-my-list-black-an-android-optimization/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 19:20:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[ListView is one of Android's most widely used widgets. It is rather easy to use, very flexible and incredibly powerful. ListView can also be difficult to understand at times.
One of the most common issues with ListView happens when you try to use a cus...]]></description>
				<content:encoded><![CDATA[<p><a href="http://code.google.com/android/reference/android/widget/ListView.html">ListView</a> is one of Android's most widely used widgets. It is rather easy to use, very flexible and incredibly powerful. <code>ListView</code> can also be difficult to understand at times.</p>
<p>One of the most common issues with <code>ListView</code> happens when you try to use a custom background. By default, like many Android widgets, <code>ListView</code> has a transparent background which means yo can see through the default window's background, a very dark gray (<code>#FF191919</code> with the current dark theme.) Additionally, <code>ListView</code> enables the <em>fading edges</em> by default, as you can see at the top of the following screenshot; the first text item gradually fades to black. This technique is used throughout the system to indicate that the container can be scrolled.</p>
<div style="text-align: center;"><img src="http://1.bp.blogspot.com/_9l0GmPwgCzk/SWOpjeZO-JI/AAAAAAAAABE/z50fFz3khZY/s400/list_fade_1.png" alt="Android's default ListView" /></div>
<p>The fade effect is implemented using a combination of <a href="http://code.google.com/android/reference/android/graphics/Canvas.html#saveLayerAlpha%28float,%20float,%20float,%20float,%20int,%20int%29">Canvas.saveLayerAlpha() and the </a><a href="http://code.google.com/android/reference/android/graphics/PorterDuff.Mode.html#DST_OUT">Porter-Duff Destination Out blending mode</a>. This technique is similar to the one explained in <a href="http://filthyrichclients.org/">Filthy Rich Clients</a> and various presentations. Unfortunately, things start to get ugly when you try to use a custom background on the <code>ListView</code> or when you change the window's background. The following two screenshots show what happens in an application when you change the window's background. The left image shows what the list looks like by default and the right image shows what the list looks like during a scroll initiated with a touch gesture:</p>
<div style="text-align: center;"><img style="margin-right: 12px;" src="http://4.bp.blogspot.com/_9l0GmPwgCzk/SWOps9T_PKI/AAAAAAAAABM/89oBTVMLShE/s400/list_fade_2.png" alt="Dark fade" /><img src="http://4.bp.blogspot.com/_9l0GmPwgCzk/SWOpvbGRLOI/AAAAAAAAABU/-rlKZc-Q314/s400/list_fade_3.png" alt="Dark list" /></div>
<p>This rendering issue is caused by an optimization of the Android framework enabled by default on all instances of <code>ListView</code> (for some reason, I forgot to enable it by default on <code>GridView</code>.) I mentioned earlier that the fade effect is implemented using a Porter-Duff blending mode. This implementation works really well but is unfortunately very costly and can bring down drawing performance by quite a bit as it requires to capture a portion of the rendering in an offscreen bitmap and then requires extra blending (which implies readbacks from memory.)</p>
<p>Since <code>ListView</code> is most of the time displayed on a solid background, there is no reason to go down that expensive route. That's why we introduced an optimization called the "cache color hint." The cache color hint is an RGB color set by default to the window's background color, that is #191919 in Android's dark theme. When this hint is set, <code>ListView</code> (actually, its base class <code>View</code>) knows it will draw on a solid background and therefore replaces th expensive <code>saveLayerAlpha()/Porter-Duff</code> rendering with a simple gradient. This gradient goes from fully transparent to the cache color hint value and this is exactly what you see on the image above, with the dark gradient at the bottom of the list. However, this still does not explain why the entire list turns black during a scroll.</p>
<p>As I said before, <code>ListView</code> has a transparent/translucent background by default, and so all default Android widgets. This implies that when <code>ListView</code> redraws its children, it has to blend the children with the window's background. Once again, this requires costly readbacks from memory that are particularly painful during a scroll or a fling when drawing happens dozen of times per second. To improve drawing performance during scrolling operations, the Android framework reuses the cache color hint. When this hint is set, the framework copies each child of the list in a <code>Bitmap</code> filled with the hint value (this assumes that another optimization, called <em>scrolling cache</em>, is not turned off.) <code>ListView</code> then blits these bitmaps directly on screen and because these bitmaps are known to be opaque, no blending is required. And since the default cache color hint is <code>#191919</code>, you get a dark background behind each item during a scroll.</p>
<p>To fix this issue, all you have to do is either disable the cache color hint optimization, if you use a non-solid color background, or set the hint to the appropriate solid color value. This can be dome <a href="http://code.google.com/android/reference/android/widget/AbsListView.html#setCacheColorHint%28int%29">from code</a> or preferably from XML, by using the <code>android:cacheColorHint</code> attribute. To disable the optimization, simply use the transparent color <code>#00000000</code>. The following screenshot shows a list with <code>android:cacheColorHint="#00000000"</code> set in the XML layout file:</p>
<div style="text-align: center;"><img src="http://4.bp.blogspot.com/_9l0GmPwgCzk/SWOp6XrZb-I/AAAAAAAAABc/qvGG6jVEYc4/s400/list_fade_4.png" alt="Fade on a custom background" /></div>
<p>As you can see, the fade works perfectly against the custom wooden background. I find the cache color hint feature interesting because it shows how optimizations can make developers' life more difficult in some situations. In this particular case, however, the benefit of the default behavior outweighs the added complexity for the developer.</p>
<p><strong>Note</strong>: this article was originally posted on <a href="http://www.curious-creature.org/2008/12/15/android-can-i-use-this-intent/">my personal blog</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2396420582459444331?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/why-is-my-list-black-an-android-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Can I use this Intent?</title>
		<link>https://googledata.org/google-android/can-i-use-this-intent/</link>
		<comments>https://googledata.org/google-android/can-i-use-this-intent/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 14:00:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Android offers a very powerful and yet easy to use tool called intents. An intent can be use to turn applications into high-level libraries and make code re-use something even better than before. The Android Home screen and AnyCut use intents extensive...]]></description>
				<content:encoded><![CDATA[<p><a href="http://code.google.com/android">Android</a> offers a very powerful and yet easy to use tool called <a href="http://code.google.com/android/reference/android/content/Intent.html">intents</a>. An intent can be use to turn applications into high-level libraries and make code re-use something even better than before. The Android Home screen and AnyCut use intents extensively to create shortcuts for instance. While it is nice to be able to make use of a loosely coupled API, there is no guarantee that the intent you send will be received by another application. This happens in particular with 3rd party apps, like <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Panoramio">Panoramio</a> and its RADAR intent.</p>
<p>While working on a new application, I came up with a very simple way to find out whether the system contains any application capable of responding to the intent you want to use. I implemented this technique in my application to gray out the menu item that the user would normally click to trigger the intent. The code is pretty simple and easy to follow:</p>
<pre class="prettyprint">
/**
 * Indicates whether the specified action can be used as an intent. This
 * method queries the package manager for installed packages that can
 * respond to an intent with the specified action. If no suitable package is
 * found, this method returns false.
 *
 * @param context The application's environment.
 * @param action The Intent action to check for availability.
 *
 * @return True if an Intent with the specified action can be sent and
 *         responded to, false otherwise.
 */
public static boolean isIntentAvailable(Context context, String action) {
    final PackageManager packageManager = context.getPackageManager();
    final Intent intent = new Intent(action);
    List&lt;ResolveInfo&gt; list =
            packageManager.queryIntentActivities(intent,
                    PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}
</pre>
<p>Here is how I use it:</p>
<pre class="prettyprint">
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    final boolean scanAvailable = isIntentAvailable(this,
        "com.google.zxing.client.android.SCAN");

    MenuItem item;
    item = menu.findItem(R.id.menu_item_add);
    item.setEnabled(scanAvailable);

    return super.onPrepareOptionsMenu(menu);
}
</pre>
<p>In this example, the menu is grayed out if the <em>Barcode Scanner</em> application is not installed. Another, simpler, way to do this is to catch the <code>ActivityNotFoundException</code> when calling <code>startActivity()</code> but it only lets you react to the problem, you cannot predict it and update the UI accordingly to prevent the user from doing something that won't work. The technique described here can also be used at startup time to ask the user whether he'd like to install the missing package, you can then simply redirect him to the Android Market by using the appropriate URI.</p>
<p><strong>Note</strong>: this article was originally posted on <a href="http://www.curious-creature.org/2008/12/15/android-can-i-use-this-intent/">my personal blog</a>.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-3652294870244820350?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/can-i-use-this-intent/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Touch Mode</title>
		<link>https://googledata.org/google-android/touch-mode/</link>
		<comments>https://googledata.org/google-android/touch-mode/#comments</comments>
		<pubDate>Mon, 01 Dec 2008 21:15:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Designing and developing user interfaces for Android is very different from doing so in a regular desktop environment. Because Android runs applications on mobile devices, application designers and developers must deal with numerous constraints that ar...]]></description>
				<content:encoded><![CDATA[<p>Designing and developing user interfaces for Android is very different from doing so in a regular desktop environment. Because Android runs applications on mobile devices, application designers and developers must deal with numerous constraints that are not always obvious. To help you design and develop better applications, we are publishing a new series of posts focusing on Android user interfaces. In this series, we will give you design guides and tools, development tips, and explain the fundamental principles of the Android UI toolkit. The goal here is simple: we want to help you design and develop a great user experience. To start off this series, I'd like to introduce <em>touch mode</em>, one of the most important principles of the UI toolkit.</p><p>The touch mode is a state of the view hierarchy that depends solely on the user interaction with the phone. By itself, the touch mode is something very easy to understand as it simply indicates whether the last user interaction was performed with the touch screen. For example, if you are using a G1 phone, selecting a widget with the trackball will take you out of touch mode; however, if you touch a button on the screen with your finger, you will enter touch mode. When the user is not in touch mode, we talk about the trackball mode, navigation mode or keyboard navigation, so do not be surprised if you encounter these terms. Finally, there is only one API directly related to touch mode, <a href="http://code.google.com/android/reference/android/view/View.html#isInTouchMode%28%29">View.isInTouchMode()</a>.</p><p>Sounds easy enough right? Oddly enough, touch mode is deceivingly simple and the consequences of entering touch mode are far greater than you might think. Let's look at some of the reasons why.</p><h4>Touch Mode, Selection, and Focus</h4><p>Designing a UI toolkit for mobile devices is difficult because of the various interaction mechanisms they provide. Some devices offer only 12 keys, some have a touch screen, some require a stylus, some have both a touch screen and a keyboard. In that regard, it is a great benefit for the Android development community that the first commercially available device, the G1, offers multiple forms of input using a touch screen, a trackball, and a keyboard. Because the user can interact with applications using three different mechanisms, we had to think very hard about all the possible issues that could arise. One issue led us to create the touch mode.</p><p>Imagine a simple application, <a href="http://code.google.com/android/samples/index.html">ApiDemos</a> for example, that shows a list of text items. The user can freely navigate through the list using the trackball and they can also scroll and fling the list using their finger. The issue in this scenario is the selection. If I select an item at the top of the list and then fling the list towards the bottom, what should happen to the selection? Should it remain on the item and scroll off the screen? In this case, what would happen if I then decide to move the selection with the trackball? Or worse, if I press the trackball to act upon the currently selected item, which is not shown on screen anymore. After careful considerations, we decided to remove the selection altogether.</p><p>In touch mode, there is no focus and no selection. Any selected item in a list of in a grid becomes unselected as soon as the user enters touch mode. Similarly, any focused widgets become unfocused when the user enters touch mode. The image below illustrates what happens when the user touches a list after selecting an item with the trackball.</p><img style="align:center; margin:0px 7px;" src="http://2.bp.blogspot.com/_9l0GmPwgCzk/SSyVEWhud-I/AAAAAAAAAAc/nBJtkfR5GtI/s400/list02.png" alt="" id="BLOGGER_PHOTO_ID_5272753165743060962" border="0" /><img style="align:center; margin:0px 7px;" src="http://4.bp.blogspot.com/_9l0GmPwgCzk/SSyVPgqTlbI/AAAAAAAAAAk/j4R_CQJ6PZI/s400/list01.png" alt="" id="BLOGGER_PHOTO_ID_5272753357441963442" border="0" /><p>To make things more natural for the user, the framework knows how to resurrect the selection/focus whenever the user leaves touch mode. For instance, in the example above, if the user were to use the trackball again, the selection would reappear on the previously-selected item. This is why some developers are confused when they create a custom view and start receiving key events only after moving the trackball once: their application is in touch mode, and they need to use the trackball to exit touch mode and resurrect the focus.</p><p>The relationship between touch mode, selection, and focus means you must not rely on selection and/or focus to exist in your application. A very common problem with new Android developers is to rely on <a href="http://code.google.com/android/reference/android/widget/AdapterView.html#getSelectedItemPosition%28%29">ListView.getSelectedItemPosition()</a>. In touch mode, this method will return <a href="http://code.google.com/android/reference/android/widget/AdapterView.html#INVALID_POSITION">INVALID_POSITION</a>. You should instead use <a href="http://code.google.com/android/reference/android/widget/AdapterView.html#setOnItemClickListener%28android.widget.AdapterView.OnItemClickListener%29">click listeners</a> or the <a href="http://code.google.com/android/reference/android/widget/ListView.html#setChoiceMode%28int%29">choice mode</a>.</p><h4>Focusable in Touch Mode</h4><p>Now that you know focus doesn't exist in touch mode, I must explain that it's not entirely true. Focus can exist in touch mode but in a very special way we call focusable in touch mode. This special mode was created for widgets that receive text input, like <a href="http://code.google.com/android/reference/android/widget/EditText.html">EditText</a> or, when filtering is enabled, <a href="http://code.google.com/android/reference/android/widget/ListView.html">ListView</a>. This is why the user can type text inside a text field without first selecting it with the trackball or their finger. When a user touches the screen, the application will enter touch mode if it wasn't in touch mode already.  What happens during the transition to touch mode depends on what the user touched, and what currently has focus.  If the user touches a widget that is focusable in touch mode, that widget will receive focus.  Otherwise, any currently focused widget will not retain focus unless it is focusable in touch mode. For instance, in the picture below, when the user touches the screen, the input text field receives the focus.</p><img style="align:center; margin:0px 7px;" src="http://3.bp.blogspot.com/_9l0GmPwgCzk/SSyXK0AJyNI/AAAAAAAAAAs/olrz5F3YsVU/s400/text_field.png" alt="" id="BLOGGER_PHOTO_ID_5272755475757779154" border="0" /><p><a href="http://code.google.com/android/reference/android/view/View.html#setFocusableInTouchMode(boolean)">Focusable in touch mode</a> is a property that you can set yourself either from code or XML. However, it should be used sparingly and only in very specific situations as it breaks consistency with Android normal behavior. A game is a good example of an application that can make good use of the focusable in touch mode property. MapView, if used in fullscreen as in Google Maps, is another good example of where you can use focusable in touch mode correctly.</p><p>Below is another example of a focusable in touch mode widget. When the user taps an AutoCompleteTextView's suggestion with his finger, the focus remains on the input text field:</p><img style="align:center; margin:0px 7px;" src="http://1.bp.blogspot.com/_9l0GmPwgCzk/SSyYRevh8lI/AAAAAAAAAA8/BWRW5T-c1LE/s400/search01.png" alt="" id="BLOGGER_PHOTO_ID_5272756689821626962" border="0" /><img style="align:center; margin:0px 7px;" src="http://3.bp.blogspot.com/_9l0GmPwgCzk/SSyX3pxKmZI/AAAAAAAAAA0/_C8XsM5a50c/s400/search02.png" alt="" id="BLOGGER_PHOTO_ID_5272756246104676754" border="0" /><p>New Android developers often think that focusable in touch mode is the solution they need to "fix" the problem of disappearing selection/focus. We really encourage you to think very hard before using it. If used incorrectly, it can make your application behave differently from the rest of the system and simply throw off the user's habits. The Android framework contains all the tools you need to handle user interactions without using "focusable in touch mode". For example, instead of trying to make ListView always keep its selection, simply use the appropriate <a href="http://code.google.com/android/reference/android/widget/ListView.html#setChoiceMode%28int%29">choice mode</a>. And if you feel that the framework does not suit all your need, feel free to <a href="http://code.google.com/p/android/issues/list">let us know</a> or <a href="http://source.android.com/">contribute a patch</a>.</p><h4>Touch Mode Cheat Sheet</h4><p>Do:</p><ul><li>Remain consistent with the core applications</li><li>Use the appropriate feature if you need persistent selection (radio button, check box, ListView's choice mode, etc.)</li><li>Use focusable in touch mode if you write a game</li></ul><p></p><p>Don't:</p><ul><li>Do not try to keep the focus or selection in touch mode</li></ul><p></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-5479496956080163987?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/touch-mode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Android Photostream</title>
		<link>https://googledata.org/google-android/android-photostream/</link>
		<comments>https://googledata.org/google-android/android-photostream/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 16:15:00 +0000</pubDate>
		<dc:creator><![CDATA[Romain Guy]]></dc:creator>
				<category><![CDATA[Google Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[Google Mobile]]></category>
		<category><![CDATA[google os]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I'm pleased to announce that a new open source sample application—called Photostream—has been added to the apps-for-android project. Photostream is a simple photos browser and viewer for Flickr. All you need to use it is a Flickr screen name or use...]]></description>
				<content:encoded><![CDATA[<p>I'm pleased to announce that a new open source sample application—called <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/#trunk/Photostream">Photostream</a>—has been added to the <a title="apps-for-android" href="http://code.google.com/p/apps-for-android/">apps-for-android</a> project. Photostream is a simple photos browser and viewer for <a title="Flickr" href="http://www.flickr.com/">Flickr</a>. All you need to use it is a Flickr screen name or user name (the application offers a default user name if you just want to try it.)</p>
<div style="text-align: center;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/a/google.com/File?id=cf49fh6b_7g2sb4rc9_b" /></div>
<p>This application serves as an illustrative example of several Android features and APIs:</p>
<ul><li>Activity aliases</li>
<li>Adding custom shortcuts to Home</li>
<li>Adding a new wallpaper chooser to the system</li>
<li>Custom layouts</li>
<li>Custom XML attributes</li>
<li>Use of themes</li>
<li>Use of styles</li>
<li>Use of text colors</li>
<li>Use of &lt;include&gt;</li>
<li>Use of bitmap and layer drawables from XML</li>
<li>Use of <a href="http://code.google.com/android/reference/org/apache/http/client/package-summary.html">HttpClient</a></li>
<li>Proper interaction between background threads and the UI thread</li>
<li>Efficient display rotation (using the new <a href="http://code.google.com/android/reference/android/app/Activity.html#onRetainNonConfigurationInstance()">onRetainNonConfigurationInstance() API</a>)</li>
<li><a href="http://code.google.com/android/reference/android/view/animation/package-summary.html">Animations</a> and layout animations</li>
<li>Cropping an image</li>
<li><a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/ImageUtilities.java">Image manipulation</a></li></ul>

<div style="text-align: center;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/a/google.com/File?id=cf49fh6b_8gwtb5hhn_b" />
</div>

<p>My favorite feature is the ability to add a new shortcut type in Home, to create a shortcut to any Flickr account. The shortcut shows a custom icon, downloaded from the Flickr user profile:</p>

<div style="text-align: center;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/a/google.com/File?id=cf49fh6b_925vnnk3q_b" /> </div>
<div style="text-align: center;"><img style="width: 320px; height: 480px;" src="http://docs.google.com/a/google.com/File?id=cf49fh6b_10cczk7pfx_b" /></div>
<p>If you plan on reusing the source code to access Flickr in your own application, you should modify the <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/Flickr.java">Flickr.java file</a> to replace the existing API key with your own. The application source code also contains a very handy class called <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/UserTask.java">UserTask.java</a>. This class is designed to help you easily write background operations that interact with the UI thread.</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6755709643044947179-2182648497144682425?l=android-developers.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>https://googledata.org/google-android/android-photostream/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
