<?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; Mobile Development</title>
	<atom:link href="http://blog.iangclifton.com/category/mobile-development/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>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>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>Missing Device On Android Market</title>
		<link>http://blog.iangclifton.com/2011/02/07/missing-device-on-android-market/</link>
		<comments>http://blog.iangclifton.com/2011/02/07/missing-device-on-android-market/#comments</comments>
		<pubDate>Tue, 08 Feb 2011 04:15:20 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Mobile Development]]></category>
		<category><![CDATA[android market]]></category>
		<category><![CDATA[devices]]></category>
		<category><![CDATA[gafyd]]></category>
		<category><![CDATA[google apps]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=393</guid>
		<description><![CDATA[If you&#8217;re like me, you probably got excited about the web-based Android Market finally being unveiled. Right away, I wanted to try the awesome app installing feature where you simply click install on an app, select the phone to install &#8230; <a href="http://blog.iangclifton.com/2011/02/07/missing-device-on-android-market/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re like me, you probably got excited about the <a href="https://market.android.com/">web-based Android Market</a> finally being unveiled.  Right away, I wanted to try the awesome app installing feature where you simply click install on an app, select the phone to install to, and <em>wah-lah</em>, it&#8217;s on your device.  Unfortunately, the Market was telling me that I didn&#8217;t have any devices associated with my account.  I checked out <a href="https://market.android.com/support/bin/answer.py?hl=en&#038;answer=1141080">the help post</a>, which basically says, &#8220;Make sure you&#8217;re logged in with the account and that you actually use it to get on the Market from your device.&#8221;  That didn&#8217;t help.</p>
<p>The problem was actually that I use my <acronym title="Google Apps For Your Domain">GAFYD</acronym> email address on my Android devices; however, logging in with it would then show my older @gmail.com email address at the top.  Continuing to search, I found that <a href="https://market.android.com/support/bin/answer.py?answer=1146414">your Google Apps account has to be transitioned to the new system</a>.  Basically, Google Apps accounts used to be second class citizens, unable to use many of Google&#8217;s services.  Unfortunately, I had tried to transition a couple of months ago and got this message:<span id="more-393"></span></p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/02/google-apps-transition-error.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/02/google-apps-transition-error-400x37.png" alt="There was a problem with your transition." title="Google Apps Transition Error" width="400" height="37" class="aligncenter size-medium wp-image-394" /></a></p>
<p>I clicked &#8220;<a href="http://www.google.com/support/a/bin/answer.py?hl=en&#038;answer=1050693">Learn more</a>&#8221; and found that the page basically said that I had a <a href="http://www.google.com/support/a/bin/answer.py?answer=185172">conflicting account</a>.  I read <a href="http://www.google.com/support/accounts/bin/static.py?page=guide.cs&#038;guide=29934&#038;topic=29935">another page</a> to finally understand the problem.</p>
<p>Let&#8217;s say my email address was me@example.com.  Before using GAFYD, I used my own server for handling mail, so me@example.com existed before my Google Apps account did.  At some point, I used a Google service and associated it with my me@example.com address.  When my me@example.com email address was supposed to be transitioned to a full fledged Google account, the system saw that email address already used, creating a conflict.</p>
<p>I found <a href="http://www.google.com/support/a/bin/answer.py?hl=en&#038;answer=185186">four steps</a> to resolve the conflict:</p>
<ol>
<li>Visit <a href="http://www.google.com/accounts">www.google.com/accounts</a> and sign in with your personal Google Account</li>
<li>Click ‘Change email’ under ‘Personal Settings’</li>
<li>Enter a different email address where you can receive mail, enter your password, and click ‘Save email address’</li>
<li>Check your other email address and click the link in the verification message from Google to confirm your change</li>
</ol>
<p>I signed in and found that my GAFYD address was listed as an alternate email address for my old @gmail.com account.  I simply removed the me@example.com address, since it was little more than an alias.  I then tried to sign into <a href="http://www.google.com/accounts">www.google.com/accounts</a> with that address and it failed, so I knew it was no longer associated with any Google services.  After that, I just had to pick to transition my account again.  A few minutes later, it had succeeded.  I logged into the Android Market and was able to see my devices:</p>
<p><a href="http://blog.iangclifton.com/wp-content/uploads/2011/02/android-market-devices.png"><img src="http://blog.iangclifton.com/wp-content/uploads/2011/02/android-market-devices-400x86.png" alt="" title="Android Market - My Devices" width="400" height="86" class="aligncenter size-medium wp-image-395" /></a></p>
<p>All is well again.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2011/02/07/missing-device-on-android-market/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Nexus One Debugging In Ubuntu Linux</title>
		<link>http://blog.iangclifton.com/2010/04/08/nexus-one-debugging-in-ubuntu-linux/</link>
		<comments>http://blog.iangclifton.com/2010/04/08/nexus-one-debugging-in-ubuntu-linux/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 04:01:14 +0000</pubDate>
		<dc:creator>Ian G. Clifton</dc:creator>
				<category><![CDATA[Mobile Development]]></category>
		<category><![CDATA[adb]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[g1]]></category>
		<category><![CDATA[htc]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[n1]]></category>
		<category><![CDATA[nexus one]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.iangclifton.com/?p=179</guid>
		<description><![CDATA[This is mostly just a note to myself, but I figured some other people might find it useful. When I connected my Nexus One, it was showing up as &#8220;???????????? no permissions&#8221; when I ran adb devices. I added the &#8230; <a href="http://blog.iangclifton.com/2010/04/08/nexus-one-debugging-in-ubuntu-linux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is mostly just a note to myself, but I figured some other people might find it useful.  When I connected my Nexus One, it was showing up as &#8220;????????????	no permissions&#8221; when I ran <code>adb devices</code>.  I added the typical udev rule and had no luck.  Running <code>lsusb</code> revealed the the vendor ID is different from the HTC G1.  So, to enable debugging this device and the G1 in Ubuntu (and other flavors of Linux), create/edit <code>/etc/udev/rules.d/51-android.rules</code> and put the following in it:</p>
<p><code>SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"<br />
SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"</code></p>
<p>You may need to run <code>sudo reload udev</code> and/or disconnect and reconnect the N1.  Check <code>adb devices</code> again and hopefully you&#8217;ll see &#8220;HT9CSP123456	device&#8221; or similar.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.iangclifton.com/2010/04/08/nexus-one-debugging-in-ubuntu-linux/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

