<?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>A Dash of Web and Mobile Development &#187; android</title>
	<atom:link href="http://blog.iangclifton.com/tag/android/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.iangclifton.com</link>
	<description>Discussing trends and technologies in web and mobile development</description>
	<lastBuildDate>Fri, 03 Feb 2012 05:15:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>An Android Lover&#8217;s Take On The iPhone 4S</title>
		<link>http://blog.iangclifton.com/2011/12/18/an-android-lovers-take-on-the-iphone-4s/</link>
		<comments>http://blog.iangclifton.com/2011/12/18/an-android-lovers-take-on-the-iphone-4s/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 02:57:24 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Mobile Devices]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[galaxy nexus]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[ice cream sandwich]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ios 5]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[parody]]></category>
		<category><![CDATA[sarcasm]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=526</guid>
		<description><![CDATA[So what about the iPhone 4S? First and foremost, the iPhone is way too small. The 3.5 inch screen is nice when I&#8217;m holding it 8 inches from my eye, but out and about it feels like my hands belong &#8230; <a href="http://blog.iangclifton.com/2011/12/18/an-android-lovers-take-on-the-iphone-4s/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>So what about the iPhone 4S?</p>
<p>First and foremost, the iPhone is way too small.  The 3.5 inch screen is nice when I&#8217;m holding it 8 inches from my eye, but out and about it feels like my hands belong to Andre the Giant.  I try to touch the screen and my thumb covers at least 10% of the surface area.  How can you have accurate touches like that?  I guess I should file down my thumbs and fingers.  It&#8217;s so tiny that it killed all two-handed operations for me (especially since you can barely fit two thumbs side by side).  I&#8217;ll admit that for some pockets, having a tiny screen is nice, but 4.3 inches might be better.  This is just too small.</p>
<p>While the screen is too small, I&#8217;m happy that Apple has stuck to their decision to have one button that does different things depending on what version of the OS you have and how many times you press it and even how slow your presses are.  It&#8217;s like opening a Christmas present every time I press the home button.  Will I go to the home screen?  The search screen?  The recent apps?  The Siri frontend for Wolfram Alpha?  The music app?</p>
<p>To be fair, the small screen on the iPhone did introduce me to some new people.  I heard that you can do a five-finger swipe to bring up the multitasking bar, but I couldn&#8217;t fit five fingers on the screen, so I had to go to Starbucks to find some fellow Apple users with smaller fingers to try.  Then I found out that gesture just works on iPad.  When will Apple develop a consistent user experience?</p>
<p>I like the missing software back button that is always in one place like on the Galaxy Nexus.  On the iPhone, you can have it sometimes be in the top left with the word &#8220;Back&#8221; or &#8220;Home&#8221; or something else, or at the top right with the word &#8220;Done&#8221; or at the bottom as a &#8220;Cancel&#8221; button.  This forces the user to be much more aware of the UI and whether something is a modal dialog, an action sheet, or whatever else.  (Of course, the iPhone still has a power/wake button on the top.)</p>
<p>I also like the lack of indicator light on the iPhone.  It&#8217;s helpful because I can make sure everyone knows I use Apple products since I have to always hold up my phone to turn it on to check for messages and people can see my important Apple logo and know that I&#8217;m creative.  Why Samsung included a multi-color indicator light that tells me exactly what I missed without turning on the device, I will never understand.</p>
<p>The rest of the iPhone hardware leaves something to be desired.  The Galaxy Nexus feels like a completely and thoughtfully designed product.  By comparison, the iPhone is made of glass, something we intuitively think of as fragile.  It&#8217;s also heavy/dense, giving it the consistant feeling of 80s technology that goes well with the click of the home button (or double click or long click or&#8230;).  It&#8217;s not awful, but you&#8217;d think Apple could do better at this point.  Some people will like not having the option to remove the back to get at the battery because that makes the iPhone almost as thin and as light as the Galaxy Nexus and gives you an excuse to buy a new phone every year.</p>
<p>The battery life itself is very good.  I felt like the iPhone was lasting at least as long as the Galaxy Nexus on a fully charged battery, perhaps even a bit longer in some cases.  Of course, I don&#8217;t have to worry about having the option of using it on 4G and possibly lowering the battery life.</p>
<p>The camera on the iPhone 4S is definitely worse than the Galaxy Nexus in both terms of front-facing camera (the 4S has a measly VGA camera and the Galaxy Nexus has a front-facing camera capable of 720p&#8230; a resolution the iPhone can&#8217;t even display) and in speed.  If you want to get a picture of where something exciting was happening two seconds ago, the iPhone 4S will not let you down.  Just press the shutter button when the scene is composed and you&#8217;ll get the scene that happens two seconds later.  It&#8217;s like time travel.</p>
<p>And let&#8217;s talk about iOS 5.  There is no question that the software is much improved over previous iterations in terms of copying Android&#8217;s notification system (though improved with X close buttons that are polished so much that they shrank to a size where you need a 2-year-old&#8217;s pinky to press them) and supporting Twitter.  You know an OS has improved when Twitter is a selling point.</p>
<p>Unfortunately, the system still lacks much of the features that Android users enjoy.  The majority of iOS users will probably think such criticism is bullshit, but that has always been the case.  I imagine it&#8217;s probably pretty hard for a person who bought the car that made the most sense to him or her to explain to the person who bought a Prius because it was popular how perception affects the driving experience.  The person with a personally-fitting car can attempt to explain why he or she likes a stick or more room, but the Prius owner will just believe that having the car pick gears for you is the best and would never spend enough time with any other car to appreciate the differences.</p>
<p>Still, if the iOS team ever wants to convert (or at least convice) most Android users, they still have quite a bit of work to do here.  Then again, they probably don&#8217;t (or shouldn&#8217;t) care too much about converting Android users over to iOS.  All the non-smartphone users out there remain the much bigger prize to go after (for both Apple and Google).</p>
<p>Other things that will sound like nits but drove me crazy with iOS 5 included having widgets only in the notification center.  If I am adding a widget, I clearly want to see it where I want it.  Why should I have to have it sit somewhere invisible that requires an extra swipe?  What&#8217;s the different between being on my homescreen and having to open a full weather app (iOS4) and being on the home screen and having to swipe down the notifications to see the weather widget (iOS5)?</p>
<p>Another: why do I have to go into the Google Voice app to make a phone call using my Google Voice number?  Google baked in support for alternate dialers into their OS; why didn&#8217;t Apple?  If they&#8217;re worried about competition, why did they finally approve the app after a year-and-a-half and an FCC inquiry?  Why is Siri letting people look at my private calendar while my phone is locked?  And why on Earth is the web browser not the desktop version of Safari yet!?</p>
<p>The new WiFi-syncing is nice &#8212; I love not having to find the proprietary cable.  But my god Apple needs help with iTunes.  I have to reboot my computer into an OS they support and leave it on while my phone is plugged into a power outlet.  As if iTunes weren&#8217;t already the worst software on the planet, I also have to waste a bunch of electricity keeping my computer on all the time in one of the two OSes Apple supports just to sync my data?</p>
<p>Apple&#8217;s universal support of voice dictation is a joke compared to Ice Cream Sandwich.</p>
<p>Some other authors have noted that iOS is ahead of Android when it comes to custom settings for apps, but I have to disagree.  Why do I have to leave an app to go find the settings app to change the settings for the app I was just in?  That&#8217;s completely illogical.  Of course, some apps support changing their settings within the app and others don&#8217;t, so now we get back to the inconsistancy problem present in the iOS experience.</p>
<p>When it comes to web browsers, arguably the most important feature of any of these devices, there is no question that Android still has a big edge here.  I&#8217;ve seen arguments on both sides for why iOS does not support third-party plugins&#8211;but doing a simple test proves that much of the web is still inaccessible from iOS.  Worse, many pages render as large missing tiles featuring a checkerbox to keep the illusion of scrolling smoothly, even beyond the point at which the actual page ends.  You try pinching to zoom and everything just stays fuzzy until your fingers stop moving.  How am I supposed to know if the text is large and clear enough if it just zooms in and out on fixed pixels?</p>
<p>You&#8217;ll also see a bit of impossibility in iOS when you do simple things like trying to attach a file to an existing email draft or trying to attach a second file or trying to store any arbitrary data on your device.  For the most part, iOS 5 does a good job of hiding its limitations, but there are plenty of times that you&#8217;ll still hit your head on a wall here and there.</p>
<p>The main problem I have with apps on iOS is that, well, they aren&#8217;t on iOS.  I try to find my favorite keyboard replacement (SwiftKey) and it&#8217;s nowhere to be found.  I try to get the ever-useful Wifi Analyzer, also not available.  I&#8217;ve heard that the entire experience has a lot more polish on iOS, especially with the Twitter integration, so I gave it a try.  I found one of my favorite links online and decided to open it on the Galaxy Nexus and the iPhone to verify it looked right.  For the Galaxy Nexus, I simply clicked the Chrome to Phone button and it instantly popped up on my device.  It looked good, so I long-pressed on the URL within the browser, picked share, selected my favorite Twitter app (hint: not the official one), and sent it with a tweet and a comment.  I tried that on iOS, which involved trying to type the long URL in by hand in the stock keyboard.  That was a pain, so I decided to long-press it in the Android browser again, share, and send it via Google Voice to the iPhone.  I opened it in the iPhone, it looked pretty much the same as on the Galaxy Nexus (though tiny), so I copied the URL, pressed the clicky home button (just once), scrolled to the right through ten screens of apps, opened a Twitter app, pasted it into the new tweet box along with a comment, and tweeted.</p>
<p>It&#8217;s these tangibles where Android holds the huge advantage.  And just like in sports, you can clearly teach the fundamentals.  At some point, Apple may simple have to acknowledge that Android works better than iOS because Android&#8217;s entire open concept is woven into the product.  Apps can properly communicate to each other without having to know of the other apps.  The user can do what he or she wants.  Even the launcher app can be replaced.  Apple&#8217;s strengths are elsewhere; they should embrace that.</p>
<p>Apple has done some very nice work here.  Both the iPhone 4S and iOS5 are a new pinnacle of the iOS platform.  But in the end, it still comes down to something very simple: which device do I want to use day-to-day?  Which phone do I reach for when I&#8217;m not doing a review?  It&#8217;s still an Android phone.  Without question.</p>
<p>Keep at it, Apple.</p>
<p>(For those who don&#8217;t know, this is a parody on the post MG Siegler did called &#8220;<a href="http://techcrunch.com/2011/12/14/iphone-galaxy-nexus-review/">An iPhone Lover&#8217;s Take On The Galaxy Nexus</a>.&#8221;  I strongly recommend that you buy the phone that makes the most sense to you, whether it&#8217;s an Android phone, an iPhone, a Windows phone, or whatever.  Any useful review will highlight the strengths and weaknesses of a given device and never tell you that it&#8217;s the one-size-fit-all solution.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/12/18/an-android-lovers-take-on-the-iphone-4s/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Current Job And Projects</title>
		<link>http://blog.iangclifton.com/2011/11/01/current-job-and-projects/</link>
		<comments>http://blog.iangclifton.com/2011/11/01/current-job-and-projects/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 05:01:23 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Opinion / Just Talking]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[career]]></category>
		<category><![CDATA[developer]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=517</guid>
		<description><![CDATA[I had expected to write this post quite a while ago. In fact, I mentioned my intent to write it at the end of my An Evolving Career Path post, but that career path changed more rapidly than I had &#8230; <a href="http://blog.iangclifton.com/2011/11/01/current-job-and-projects/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I had expected to write this post quite a while ago.  In fact, I mentioned my intent to write it at the end of my <a href="/2011/08/09/an-evolving-career-path/">An Evolving Career Path</a> post, but that career path changed more rapidly than I had expected.  I am still doing Android development, but I am not doing any web dev (other than my personal projects).  I&#8217;m also taking on some other projects&#8230; but I&#8217;ll get to that shortly.<span id="more-517"></span></p>
<p>At the end of July, I moved on from Treemo Labs.  I already had a one-month contract in place for some simple Android developer work, so I was not taking any time off (well, after the extent to which I had been working, dropping to 8 hours a day felt like taking time off).  CBS Interactive also contacted me and talked to me about the possibility of a position there.  I flew down to Los Angeles to quickly meet everyone and get a more detailed explanation of what they were looking for (and let them know what I was looking for).  It was a great trip, and I finally got to put faces to many of the names I had worked with while at Treemo Labs via email and conference calls.</p>
<p>After a bit of negotiation, I accepted a position at CBS Interactive as a mobile developer, and I started to pack up, reserve an apartment, etc.  That&#8217;s the position I alluded to at the end of the other post.  Well, things changed rather suddenly when some contract agreements got in the way (business protection agreement legalese) that removed the posibility of me holding that position.  It was an unfortunate and unexpected turn of events that forced me to take a seat and consider my options.</p>
<p>There is no shortage of mobile development positions out there, but I wasn&#8217;t interested in making unexciting apps and I started to question whether moving out of the Seattle area would be worth it for me.  I was bombarded by recruiter emails offering great clients, unbeatable opportunities, and pleas to contact all my developer friends on the recruiters&#8217; behalf.  A few were interesting on the surface, and I pursued them while simultaneously considering the possibility of working for myself full time.</p>
<p>I created wireframes and documentation for a game I decided to develop (and <a href="http://twitter.com/#!/IanGClifton/status/107955561080950784">tweeted about it</a>).  With my excitement for that app growing, I determined a timeline for the game with a <a href="http://twitter.com/#!/IanGClifton/status/108413952928649216">mid-October alpha</a> and calculated out how long I could live without income.  Things were looking very positive.  Even if I didn&#8217;t make much on the game, I had plenty of time to ensure it was done well before having to consider looking for a job.  If nothing else, it would teach me a lot and be another bullet on the resume.</p>
<p>Then I was contacted by <a href="http://aro.com/">ARO</a>, a stealth-mode startup in Seattle.  I was intrigued, so I interviewed and found out about their goals&#8211;definitely some exciting stuff that could push mobile beyond where it is today.  I received an offer from them the next day.  Considering their goals, offer, and ability to move fast (vital for anywhere I work), I accepted the position.</p>
<p>So, I am a salaried employee at ARO, working on some awesome stuff and, now that I have time outside of work as well, I&#8217;ve been taking on some outside projects.  I wrote about <a href="http://blog.iangclifton.com/2011/10/23/android-for-programmers-an-app-driven-approach/">reviewing Android for Programmers</a> recently.  I am also going to be creating an Android video series for developers (details to come) that I&#8217;m very excited about.  In the near future, the app I&#8217;ve been developing for <a href="http://androidpolice.com">Android Police</a> will be coming out, and then I&#8217;ll spend a little more time on the Disease to Dust game (though I don&#8217;t expect a beta this year).  I&#8217;m sure I&#8217;ll spend a little time here and there on other projects (such as prepping <a href="http://iangclifton.com/apps/android/predator-clock-widget/">Predator Clock Widget</a> for improvements), but life is good right now.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/11/01/current-job-and-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android for Programmers: An App-Driven Approach</title>
		<link>http://blog.iangclifton.com/2011/10/23/android-for-programmers-an-app-driven-approach/</link>
		<comments>http://blog.iangclifton.com/2011/10/23/android-for-programmers-an-app-driven-approach/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 18:57:59 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Mobile Development]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[programmers]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=506</guid>
		<description><![CDATA[For the past few months, I spent some of my off time working as a technical editor/reviewer for an Android book called &#8220;Android for Programmers: An App-Driven Approach.&#8221; From a reader&#8217;s perspective, this is a great book to dive right &#8230; <a href="http://blog.iangclifton.com/2011/10/23/android-for-programmers-an-app-driven-approach/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/10/androidfp1.jpg"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/10/androidfp1-114x150.jpg" alt="" title="Android for Programmers" width="114" height="150" class="alignleft size-thumbnail wp-image-510" /></a>For the past few months, I spent some of my off time working as a technical editor/reviewer for an Android book called &#8220;<a href="http://bit.ly/AndroidFP">Android for Programmers: An App-Driven Approach</a>.&#8221;  From a reader&#8217;s perspective, this is a great book to dive right into Android development because it actually creates an app in each chapter to explain specific concepts.  Other books often take the approach of pseudo-code or simplistic examples that demonstrate syntax but don&#8217;t really show how code is <em>actually used</em>.  Android for Programmers demonstrates each topic with real code.<span id="more-506"></span></p>
<p>As a reviewer, I found it interesting to see other people&#8217;s approaches, offering just a bit of guidance here and there to follow common/best practices used my most Android developers.  In one chapter in particular, you learn how to create a game called SpotOn that makes use of property animation (from Honeycomb) to create moving targets.  This is a great use of property animation that not only demonstrates a core feature in Honeycomb, it also shows how easily you can use the SDK to accomplish what would otherwise take a lot more code.</p>
<p>If you&#8217;re considering learning Android app development or know the basics but want to broaden your understanding, definitely take a look at <a href="http://bit.ly/AndroidFP">Android for Programmers: An App-Driven Approach</a>.  (And I don&#8217;t earn any royalties; I just love the &#8220;real code&#8221; approach that this book takes.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/10/23/android-for-programmers-an-app-driven-approach/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>RenderScript 101, Part 2: RenderScript Interaction</title>
		<link>http://blog.iangclifton.com/2011/08/24/renderscript-101-part-2-renderscript-interaction/</link>
		<comments>http://blog.iangclifton.com/2011/08/24/renderscript-101-part-2-renderscript-interaction/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 02:38:20 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[honeycomb]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[renderscript]]></category>
		<category><![CDATA[renderscript-tutorial-101]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=477</guid>
		<description><![CDATA[Note: This tutorial continues on from RenderScript 101, Part 1: RenderScript Basics Tutorial. If you have not yet read that tutorial, you should do so before starting this one. The previous tutorial ended with a simple app built that could &#8230; <a href="http://blog.iangclifton.com/2011/08/24/renderscript-101-part-2-renderscript-interaction/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><i>Note: This tutorial continues on from <a href="http://blog.iangclifton.com/2011/08/24/renderscript-101-part-1-renderscript-basics-tutorial/">RenderScript 101, Part 1: RenderScript Basics Tutorial</a>.  If you have not yet read that tutorial, you should do so before starting this one.</i></p>
<p>The previous tutorial ended with a simple app built that could display a green screen with RenderScript.  The next step to making RenderScript more useful is understanding how to interact with it when it&#8217;s already running.  We want to be able to pass values to the RenderScript code and we also want to pick up on user interactions with the view.<span id="more-477"></span></p>
<p>Since we already know how to set a background color within the <code>init</code> method in the RenderScript file, lets build on that by learning how to set it from the Java side.  Here&#8217;s where our <code>RenderScript101RS</code> class comes in handy.  Just add this method:</p>
<pre class="brush: java; title: ; notranslate">
	public void setBackgroundColor(Float4 color) {
		mScript.set_bgColor(color);
	}
</pre>
<p>This simple method takes a <a href="http://developer.android.com/reference/android/renderscript/Float4.html">Float4</a> and passes it directly to the <code>set_bgColor</code> method.  That method is automatically generated in the glue class and lets you set the <code>bgColor</code> value in <code>RenderScript101.rs</code> from Java.</p>
<p>In the <code>RenderScript101View</code>, we need to override onTouchEvent:</p>
<pre class="brush: java; title: ; notranslate">
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        if (mRenderScript == null) {
        	return true;
        }

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
        	final Random random = new Random();
        	final Float4 newColor = new Float4(random.nextFloat(), random.nextFloat(), random.nextFloat(), 1.0f);
        	mRenderScript.setBackgroundColor(newColor);
        }

        return true;
    }
</pre>
<p>If the <code>RenderScript101RS</code> reference is not yet set, don&#8217;t do anything.  If it is set, check to see if we&#8217;re getting an <code>ACTION_DOWN</code> event (e.g., touching the screen).  If we are, then we create a new <code>Float4</code> using three random float values and one hard-coded to 1.0f (the transparency/opacity to make sure it is fully opaque).  Then, we just trigger our newly created <code>setBackgroundColor</code> method with the generated <code>Float4</code>.</p>
<p>If you run the app now, you can tap the RenderScript view to watch it change colors.</p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/08/renderscript-tutorial-screenshot-02.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/08/renderscript-tutorial-screenshot-02-1024x640.png" alt="" title="RenderScript Tutorial Screenshot 02" width="640" height="400" class="aligncenter size-large wp-image-481" /></a></p>
<p>Well, that wasn&#8217;t too bad, was it?  The next part is going to be a bit more challenging, so we will have a crash course on computer graphics terminology.</p>
<h2>The Difficult Part</h2>
<p>Three-dimensional graphics revolve around vertices (vertex is the singular form).  These are essentially points in space that can be used to construct more complicated graphics.  Moving the vertices around is called &#8220;transformation.&#8221;  The mathematical construct that accomplishes this is called a &#8220;transformation matrix.&#8221;  There have been many, many books written on these concepts, so it&#8217;s impossible to condense everything down into a blog post; however, here are some specific terms for understanding RenderScript for Android:</p>
<ul>
<li><a href="http://developer.android.com/reference/android/renderscript/ProgramStore.html">ProgramStore</a> &#8211; This controls how the framebuffer is used.  For instance, you can enable or disable depth testing which controls what happens when one pixel is closer to the camera than another (e.g., whether it should blend or just overwrite).</li>
<li><a href="http://developer.android.com/reference/android/renderscript/Sampler.html">Sampler</a> &#8211; Samplers are used by ProgramFragments to determine how to get the pixels of a texture</li>
<li><a href="http://developer.android.com/reference/android/renderscript/ProgramFragment.html">ProgramFragment</a> &#8211; The Android-equivalent of a <a href="http://en.wikipedia.org/wiki/Pixel_shader">fragment shader</a></li>
<li><a href="http://developer.android.com/reference/android/renderscript/ProgramVertex.html">ProgramVertex</a> &#8211; The Android-equivalent of a <a href="http://en.wikipedia.org/wiki/Vertex_shader">vertex shader</a></li>
</ul>
<p>If you want to learn more about computer graphics, I recommend learning about OpenGL.  It&#8217;s extremely valuable to learn and many of the concepts from OpenGL apply to RenderScript.</p>
<p>Here is the updated <code>RenderScript101.rs</code> file:</p>
<pre class="brush: cpp; title: ; notranslate">
#pragma version(1)
#pragma rs java_package_name(com.iangclifton.tutorials.renderscript);

#include &quot;rs_graphics.rsh&quot;

float4 gBgColor; // Background color as xyzw 4-part float
rs_allocation gBgImage; // Background image
rs_sampler gLinearClamp; // Sampler used by the program fragment
rs_program_fragment gSingleTextureFragmentProgram; // fragment shader
rs_program_store gProgramStoreBlendNone; // blend none, depth none program store
rs_program_vertex gProgramVertex; // Default vertex shader

static const float3 gBgVertices[4] = {
        { -1.0, -1.0, -1.0 },
        { 1.0, -1.0, -1.0 },
        { 1.0, 1.0, -1.0 },
        {-1.0, 1.0, -1.0 }
};

static void drawBackground() {
	if (gBgImage.p != 0) {
		rs_matrix4x4 projection, model;
		rsMatrixLoadOrtho(&amp;projection, -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f);
		rsgProgramVertexLoadProjectionMatrix(&amp;projection);

		rsMatrixLoadIdentity(&amp;model);
		rsgProgramVertexLoadModelMatrix(&amp;model);

		rsgBindTexture(gSingleTextureFragmentProgram, 0, gBgImage);

	    rsgDrawQuad(
			gBgVertices[0].x, gBgVertices[0].y, gBgVertices[0].z,
			gBgVertices[1].x, gBgVertices[1].y, gBgVertices[0].z,
			gBgVertices[2].x, gBgVertices[2].y, gBgVertices[0].z,
			gBgVertices[3].x, gBgVertices[3].y, gBgVertices[0].z
		);
	} else {
		rsgClearColor(gBgColor.x, gBgColor.y, gBgColor.z, gBgColor.w);
	}
}

void init() {
	gBgColor = (float4) { 0.0f, 1.0f, 0.0f, 1.0f };
	rsDebug(&quot;Called init&quot;, rsUptimeMillis());
}

int root() {
	rsgBindProgramVertex(gProgramVertex);
	rsgBindProgramFragment(gSingleTextureFragmentProgram);
	rsgBindProgramStore(gProgramStoreBlendNone);

	drawBackground();
	return 16;
}
</pre>
<p>Note that I&#8217;ve updated all of the global variables to start with &#8220;g&#8221; in order to keep things a bit more clear.  The <code>root()</code> method has been updated to bind the <code>ProgramVertex</code>, <code>ProgramFragment</code>, and <code>ProgramStore</code> right away.  Looking at the <code>drawBackground()</code> method, you can see that the old code falls under the <code>else</code> statement.  Everything else happens when <code>gBgImage.p</code> is not equal to zero (in other words, the <code>gBgImage</code> has been set).</p>
<p>We create a four-by-four projection matrix and model matrix.  The projection matrix is passed by reference and is turned into an orthographic matrix with <code>rsMatrixLoadOrtho</code>.  An orthographic matrix is essentially a flat representation of points in space (e.g., the <acronym title="Heads-up Display">HUD</acronym> in a first-person shooter</acronym>).  Most commonly, the points are -1 to +1 in each dimension (though we use 0-1 for one here).  In graphics hardware, it is common to represent everything with floats because they give more precision than an arbitrary system (e.g., think of how colors are commonly represented by 0-255; in OpenGL and other languages, they are represented by floats because hardware can create an unknown number of unique colors in the future).  Then the matrix is passed to <code>rsgProgramVertexLoadProjectionMatrix</code> so that the 3D points can be flattened to 2D points.</p>
<p>We pass <code>model</code> by reference to <code>rsMatrixLoadIdentity</code> which makes <code>model</code> an <a href="http://en.wikipedia.org/wiki/Identity_matrix">identity matrix</a>.  An identity matrix is essentially a matrix that does not affect other matrices in multiplication (think of it like a 1 where 1 times X results in X).  With this identity matrix, we call <code>rsgProgramVertexLoadModelMatrix</code> to avoid manipulating the vertices.</p>
<p>Next, we call <code>rsgBindTexture</code>, which takes a program fragment, an unsigned <code>int</code> (slot), and an <code>rs_allocation</code>.  This is essentially where we are setting up our texture (<code>Bitmap</code>) to be drawn.  Now that the texture has been set up, we can draw the quad on which it will appear.  The <code>gBgVertices</code> are defined on lines 13-18 but we&#8217;re essentially passing the top left, top right, bottom left, and bottom right points of the screen.  The Z position for all of them is -1, which we set as the maximum Z-depth in our <code>rsMatrixLoadOrtho</code> call.  Therefore, this texture spans the whole view but appears at the very &#8220;back&#8221; of it.</p>
<p>Now we have to update <code>RenderScript101RS</code> to set these new values:</p>
<pre class="brush: java; title: ; notranslate">
package com.iangclifton.tutorials.renderscript;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Float4;
import android.renderscript.Matrix4f;
import android.renderscript.ProgramFragment;
import android.renderscript.ProgramFragmentFixedFunction;
import android.renderscript.ProgramStore;
import android.renderscript.ProgramVertex;
import android.renderscript.ProgramVertexFixedFunction;
import android.renderscript.RenderScriptGL;
import android.renderscript.Sampler;

public class RenderScript101RS {

	private Sampler mLinearClamp;
    private ProgramStore mProgramStoreBlendNone;
    private ProgramVertex mProgramVertex;
	private RenderScriptGL mRS;
	private ScriptC_RenderScript101 mScript;
    private ProgramFragment mSingleTextureFragmentProgram;

	public RenderScript101RS(RenderScriptGL rs, Resources res, int resId) {
		mRS = rs;
		mScript = new ScriptC_RenderScript101(rs, res, resId);

		initProgramStore();
		initSampler();
		initProgramFragment();
		initProgramVertex();
		mRS.bindRootScript(mScript);

	}

	public void setBackgroundBitmap(Bitmap bitmap) {
		if (bitmap == null) {
			return;
		}
		final Allocation bitmapAllocation = Allocation.createFromBitmap(mRS, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);
		mScript.set_gBgImage(bitmapAllocation);
	}

	public void setBackgroundColor(Float4 color) {
		mScript.set_gBgColor(color);
	}

	private void initProgramFragment() {
        final ProgramFragmentFixedFunction.Builder pfBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
        pfBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
        mSingleTextureFragmentProgram = pfBuilder.create();
        mScript.set_gSingleTextureFragmentProgram(mSingleTextureFragmentProgram);
	}

    private void initProgramStore() {
        mProgramStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS);
        mScript.set_gProgramStoreBlendNone(mProgramStoreBlendNone);
    }

	private void initProgramVertex() {
        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
        mProgramVertex = pvb.create();
        ProgramVertexFixedFunction.Constants pva = new ProgramVertexFixedFunction.Constants(mRS);
        ((ProgramVertexFixedFunction)mProgramVertex).bindConstants(pva);
        Matrix4f proj = new Matrix4f();
        proj.loadProjectionNormalized(1, 1);
        pva.setProjection(proj);
        mScript.set_gProgramVertex(mProgramVertex);
	}

	private void initSampler() {
		mLinearClamp = Sampler.CLAMP_LINEAR(mRS);
		mScript.set_gLinearClamp(mLinearClamp);
	}
}
</pre>
<p>Looking at the constructor, we can see that first the <code>ProgramStore</code> is initialized, then the <code>Sampler</code>, then the <code>ProgramFragment</code>, and finally the <code>ProgramVertex</code>.  Each of these has an <code>init___</code> method that you can look at.  The <code>initProgramStore</code> just sets a <code>ProgramStore</code> that does no blending and no depth testing since they are not needed for the background.  Then <code>initSampler</code> just creates a <code>CLAMP_LINEAR</code> <code>Sampler</code>.  The <code>initProgramFragment</code> method creates a simple fragment shader.  Lastly, the <code>initProgramVertex</code> method creates a simple <code>ProgramVertexFixedFunction</code> (vertex shader) without any custom GLSL.</p>
<p>If you&#8217;ve never done any OpenGL or other 3D computer graphics, you&#8217;re probably lost by now.  Sorry!  It would take a few hundred pages to truly clarify all of this, but hopefully some of it is making sense.</p>
<p>Finally, we just updated the <code>RenderScript101View</code> class&#8217;s <code>onTouchEvent</code> method:</p>
<pre class="brush: java; title: ; notranslate">
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        if (mRenderScript == null) {
        	return true;
        }

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
        	mRenderScript.setBackgroundBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
        }

        return true;
    }
</pre>
<p>We simply update this method so that tapping the view will set the background <code>Bitmap</code> to the default icon.  Yup, it looks terrible, but you&#8217;ve now experimented with the key features of RenderScript and you might even understand a thing or two.</p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/08/renderscript-tutorial-screenshot-03.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/08/renderscript-tutorial-screenshot-03-1024x640.png" alt="" title="RenderScript Tutorial Screenshot 03" width="640" height="400" class="aligncenter size-large wp-image-486" /></a></p>
<p>Note: The <a href="https://github.com/IanGClifton/Android-RenderScript-Tutorials">source code</a> for this tutorial is available in on GitHub.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/08/24/renderscript-101-part-2-renderscript-interaction/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>RenderScript 101, Part 1: RenderScript Basics Tutorial</title>
		<link>http://blog.iangclifton.com/2011/08/24/renderscript-101-part-1-renderscript-basics-tutorial/</link>
		<comments>http://blog.iangclifton.com/2011/08/24/renderscript-101-part-1-renderscript-basics-tutorial/#comments</comments>
		<pubDate>Wed, 24 Aug 2011 22:33:05 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[honeycomb]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[renderscript]]></category>
		<category><![CDATA[renderscript-tutorial-101]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=464</guid>
		<description><![CDATA[A couple of months ago, I had to do a lot of work with RenderScript. Unfortunately, there was not much documentation available then and there isn&#8217;t much more now. The purpose of this post is to provide the foundations for &#8230; <a href="http://blog.iangclifton.com/2011/08/24/renderscript-101-part-1-renderscript-basics-tutorial/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A couple of months ago, I had to do a lot of work with RenderScript.  Unfortunately, there was not much documentation available then and there isn&#8217;t much more now.  The purpose of this post is to provide the foundations for actually using RenderScript for graphical purposes.  You should have already read about RenderScript and understand the overall concept (just not necessarily implementation details).  I assume that you know Android and Java and aren&#8217;t scared of some basic C-style code.  An understanding of computer graphics (or a graphics library such as OpenGL) definitely helps but is not a requirement.<span id="more-464"></span></p>
<p>We&#8217;ll be creating four files:</p>
<ul>
<li>RenderScript101.rs &#8211; The actual RenderScript code</li>
<li>RenderScript101RS.java &#8211; A helper class to simplify interaction with RenderScript</li>
<li>RenderScript101View.java &#8211; An RSSurfaceView that handles setting up the view and can capture touch events</li>
<li>RenderScript101Activity.java &#8211; Main Activity and it&#8217;s even simpler than a typical one</li>
</ul>
<p>When you create a new project, select a target of at least 11 and let Eclipse generate the Activity for you (ignore it for now).  We&#8217;re diving right into the actual RenderScript code, so create the <code>RenderScript101.rs</code> text file (in the same folder/package as the Activity).  The first things we have to do are to specify the version of RenderScript we&#8217;re using (1) and specify the package (I&#8217;m using <code>com.iangclifton.tutorials.renderscript</code>).</p>
<pre class="brush: cpp; title: ; notranslate">
#pragma version(1)
#pragma rs java_package_name(com.iangclifton.tutorials.renderscript);

#include &quot;rs_graphics.rsh&quot;

float4 bgColor; // Background color as xyzw 4-part float

static void drawBackground() {
	rsgClearColor(bgColor.x, bgColor.y, bgColor.z, bgColor.w);
}

void init() {
	bgColor = (float4) { 0.0f, 1.0f, 0.0f, 1.0f };
	rsDebug(&quot;Called init&quot;, rsUptimeMillis());
}

int root() {
	drawBackground();
	return 16;
}
</pre>
<p>When your RenderScript code is first initialized, the <code>init()</code> method will run once.  Then the <code>root()</code> method will run repeatedly.  The return value for the <code>root</code> method is an int specifying the number of milliseconds before <code>root()</code> should run again.</p>
<p>Looking first at <code>init()</code>, you can see we are setting the <code>bgColor</code> (a 4-part float defined on line 6) to 0, 1, 0, 1.  This is in RGBA format, so we&#8217;re saying no red, maximum green, no blue, and full opacity.  In the next line we call <code>rsDebug</code> with the message &#8220;Called init&#8221; and the current uptime in milliseconds.  Think of this as an easy way to call <code>Log.d("RenderScript", your_message_here)</code>.  This call is not necessary, but you should definitely get used to adding debug messages into your RenderScript early on.  For reference, <code>rsDebug</code> is defined in <code>rs_core.rsh</code> and <code>rsUptimeMillis</code> is defined in <code>rs_time.rsh</code> (both are available in your sdk directory under <code>platforms/android-11/renderscript/include</code> and are included automatically for you).</p>
<p>Jumping down to the <code>root</code> method, we see that it calls <code>drawBackground()</code> and returns 16 (16ms for a frame is close to 60 frames per second).  The drawBackground() call only does one thing right now; it clears the screen using the <code>bgColor</code> we set in <code>init()</code>.  The <code>rsgClearColor</code> method takes four floats (R, G, B, A) and is defined in <code>rs_graphics.rsh</code>.  Remember that RenderScript can also be used for calculations, so you have to specifically include the graphics header file (line 4).  If you&#8217;re new to computer graphics, the use of the x, y, z, and w properties of <code>bgColor</code> might seem strange.  Without getting into the details, this is a convention in graphics where a four-part float is represented with these four letters (as you can probably guess, x, y, and z are typically coordinates.  The w is usually for projection where the values are actually represented as x/w, y/w, and z/w.  There&#8217;s a lot more to it than that, but the important part is knowing the letters right now).</p>
<p>Alright, so all that code does is define a background color from four floats (x, y, z, and w) and then it clears the screen to that color every 16-ish milliseconds.  Pretty simple, but it&#8217;s a good start.</p>
<p>Next, you want to create the <code>RenderScript101RS.java</code> file to simplify interaction with the RenderScript.  It should look like this:</p>
<pre class="brush: java; title: ; notranslate">
package com.iangclifton.tutorials.renderscript;

import android.content.res.Resources;
import android.renderscript.RenderScriptGL;

public class RenderScript101RS {
    private RenderScriptGL mRS;
    private ScriptC_RenderScript101 mScript;

    public RenderScript101RS(RenderScriptGL rs, Resources res, int resId) {
    	mRS = rs;
    	mScript = new ScriptC_RenderScript101(rs, res, resId);
    	mRS.bindRootScript(mScript);
    }
}
</pre>
<p>All we are doing for now is setting a reference to the <a href="http://developer.android.com/reference/android/renderscript/RenderScriptGL.html">RenderScriptGL</a> (the graphics derivative of RenderScript), instantiating the &#8220;glue&#8221; class <code>ScriptC_RenderScript101</code>, and binding the script.  The glue class is generated for you by Eclipse.  If you have automatic builds on and saved the <code>.rs</code> file we just worked on, you might have noticed the class being added to the gen folder along with your <code>R</code> class.  This glue class lets you interact with your RenderScript code via Java (such as if you want to set the background color from Java instead of within the RenderScript).  We&#8217;ll get to it later.  The <code>bindRootScript()</code> method simply tells Android which script should handle rendering to the surface.</p>
<p>Next up, <code>RenderScript101View.java</code>:</p>
<pre class="brush: java; title: ; notranslate">
package com.iangclifton.tutorials.renderscript;

import android.content.Context;
import android.renderscript.RSSurfaceView;
import android.renderscript.RenderScriptGL;

public class RenderScript101View extends RSSurfaceView {
	private Context mContext;
	private RenderScript101RS mRenderScript;
	private RenderScriptGL mRS;

	public RenderScript101View(Context context) {
	    super(context);
	    mContext = context;
	    ensureRenderScript();
    }

	private void ensureRenderScript() {
		if (mRS == null) {
			final RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
			mRS = createRenderScriptGL(sc);
		}
		if (mRenderScript == null) {
			mRenderScript = new RenderScript101RS(mRS, mContext.getResources(), R.raw.renderscript101);
		}
	}
}
</pre>
<p>This is the <a href="http://developer.android.com/reference/android/renderscript/RSSurfaceView.html">RSSurfaceView</a> that essentially works like other views in Android.  In fact, it extends <a href="http://developer.android.com/reference/android/view/SurfaceView.html">SurfaceView</a>, so if you&#8217;ve used SurfaceView or <a href="http://developer.android.com/reference/android/opengl/GLSurfaceView.html">GLSurfaceView</a>, you have a pretty good idea of what this is.</p>
<p>All we&#8217;re doing here is following the convention of having an <code>ensureRenderScript()</code> method that sets up the RenderScriptGL and <code>RenderScript101RS</code> class instances.  This method can be called when the view is first set up or when it changes.  If <code>mRS</code> is null, we create a <a href="http://developer.android.com/reference/android/renderscript/RenderScriptGL.SurfaceConfig.html">SurfaceConfig</a> (this can be used to control the bit-depth for colors, the depth buffer, etc., but we&#8217;re just using the defaults).  We use the <code>SurfaceConfig</code> in our call to <code>createRenderScriptGL()</code> to generate the <code>RenderScriptGL</code>.  If the <code>mRenderScript</code> reference is null, we simply construct a new one by passing the <code>RenderScriptGL</code>, a reference to the <a href="http://developer.android.com/reference/android/content/res/Resources.html">Resources</a>, and the resource identifier for our RenderScript file (this bytecode file is automatically generated for you in res/raw).</p>
<p>And, finally, <code>RenderScript101Activity.java</code>:</p>
<pre class="brush: java; title: ; notranslate">
package com.iangclifton.tutorials.renderscript;

import android.app.Activity;
import android.os.Bundle;

public class RenderScript101Activity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new RenderScript101View(this));
    }
}
</pre>
<p>Yeah, that&#8217;s all there is to this <code>Activity</code>.  We&#8217;re simply constructing a new <code>RenderScript101View</code> and using it as the layout.  Run the app on your Honeycomb device and you should see a horrendous green screen like this:</p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/08/renderscript-tutorial-screenshot-01.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/08/renderscript-tutorial-screenshot-01-1024x640.png" alt="" title="RenderScript Tutorial Screenshot" width="640" height="400" class="aligncenter size-large wp-image-470" /></a></p>
<p>If your eyes are burning, you did it right.  If you don&#8217;t see a green screen, check DDMS for anything suspicious in the logs.</p>
<p>That concludes part one of the RenderScript 101 tutorial.  Next up, <a href="http://blog.iangclifton.com/2011/08/24/renderscript-101-part-2-renderscript-interaction/">RenderScript 101, Part 2: RenderScript Interaction</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/08/24/renderscript-101-part-1-renderscript-basics-tutorial/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An Evolving Career Path</title>
		<link>http://blog.iangclifton.com/2011/08/09/an-evolving-career-path/</link>
		<comments>http://blog.iangclifton.com/2011/08/09/an-evolving-career-path/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 01:44:10 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Opinion / Just Talking]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[career]]></category>
		<category><![CDATA[developer]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=458</guid>
		<description><![CDATA[As you can probably guess, I&#8217;ve always been interested in technology.  My career didn&#8217;t lead directly to mobile development though. I worked with tactical satellite communications in the Air Force and even earned a degree and certification for teaching English &#8230; <a href="http://blog.iangclifton.com/2011/08/09/an-evolving-career-path/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As you can probably guess, I&#8217;ve always been interested in technology.  My career didn&#8217;t lead directly to mobile development though.  I worked with tactical satellite communications in the Air Force and even earned a degree and certification for teaching English at the secondary level (essentially, high school).<span id="more-458"></span></p>
<p>I ended up at Treemo Labs by way of a buddy I had worked with at Western Washington University where we were web developers.  I had finished my teaching internship, but the economy was weak and teaching jobs (particularly for someone with such limited experience) were not easy to come by.  Fortunately, I started up at Treemo doing web development and ended up leaning toward my current passion, mobile development.</p>
<p>I truly enjoy learning and tackling new challenges as well as working with technology and sharing that knowledge and experience with others.  One of the great things about mobile development is the unbelievable pace of change.  It wasn&#8217;t long ago that I could name all relevant Android devices and their specs, now it&#8217;s simply impossible to keep up.  Now I focus more on the software side of things, playing with all the newest OS features both announced and slipped in.</p>
<p>When I started at Treemo, the G1 and iPhone 3G were the primary devices.  The G1 could do far more than the iPhone and even had some features current iPhones still don&#8217;t have, but the iPhone&#8217;s narrower list of capabilities was generally executed much more smoothly.  The contrast was intriguing to me&#8211;and still is.  In 2009, we saw the Palm Pre come and go, the 3G update to the 3GS, and the G1&#8242;s angular cousin, the Motorola Droid, take off.  I had the opportunity to work with all of these devices and many more while at Treemo.  I also got to see the evolution of my skills alongside these changing devices.  I worked on the CBS News app for both Android and iOS as my intro into mobile development, not a bad start!  I developed a variety of Android apps (CNET News, Survivor, Rick Steves&#8217; Audio Europe, etc.), learning from each experience.  Even the last app I developed at Treemo Labs was an opportunity to learn and grow; developing Big Brother gave me the chance to learn more about Honeycomb (and RenderScript in particular) than I would have thought possible, given the time constraints.</p>
<p>As much as I enjoyed working with the people at Treemo, it came time for me to move on.  I won&#8217;t go into the details, but a lot of signs pointed to the need for a change.  Fortunately, Android developers are in high demand, and an excellent opportunity has already come my way.  I&#8217;ll have a separate post about that later on.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/08/09/an-evolving-career-path/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Asus Transformer Review</title>
		<link>http://blog.iangclifton.com/2011/07/17/asus-transformer-review/</link>
		<comments>http://blog.iangclifton.com/2011/07/17/asus-transformer-review/#comments</comments>
		<pubDate>Sun, 17 Jul 2011 19:29:25 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Mobile Devices]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[asus]]></category>
		<category><![CDATA[eee pad]]></category>
		<category><![CDATA[honeycomb]]></category>
		<category><![CDATA[tablet]]></category>
		<category><![CDATA[transformer]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=452</guid>
		<description><![CDATA[I received my Asus Eee Pad Transformer more than a month ago, and I have to say that I am very impressed with it. The ability to add on the keyboard dock adds a huge amount of value to the &#8230; <a href="http://blog.iangclifton.com/2011/07/17/asus-transformer-review/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I received my Asus Eee Pad Transformer more than a month ago, and I have to say that I am very impressed with it. The ability to add on the keyboard dock adds a huge amount of value to the device, allowing for productivity that is not matched by stand-alone tablets. Of course, there are times when the tablet alone is better (such as for presentations or certain games), and the Transformer makes it easy to pull the tablet out of the dock and just keep using it.</p>
<p>I wrote a review called <a href="http://www.androidpolice.com/2011/07/15/review-asus-transformer-more-than-a-month-with-a-tablet-in-disguise/">[Review] ASUS Eee Pad Transformer &#8211; A Month With A Tablet In Disguise</a> at <a href="http://www.androidpolice.com/">Android Police</a>, so I will not go into excessive detail here. If you are looking for a tablet that can actually be used to create real content, particularly for typing on the go, take a look at the Asus Eee Pad Transformer.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/07/17/asus-transformer-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Android Developer Mistakes</title>
		<link>http://blog.iangclifton.com/2011/05/22/simple-android-developer-mistakes/</link>
		<comments>http://blog.iangclifton.com/2011/05/22/simple-android-developer-mistakes/#comments</comments>
		<pubDate>Mon, 23 May 2011 02:42:49 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Mobile Development]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[density]]></category>
		<category><![CDATA[emulator]]></category>
		<category><![CDATA[linearlayout]]></category>
		<category><![CDATA[listview]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=433</guid>
		<description><![CDATA[I would really like to write more tips, tricks, and tutorial posts relating to Android, but I&#8217;ve been extremely busy on apps both professionally and personally, and I am also doing technical review on an Android dev book due out &#8230; <a href="http://blog.iangclifton.com/2011/05/22/simple-android-developer-mistakes/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I would really like to write more tips, tricks, and tutorial posts relating to Android, but I&#8217;ve been extremely busy on apps both professionally and personally, and I am also doing technical review on an Android dev book due out later this year.  So, while I don&#8217;t have time to go in the level of depth I&#8217;d like to, I thought I could work on a post with a bunch of short pieces that could be written when I have a few free minutes here and there and save the longer posts that require a greater chunk of continuous focus for later.  This post talks about some challenges that you may run into early in your foray into Android development.  There isn&#8217;t really any sense of order to these; they&#8217;re more-or-less a brain dump of issues I&#8217;ve experienced or seen that take seconds to solve if you know what you&#8217;re doing or hours if you don&#8217;t.<span id="more-433"></span></p>
<h2>OMG! The emulator is slow!</h2>
<p>There are two things to note here: the default <acronym title="Android Virtual Device">AVD</acronym>s tend to have limited resources and the devices you&#8217;re targeting are likely running with a different chipset than the computer you&#8217;re developing on.  The first limitation can be easily overcome; the second is a much bigger issue, particularly with Android 3.x and attempting to develop for Honeycomb tablets without actually having a Xoom, Asus Eee Pad Transformer, etc.  Currently, it&#8217;s not very feasible to develop a 3.x app without a tablet.</p>
<p>Back to that first limitation: When creating a new AVD, you can specify hardware settings, which can dramatically improve performance.  The most important setting is the device RAM size; I tend to want the emulator to be as fast as possible, relying on on-device testing for a sense of &#8220;real-world speed,&#8221; so I usually give my phone emulators 512MB of RAM.  That&#8217;s the equivalent of most good smartphones from 2010.  The 1.x AVDs seem to run fine on 256MB, so you can potentially drop to that if your machine is limited (the Motorola Droid/Milestone had 256MB of RAM as well).  You can also try upping the cache partition size (128MB is a good start) and the max VM application heap size (48 is plenty) for a minor improvement.</p>
<h2>LinearLayout mistakes</h2>
<p>LinearLayout is a very useful and very simple ViewGroup.  It essentially puts one View after another either horizontally or vertically, depending on the orientation you have set.  <strong>Set an orientation!</strong></p>
<p>LinearLayout defaults to horizontal, but you should always manually specify an orientation.  It&#8217;s very easy to throw two Views in there and not see one because the first View is set to match_parent for width.  That said, LinearLayout also processes layouts linearly, which is what you&#8217;d expect, but that means that setting a child View to match_parent can leave no room for subsequent Views.  If you aren&#8217;t seeing one of your Views in a LinearLayout, verify you&#8217;ve set the orientation and that none of the Views are taking up all the available space.  Within a LinearLayout, you should generally rely on layout_weight to &#8220;grow&#8221; the View.  Here&#8217;s an example:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout
  xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
  android:layout_height=&quot;match_parent&quot;
  android:layout_width=&quot;match_parent&quot;
  android:orientation=&quot;vertical&quot;
&gt;
    &lt;SomeView
      android:id=&quot;@+id/childview1&quot;
      android:layout_height=&quot;0px&quot;
      android:layout_weight=&quot;2&quot;
      android:layout_width=&quot;match_parent&quot;
    /&gt;

    &lt;SomeView
      android:id=&quot;@+id/childview2&quot;
      android:layout_height=&quot;0px&quot;
      android:layout_weight=&quot;3&quot;
      android:layout_width=&quot;match_parent&quot;
    /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>The heights are set to 0, but both child Views have weights.  The first has a weight of 2 and the second has a weight of 3.  Out of a total of 5, the first is taking 2 (40%) and the second gets 3 (60%), so their heights will actually use that portion of the parent View&#8217;s space (if that View has a 100px height, the first child will be 40px tall).  The weights are relative, so you can set whatever values make sense for you.  In this example, the second layout could have had a set height and no weight and the first could have had a weight of 1, which would have made the first take up all space that the second didn&#8217;t use.</p>
<h2>Stupid Android!  It keeps restarting my Activity!</h2>
<p>The default behavior when a configuration change happens (e.g., orientation change, sliding out the keyboard, etc.) is to finish the current Activity and restart it with the new configuration.  If you&#8217;re not getting any dynamic data, such as loading content from the web, this means you probably don&#8217;t have to do any work to support configuration changes; however, if you are loading other data, you need to pass it between configuration changes.  Fortunately, there&#8217;s already a great post on <a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Faster screen orientation change</a>s.  Read it and remember that you should not pass anything via the config change methods that is tied to the Activity or Context.</p>
<h2>Density</h2>
<p>Density should only be considered in terms of density <em>not</em> size.  In other words, don&#8217;t decide that MDPI means 320px wide.  It doesn&#8217;t.  It means that the device has around 160dpi like the G1 (320px wide) and the Xoom (1280px wide).  Fortunately, you can combine multiple qualifiers for your folders to give precise control, so you can have a drawable-large-land-hdpi/ containing only drawables that are used on large HDPI devices that are in landscape orientation.</p>
<p>One other important thing to note: Support for different screen sizes and densities came in Android 1.6.  Android 1.5 devices are all MDPI devices, but they don&#8217;t know to look in drawable-mdpi/ because there were no different densities then.  So, if you&#8217;re supporting Android 1.5, your MDPI drawables should go in drawables/.  If your minSdkVersion is 1.6 or above, put the MDPI drawables in drawable-mdpi/.</p>
<h2>What the heck is ListView doing?</h2>
<p>A full explanation of ListView would take quite a while, but here&#8217;s a quick summary: A ListView&#8217;s associated Adapter&#8217;s getView method is called for each child View it needs to construct to fill the ListView.  If you scroll down, the top View that leaves the screen is not garbage collected but is instead passed back to the getView method as the &#8220;convertView&#8221; (second param).  Use this View!  If you don&#8217;t, not only does it need to be garbage collected, you have to inflate new Views.  You should also use the ViewHolder paradigm where you use a simple class to store View references to avoid constant findViewById() calls.  Here&#8217;s an example:</p>
<pre class="brush: java; title: ; notranslate">

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.some_layout, null);
        holder = new ViewHolder();
        holder.thumbnail = (ImageView) convertView.findViewById(R.id.thumbnail);
        holder.title = (TextView) convertView.findViewById(R.id.title);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    final MyObject obj = (MyObject) getItem(position);
    holder.thumbnail.setImageDrawable(obj.getThumbnail());
    holder.title.setText(Html.fromHtml(obj.getTitle()));

    return convertView;
}

/**
 * Static ViewHolder class for retaining View references
 */
private static class ViewHolder {
    ImageView thumbnail;
    TextView title;
}
</pre>
<p>This method is first checking if the convertView exists (when the ListView is first laid out, convertView will not exist).  If it doesn&#8217;t exist, a new layout is inflated with the LayoutInflater.  A ViewHolder object is instantiated and the View references are set.  Then, the holder is assigned to the View with the setTag method (which essentially allows you to associate an arbitrary object with a View).  If the convertView already exists, all that has already been done, so you just have to call getTag() to pull that ViewHolder out.  The &#8220;bulk&#8221; of the method is just grabbing MyObject (whatever object your Adapter is connecting to) and setting the thumbnail ImageView and the title TextView.  You could also make the ViewHolder fields final and set them in the constructor, but I tried to keep this example as simple as possible.  This method no longer requires View inflation while scrolling nor does it require looking through the Views for specific IDs each time.  This little bit of work can make a huge different on scrolling smoothness.</p>
<p>One last thing about ListViews&#8230; <strong>never set the height of a ListView to wrap_content</strong>.  If you have all your data locally available, it might not seem so bad, but it becomes particularly troublesome when you don&#8217;t.  Consider the above example but instead of the setImageDrawable call, it triggers an image download (though it&#8217;s better to have the Adapter handle that).  If you use wrap_content on your ListView, this is what happens:  The first getView call is done, convertView is null, and position 0 is loaded.  Now, position 1 is loaded, but it is passed the View you just generated for position 0 as its convertView.  Then position 2 is loaded with that same View, and so on.  This is done to lay out the ListView since it has to figure out how tall it should be and you didn&#8217;t explicitly tell it.   Once it has run through all of those positions, that View is passed back to position 0 for yet another getView call, and then position 1 and on are loaded with getView and no convertView.  You&#8217;re going to end up seeing getView called two or three times as often as you would have expected.  Not only does that suck for performance, but you can get some really confusing issues (e.g., if you had been passing a reference to an ImageView with an image download request, that same ImageView could be tied to all of the download requests, causing it to flicker through the images as they return).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/05/22/simple-android-developer-mistakes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Android Layout Optimization: TextViews</title>
		<link>http://blog.iangclifton.com/2011/04/06/android-layout-optimization-textviews/</link>
		<comments>http://blog.iangclifton.com/2011/04/06/android-layout-optimization-textviews/#comments</comments>
		<pubDate>Wed, 06 Apr 2011 07:19:47 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[hierarchy viewer]]></category>
		<category><![CDATA[imageview]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[linearlayout]]></category>
		<category><![CDATA[relativelayout]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=421</guid>
		<description><![CDATA[One of the best things you can study when first learning Android is how to approach layouts in a way that keeps them simple and logical. Typically, you start with learning LinearLayouts and Views that commonly go in those (TextView, &#8230; <a href="http://blog.iangclifton.com/2011/04/06/android-layout-optimization-textviews/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the best things you can study when first learning Android is how to approach layouts in a way that keeps them simple and logical.  Typically, you start with learning LinearLayouts and Views that commonly go in those (TextView, ImageView, etc.).  The next thing to learn is how to <a href="http://developer.android.com/resources/articles/layout-tricks-efficiency.html" title="Android Developers: Layout Tricks: Creating Efficient Layouts">eliminate the nesting of LinearLayouts by using RelativeLayouts</a>.  After that, it comes down to implementing common UI patterns; this blog post focuses on eliminating LinearLayouts by using TextViews.<span id="more-421"></span></p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/04/layout_example_01.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/04/layout_example_01-200x300.png" alt="" title="Layout Example" width="200" height="300" class="alignleft size-medium wp-image-422" /></a>A very common UI pattern for lists and menus is to have some kind of icon on the left, text in the center, and an arrow or other indicator on the right to signify that it can be tapped.  In this first example, the layout is created in the most obvious way: a single vertical LinearLayout, containing three horizontal LinearLayouts.  Each of those LinearLayouts contains an ImageView, a TextView (with a weight of 1 to stretch as needed), and another ImageView.</p>
<p>We can <a href="http://developer.android.com/guide/developing/debugging/debugging-ui.html" title="Android Developers: Debugging and Profiling User Interfaces">profile this layout with Hierarchy Viewer</a> to see that it consists of 18 views, the measure time takes 2.399ms, layout uses just .36ms, and drawing time is 9.322ms.  Not bad, but not great, especially when you consider only half the screen was used.  The hierarchy view shows the level of depth, which is really just 3 levels for this layout (the rest is from the system), but it&#8217;s easy to see how this approach can start to create a lot more Views with more depth than desired.</p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/04/hierarchy_viewer_01.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/04/hierarchy_viewer_01-1024x853.png" alt="" title="Hierarchy Viewer Example 1" width="640" height="533" class="aligncenter size-large wp-image-424" /></a></p>
<p>Here&#8217;s the sample XML:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout
  xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
  android:background=&quot;#FF333333&quot;
  android:layout_height=&quot;match_parent&quot;
  android:layout_width=&quot;match_parent&quot;
  android:orientation=&quot;vertical&quot;
&gt;
    &lt;LinearLayout
      android:background=&quot;#FF003333&quot;
      android:gravity=&quot;center_vertical&quot;
      android:layout_height=&quot;wrap_content&quot;
      android:layout_width=&quot;match_parent&quot;
      android:orientation=&quot;horizontal&quot;
      android:padding=&quot;5dp&quot;
    &gt;
        &lt;ImageView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:src=&quot;@drawable/ic_contact_picture&quot;
        /&gt;
        &lt;TextView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_marginLeft=&quot;5dp&quot;
          android:layout_weight=&quot;1&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:text=&quot;@string/menu_item_1&quot;
        /&gt;
        &lt;ImageView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:src=&quot;@drawable/ic_menu_forward&quot;
        /&gt;
    &lt;/LinearLayout&gt;
    &lt;LinearLayout
      android:background=&quot;#FF006666&quot;
      android:gravity=&quot;center_vertical&quot;
      android:layout_height=&quot;wrap_content&quot;
      android:layout_width=&quot;match_parent&quot;
      android:orientation=&quot;horizontal&quot;
      android:padding=&quot;5dp&quot;
    &gt;
        &lt;ImageView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:src=&quot;@drawable/ic_contact_picture_2&quot;
        /&gt;
        &lt;TextView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_marginLeft=&quot;5dp&quot;
          android:layout_weight=&quot;1&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:text=&quot;@string/menu_item_2&quot;
        /&gt;
        &lt;ImageView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:src=&quot;@drawable/ic_menu_forward&quot;
        /&gt;
    &lt;/LinearLayout&gt;
    &lt;LinearLayout
      android:background=&quot;#FF003333&quot;
      android:gravity=&quot;center_vertical&quot;
      android:layout_height=&quot;wrap_content&quot;
      android:layout_width=&quot;match_parent&quot;
      android:orientation=&quot;horizontal&quot;
      android:padding=&quot;5dp&quot;
    &gt;
        &lt;ImageView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:src=&quot;@drawable/ic_contact_picture_3&quot;
        /&gt;
        &lt;TextView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_marginLeft=&quot;5dp&quot;
          android:layout_weight=&quot;1&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:text=&quot;@string/menu_item_3&quot;
        /&gt;
        &lt;ImageView
          android:layout_height=&quot;wrap_content&quot;
          android:layout_width=&quot;wrap_content&quot;
          android:src=&quot;@drawable/ic_menu_forward&quot;
        /&gt;
    &lt;/LinearLayout&gt;
&lt;/LinearLayout&gt;
</pre>
<p>Some of the attributes in this layout should be defined externally in a real application, but I&#8217;ve defined them all here to make it clear how they&#8217;re defined when we optimize the layout.</p>
<p>The big improvement to be made here is to eliminate each of the horizontal LinearLayouts, replacing them with the TextViews.  We can also eliminate the two ImageViews by using the <a href="http://developer.android.com/reference/android/widget/TextView.html#attr_android:drawableLeft" title="Android Developers: TextView android:drawableLeft">android:drawable</a> properties.  Here&#8217;s the new XML:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout
  xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
  android:background=&quot;#FF333333&quot;
  android:layout_height=&quot;match_parent&quot;
  android:layout_width=&quot;match_parent&quot;
  android:orientation=&quot;vertical&quot;
&gt;
    &lt;TextView
      android:background=&quot;#FF003333&quot;
      android:drawableLeft=&quot;@drawable/ic_contact_picture&quot;
      android:drawablePadding=&quot;5dp&quot;
      android:drawableRight=&quot;@drawable/ic_menu_forward&quot;
      android:gravity=&quot;center_vertical&quot;
      android:layout_height=&quot;wrap_content&quot;
      android:layout_width=&quot;match_parent&quot;
      android:padding=&quot;5dp&quot;
      android:text=&quot;@string/menu_item_1&quot;
    /&gt;
    &lt;TextView
      android:background=&quot;#FF006666&quot;
      android:drawableLeft=&quot;@drawable/ic_contact_picture_2&quot;
      android:drawablePadding=&quot;5dp&quot;
      android:drawableRight=&quot;@drawable/ic_menu_forward&quot;
      android:gravity=&quot;center_vertical&quot;
      android:layout_height=&quot;wrap_content&quot;
      android:layout_width=&quot;match_parent&quot;
      android:padding=&quot;5dp&quot;
      android:text=&quot;@string/menu_item_2&quot;
    /&gt;
    &lt;TextView
      android:background=&quot;#FF003333&quot;
      android:drawableLeft=&quot;@drawable/ic_contact_picture_3&quot;
      android:drawablePadding=&quot;5dp&quot;
      android:drawableRight=&quot;@drawable/ic_menu_forward&quot;
      android:gravity=&quot;center_vertical&quot;
      android:layout_height=&quot;wrap_content&quot;
      android:layout_width=&quot;match_parent&quot;
      android:padding=&quot;5dp&quot;
      android:text=&quot;@string/menu_item_3&quot;
    /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>This drops from 18 Views to 9.  Although you can&#8217;t necessarily compare exact values for measure/layout/draw times between layouts (you&#8217;re never going to have a perfect benchmarking environment), it&#8217;s worth noting that the measure time is .952ms (vs. 2.399ms with the 18 Views), layout is .171ms (vs. .36ms), and drawing time is 8.347ms (vs. 9.322ms).  That means the overall time went from 12.081ms to 9.47ms (2.611ms difference).  Raw numbers are nice, but sometimes a visual says things better:</p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/04/hierarchy_viewer_02.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/04/hierarchy_viewer_02-1024x435.png" alt="" title="Hierarchy Viewer Example 2" width="640" height="271" class="aligncenter size-large wp-image-427" /></a></p>
<p>From that image alone, it&#8217;s clear that the layout is much simpler hierarchically and in total Views.  But how does that affect the actual display?  Compare the 18 View version (left) with the 9 View version (right):<br />
<a href="http://blog.iangclifton.com/wp-content/uploads/2011/04/layout_example_compared.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/04/layout_example_compared.png" alt="" title="Layouts Compared" width="642" height="480" class="aligncenter size-full wp-image-428" /></a></p>
<p>Knowing how to make use of each View can simplify your layouts both for you creating them and for the device calculating their positions and displaying them.  Reviewing each of your layouts in Hierarchy Viewer is a good habit to have.  Although your improvements won&#8217;t always be as drastic as shown in this post (especially once you&#8217;ve become familiar with the Views in the SDK and common UI patterns), seeing the hierarchical structure of your layout can definitely help catch areas that need improvement.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/04/06/android-layout-optimization-textviews/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Counting Android Tablet Apps</title>
		<link>http://blog.iangclifton.com/2011/03/29/counting-android-tablet-apps/</link>
		<comments>http://blog.iangclifton.com/2011/03/29/counting-android-tablet-apps/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 05:33:02 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Mobile Applications]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[honeycomb]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[xoom]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=418</guid>
		<description><![CDATA[Steve Jobs said that Android had &#8220;at most 100 apps&#8221; that make use of the additional screen space offered by the tablet form factor; clearly, this wasn&#8217;t intended to be an exact figure but an estimate designed to show the &#8230; <a href="http://blog.iangclifton.com/2011/03/29/counting-android-tablet-apps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Steve Jobs said that Android had &#8220;at most 100 apps&#8221; that make use of the additional screen space offered by the tablet form factor; clearly, this wasn&#8217;t intended to be an exact figure but an estimate designed to show the contrast between the &#8220;65,000&#8243; iPad apps and the relatively few Android tablet apps. More recently, Justin Williams wrote a blog post entitled <a href="http://carpeaqua.com/2011/03/29/an-updated-list-of-android-apps-for-honeycomb/">An Updated List Of Android Apps For Honeycomb</a>, where he (originally) counted just 12 tablet apps for Android that <a href="http://www.appleinsider.com/articles/11/03/29/steve_jobs_grossly_exaggerated_android_tablet_app_market_size.html">Apple Insider picked up on</a>.<span id="more-418"></span></p>
<p>Wait a minute! That&#8217;s a ridiculously small number! Yes, Justin decided to use a very <em>scientific</em> process of finding tablet apps via &#8220;<a href="http://twitter.com/justinw/status/52748641714176001">market descriptions, youtube searches, google searches</a>&#8221; and he decided to exclude &#8220;games or existing Android apps that are just upconverted to take advantage of the existing screen real estate.&#8221; In fact, Justin (indirectly) admits to not even owning a Xoom: &#8220;Short of buying a Xoom, I am unable to find a decent way to scour the Android marketplace other than browsing it.&#8221;  People on Twitter <a href="http://twitter.com/BillyGrantGrove/statuses/52772750812655616">have</a> <a href="http://twitter.com/JennGrover/statuses/52743264809402368">offered</a> <a href="http://twitter.com/JennGrover/statuses/52743644469395456">suggestions</a> (<a href="http://twitter.com/IanGClifton/status/52865432230699009">me included</a>) for the list that haven&#8217;t been added.  In other words, Apple Insider (among other sites) has taken an inaccurate listing of Android tablet apps that was written by someone with an artificial criteria and who doesn&#8217;t even own a Xoom&#8230;. and treated it like fact.  Oh internet&#8230;</p>
<p>Here&#8217;s the problem (or at least one of them) with that: Android doesn&#8217;t just have two device types like iOS (iPod/iPhone vs. iPad). It has multiple physical sizes (small, medium, large, x-large), multiple densities (ldpi, mdpi, hdpi, xhdpi), and other attributes developers can use to customize an app for different devices. Android automatically selects the correct assets (layouts, images, etc.) based on the device and even scales as needed (a medium-density drawable is scaled up 50% for hdpi devices). Therefore, all apps targeting Android 1.6 and above are inherently &#8220;universal binaries&#8221; rather than being the complete pixel-by-pixel phone-app-on-a-tablet experience that most iOS apps are. In fact, just <a href="http://mashable.com/2010/12/16/ios-app-store-infographic/">8% of iOS apps were universal binaries as of December</a>.</p>
<p>I think it&#8217;s fair to say there are more iOS apps designed specifically for iPad than Android apps designed specifically for Android tablets. It&#8217;s also fair to say that the average Android app makes better use of the space on a tablet than the average iPhone app on an iPad.  I am guessing that no Android tablet in the near future will sell more than the iPad, but it&#8217;s likely that several will come to market and their combined numbers will soon challenge the iPad.  That growth will fuel better tablet experiences and the initial limited number of apps will grow exponentially.</p>
<p>In other words, Justin&#8217;s article is not just inaccurate and misleading; it will be irrelevant soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/03/29/counting-android-tablet-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

