<?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>Android Magic</title>
	<atom:link href="http://android.codeandmagic.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://android.codeandmagic.org</link>
	<description>&#34;It&#039;s not easy being green...&#34;</description>
	<lastBuildDate>Wed, 09 Nov 2011 22:40:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Android Continuous Integration &#8211; Part 2</title>
		<link>http://android.codeandmagic.org/2011/11/android-continuous-integration-part-2/</link>
		<comments>http://android.codeandmagic.org/2011/11/android-continuous-integration-part-2/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 22:26:53 +0000</pubDate>
		<dc:creator>Evelina Vrabie</dc:creator>
				<category><![CDATA[Util]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=201</guid>
		<description><![CDATA[My little project is made of 3 modules: a parent Maven project &#8211; for keeping things together, an Android project for the application logic and ui and an Android project for running integration tests with Robotium. In some cases (e.g. you want to have a common base code and then 2 different ui implementations for [...]]]></description>
			<content:encoded><![CDATA[<p>My little project is made of 3 modules: a parent Maven project &#8211; for keeping things together, an Android project for the application logic and ui and an Android project for running integration tests with Robotium. In some cases (e.g. you want to have a common base code and then 2 different ui implementations for handsets and tablets) it is useful to have an <a href="http://developer.android.com/guide/developing/projects/projects-cmdline.html#SettingUpLibraryProject" title="Library Project" target="_blank">Android Library Project</a> which then the 2 other can depend on. The android-maven-plugin packages the library project as .apklib and you can find the tutorial <a href="http://code.google.com/p/maven-android-plugin/wiki/ApkLib" title="ApkLib" target="_blank">here</a>.</p>
<p>To download the dependencies needed by your project you have at least 3 choices:<br />
1. Let Maven automatically find and download them from <a href="http://mvnrepository.com/" title="Maven Repository" target="_blank">Maven Repository</a> &#8211; might not all be available<br />
2. Use the <a href="https://github.com/mosabua/maven-android-sdk-deployer" title="Maven Android Sdk Deployer" target="_blank">maven-android-sdk-deployer</a> which installs the android jars from your SDK into your local repository (~/.m2/repository)<br />
3. Setup your own enterprise repository with <a href="http://nexus.sonatype.org/" title="Sonatype Nexus" target="_blank">Sonatype Nexus</a>, where you can add whatever jar you might need and can&#8217;t find on other sources. Then all you need to do is to let Maven know where to look:</p>
<pre class="brush: xml; title: ; notranslate">   &lt;repositories&gt;
		&lt;repository&gt;
			&lt;id&gt;Nexus&lt;/id&gt;
			&lt;url&gt;http://myip:myport/nexus/content/repositories/releases&lt;/url&gt;
		&lt;/repository&gt;
	&lt;/repositories&gt; </pre>
<p>The parent .pom file contains a description of what dependencies will be managed top-level to be used by children projects. This doesn&#8217;t actually download them in your local repository, but lets you use a simpler way of including the dependencies later on. For e.g. you can skip specifying the <code>&lt;version/&gt;</code> or even the <code>&lt;groupId/&gt;</code> on some cases.</p>
<pre class="brush: xml; title: ; notranslate">    &lt;dependencyManagement&gt;
		&lt;dependencies&gt;
			&lt;dependency&gt;
				&lt;groupId&gt;com.google.android&lt;/groupId&gt;
				&lt;artifactId&gt;android&lt;/artifactId&gt;
				&lt;version&gt;${android.version}&lt;/version&gt;
			&lt;/dependency&gt;
			&lt;dependency&gt;
				&lt;groupId&gt;com.google.android&lt;/groupId&gt;
				&lt;artifactId&gt;android-test&lt;/artifactId&gt;
				&lt;version&gt;${android.version}&lt;/version&gt;
			&lt;/dependency&gt;
			&lt;dependency&gt;
				&lt;groupId&gt;com.google.android&lt;/groupId&gt;
				&lt;artifactId&gt;android-support&lt;/artifactId&gt;
				&lt;version&gt;${android.support.version}&lt;/version&gt;
			&lt;/dependency&gt;
			&lt;dependency&gt;
				&lt;groupId&gt;junit&lt;/groupId&gt;
				&lt;artifactId&gt;junit&lt;/artifactId&gt;
				&lt;version&gt;${junit.version}&lt;/version&gt;
			&lt;/dependency&gt;
		&lt;/dependencies&gt;
	&lt;/dependencyManagement&gt;</pre>
<p>The dependencies that I&#8217;ll need in more than one module are the <strong>android jars</strong> (for instrumentation tests as well), <strong>junit</strong> and the <strong>android compatibility (support) library</strong>.</p>
<p>The same you can do for specifying how certain plugins that are used in the children modules behave inside <code>&lt;pluginManagement/&gt;</code>. For e.g. here&#8217;s the <strong>android-maven-plugin</strong>:</p>
<pre class="brush: xml; title: ; notranslate">&lt;groupId&gt;com.jayway.maven.plugins.android.generation2&lt;/groupId&gt;
&lt;artifactId&gt;android-maven-plugin&lt;/artifactId&gt;
&lt;version&gt;${android.maven.plugin.version}&lt;/version&gt;</pre>
<p> and below is what I&#8217;ve configured it to do (with comments):</p>
<pre class="brush: xml; title: ; notranslate">
&lt;configuration&gt;
	&lt;!-- Give the path to your Android SDK and the Android version you're using --&gt;
	&lt;sdk&gt;
		&lt;path&gt;${env.ANDROID_HOME}&lt;/path&gt;
		&lt;platform&gt;${android.api.level}&lt;/platform&gt;
	&lt;/sdk&gt;

	&lt;!-- For the testing phase, this plugin will need to run an emulator called
		'Default', that needs to be available in $HOME/.android/avd/ folder as Default.avd --&gt;
	&lt;emulator&gt;
		&lt;avd&gt;Default&lt;/avd&gt;
		&lt;wait&gt;60000&lt;/wait&gt;
		&lt;options&gt;-no-boot-anim -wipe-data -no-window&lt;/options&gt;
	&lt;/emulator&gt;

	&lt;zipalign&gt;
		&lt;verbose&gt;true&lt;/verbose&gt;
	&lt;/zipalign&gt;

	&lt;!-- ProGuard is a free Java class file shrinker, optimizer, obfuscator,
		and preverifier. It detects and removes unused classes, fields, methods,
		and attributes. It optimizes bytecode and removes unused instructions. It
		renames the remaining classes, fields, and methods using short meaningless
		names.This plugin will read the Proguard configurations inside specified
		file. --&gt;
	&lt;proguard&gt;
		&lt;config&gt;proguard.cfg&lt;/config&gt;
	&lt;/proguard&gt;

	&lt;!-- Remove the existing .apk from the device/emulator before installing
		the newly built .apk file. --&gt;
	&lt;undeployBeforeDeploy&gt;true&lt;/undeployBeforeDeploy&gt;
&lt;/configuration&gt;
</pre>
<p>I opted for not showing the emulator window when running the automated instrumentation tests because I had a strange problem: the emulator starts with the screen lock and the tests are not running properly. If you really need to see the emulator, remove the <code>-no-window</code> option. If you still have the locking problem, here&#8217;s a script that sends some key events to the emulator via <code>telnet</code> to simulate unlocking the screen. You can run that script with <a href="http://mojo.codehaus.org/exec-maven-plugin/" title="Exec Maven Plugin" target="_blank">Exec Maven Plugin</a> like below (put this inside your test project&#8217;s pom):</p>
<pre class="brush: xml; title: ; notranslate">
&lt;build&gt;
	&lt;plugins&gt;
		&lt;plugin&gt;
			&lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
			&lt;artifactId&gt;exec-maven-plugin&lt;/artifactId&gt;
			&lt;version&gt;1.2.1&lt;/version&gt;
			&lt;executions&gt;
				&lt;execution&gt;
					&lt;phase&gt;pre-integration-test&lt;/phase&gt;
					&lt;goals&gt;
						&lt;goal&gt;exec&lt;/goal&gt;
					&lt;/goals&gt;
				&lt;/execution&gt;
			&lt;/executions&gt;
			&lt;configuration&gt;
				&lt;executable&gt;unlock_emulator.sh&lt;/executable&gt;
				&lt;workingDirectory&gt;${project.parent.basedir}&lt;/workingDirectory&gt;
			&lt;/configuration&gt;
		&lt;/plugin&gt;
	&lt;/plugins&gt;
&lt;/build&gt;
</pre>
<p>The unlocking bash script (I&#8217;m not an expert in scripting, but I assume it can be done better in Python or whatever)</p>
<pre class="brush: bash; title: ; notranslate">
host=localhost
port=5554
cmd=&quot;event send EV_KEY:KEY_MENU:1 EV_KEY:KEY_MENU:0&quot;

( echo open ${host} ${port}
sleep 1
echo -e &quot;\r&quot;
sleep 1
echo ${cmd}
sleep 1
echo -e &quot;\r&quot;
sleep 1
echo exit ) | telnet

sleep 10</pre>
<p>To be continued&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/11/android-continuous-integration-part-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Android Continuous Integration &#8211; Part 1</title>
		<link>http://android.codeandmagic.org/2011/11/android-continuous-integration-part-1/</link>
		<comments>http://android.codeandmagic.org/2011/11/android-continuous-integration-part-1/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 21:00:05 +0000</pubDate>
		<dc:creator>Evelina Vrabie</dc:creator>
				<category><![CDATA[Util]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=185</guid>
		<description><![CDATA[I&#8217;ve recently started working on a new Android project and my first task was to set up a continuous integration and testing environment. For a normal java project, this is not such a big deal. For Android however, I found out that&#8217;s not the case&#8230;or maybe it&#8217;s just me So let&#8217;s start with the basics [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently started working on a new Android project and my first task was to set up a <a title="Continuous Integration" href="http://en.wikipedia.org/wiki/Continuous_integration" target="_blank">continuous integration</a> and testing environment. For a normal java project, this is not such a big deal. For Android however, I found out that&#8217;s not the case&#8230;or maybe it&#8217;s just me <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>So let&#8217;s start with the basics tools. First on my mind was <a title="Maven" href="http://en.wikipedia.org/wiki/Apache_Maven" target="_blank">Maven</a>, which is very useful mostly for keeping the project organised, manage the external dependencies, take care of project&#8217;s lifecycle from compiling to releasing and deploying etc. You need to install Maven on your workstation and there are many tutorials on how to do that, which is beyond the scope of this blog post.</p>
<p>Maven knows Java projects very well. But for an Android project, you need to tell it what and how to do for different phases like compile and release. For example, when you release you want to be able switch the debug mode off, increment the project version, sign it with a release key, zipalign it etc. Maven knows how to do that thanks to a very useful plugin called <a title="Android Maven Plugin" href="http://code.google.com/p/maven-android-plugin/" target="_blank">android-maven-plugin</a>. This plugin has several <a title="Android Maven Plugin Goals" href="http://maven-android-plugin-m2site.googlecode.com/svn/plugin-info.html" target="_blank">goals</a>, ranging from packaging the .apk, running tests on the emulator to deploying the .apk and actually running the application etc.</p>
<p>You can find the documentation needed for using this plugin on their website. The basic usage is to create an Android project and then add a .pom file in which specify, among others, the use of the android-maven-plugin.</p>
<p>In this post I am providing a very small working Android-Maven project with two modules (one for the app and one for the tests). Also I&#8217;m gonna tell you how I added <a title="Robotium" href="http://code.google.com/p/robotium/" target="_blank">Robotium</a> for integration tests and <a title="Robolectric" href="http://pivotal.github.com/robolectric/" target="_blank">Robolectric</a> for unit tests as well my view regarding which is better later on. There are a few glitches that I&#8217;ve struggled with while making this project work, so it might be useful to read on and save some time&#8230;if not, jump directly to the source <a title="Android CI Demo" href="https://github.com/CodeAndMagic/AndroidMagic" target="_blank">here</a>. <em><strong>Disclaimer</strong></em>: if the project doesn&#8217;t work out of the box on your machine, it probably means you have to tweak things here and there like explained below.</p>
<p>Most of us mortals use Eclipse to write Android code because of the ADT plugin. Eclipse Indigo comes bundled with the <a title="M2Eclipse" href="http://www.eclipse.org/m2e/" target="_blank">m2e</a> plugin which is used for enabling the Maven nature on a project. On older Eclipse versions you can install this from Eclipse Marketplace. If you add a .pom file to your normal Android project and you have m2e installed inside Eclipse, then all you have to do is right-click the project and select <em>Configure</em> &gt; <em>Convert to Maven project</em>. So instead of the usual way of managing project dependencies by creating a <code>libs</code> folder inside your project, manually adding the needed .jars in there (and keeping track of versions) and tell Eclipse to add those jars in the build classpath, you enable Maven to take care of those dependencies using a <a title="POM" href="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html" target="_blank">POM</a> file.</p>
<p>The problem I&#8217;ve faced right away was that m2e did not recognised the android-maven-plugin by saying something weird like <span style="color: #ff0000;"><em>Plugin execution not covered by lifecycle configuration</em></span>. There is an <a title="M2E-Android" href="http://rgladwell.github.com/m2e-android/" target="_blank">Android Maven Configurator</a> plugin that makes m2e work with Android. However, I could not fix it by pressing <em>Discover new m2e connectors</em> because it kept saying it can&#8217;t find any connectors. So after googling and stackoverflowing I found out that you need to go to <em>Eclipse</em> &gt; <em>Preferences</em> &gt; <em>Maven</em> &gt; <em>Discovery</em> and press <em>Open Catalog</em>. Then you&#8217;ll find the Android Connector as the first listing. You install it and it works. Mostly&#8230;</p>
<p>Download the sample code or clone it with git from <a href="https://github.com/CodeAndMagic/AndroidMagic" title="Android CI Demo" target="_blank">https://github.com/CodeAndMagic/AndroidMagic</a></p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/11/android-continuous-integration-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Small test of Asmack XMPP client library</title>
		<link>http://android.codeandmagic.org/2011/10/small-test-of-asmack-xmpp-client-library/</link>
		<comments>http://android.codeandmagic.org/2011/10/small-test-of-asmack-xmpp-client-library/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 18:25:19 +0000</pubDate>
		<dc:creator>Evelina Vrabie</dc:creator>
				<category><![CDATA[3rd party API]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=175</guid>
		<description><![CDATA[The Asmack is a patch of the Smack XMPP client library that has some fixes for Android. You can dig up what these patches are by reading this thread on Android Developers. Anyway, there are numerous tutorials on how to integrate this library in an Android project, which is pretty simple (just download their jar [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://code.google.com/p/asmack/" title="Asmack" target="_blank">Asmack</a> is a patch of the <a href="http://www.igniterealtime.org/projects/smack/" title="Smack" target="_blank">Smack</a> XMPP client library that has some fixes for Android. You can dig up what these patches are by reading this <a href="http://goo.gl/Gn8ww" title="thread" target="_blank">thread</a> on Android Developers.</p>
<p>Anyway, there are numerous tutorials on how to integrate this library in an Android project, which is pretty simple (just download their jar and include it in the java build path).</p>
<p>What I was interested in this tiny test project was to see if the Smack spawns a new thread when I connect a MessageListener to listen for XMPP messages. That is useful for instance if you have a background <a href="http://developer.android.com/reference/android/app/Service.html" title="Service" target="_blank">Service</a> that keeps a live-connection with a XMPP server in order to process the incoming messages. Since a Service in Android runs on the main thread of their host process, if I want to do intensive CPU or blocking operations (like networking), Android recommends spawning a new thread for them. </p>
<p>So I used this piece of code to connect a <a href="http://www.igniterealtime.org/builds/smack/docs/latest/documentation/messaging.html" title="MessageListener" target="_blank">MessageListener</a> and observe on which thread are messages received.</p>
<pre class="brush: java; title: ; notranslate">
@Override
		public void processMessage(final Chat chat, final Message message) {
			Log.i(TAG, &quot;Xmpp message received: '&quot; + message.getBody() + &quot;' on thread: &quot; + getThreadSignature());
			// --&gt; this is another thread ('Smack Listener Processor')
		}
</pre>
<p>Luckily, it does spawn its own thread (you can observe it in DDMS under the name &#8216;Smack Listener Processor&#8217;) in the Threads tab. So for instance, I think it&#8217;s safe to have your message parsed on this thread and then, if you need more expensive operations based on the content of the message, you can do it on a another thread and sync back with the Service&#8217;s thread via a Handler when it&#8217;s done. You can download the code for the project but you&#8217;ll need your own XMPP server to test it out. Enjoy! <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href='http://android.codeandmagic.org/wp-content/uploads/2011/10/android-asmack-test.zip'>android-asmack-test</a></p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/10/small-test-of-asmack-xmpp-client-library/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sniff http traffic for debug purposes on an Android device using a reverse proxy</title>
		<link>http://android.codeandmagic.org/2011/10/sniff-http-traffic-for-debug-purposes-on-an-android-device-using-a-reverse-proxy/</link>
		<comments>http://android.codeandmagic.org/2011/10/sniff-http-traffic-for-debug-purposes-on-an-android-device-using-a-reverse-proxy/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 18:45:42 +0000</pubDate>
		<dc:creator>Evelina Vrabie</dc:creator>
				<category><![CDATA[Util]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=153</guid>
		<description><![CDATA[The few past months have been really interesting for me personally and professionally as well. I&#8217;ve made the move to a bigger city (London) and started working in a bigger company, in an innovation environment that&#8217;s pretty impressive I&#8217;m really excited to find out how this will improve my developer abilities I was struggling the [...]]]></description>
			<content:encoded><![CDATA[<p>The few past months have been really interesting for me personally and professionally as well. I&#8217;ve made the move to a bigger city (London) and started working in a bigger company, in an innovation environment that&#8217;s pretty impressive <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I&#8217;m really excited to find out how this will improve my developer abilities <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I was struggling the other day with some basic HTTP calls in Android. The LogCat is not very helpful when you need to monitor your http traffic, especially if you use a third-party library for making the calls and thus you are unable to insert some useful logs where you need them.</p>
<p>The fastest solution I have found is to use <a href="http://www.charlesproxy.com/" title="Charles" target="_blank">Charles</a> and set up a <a href="http://www.charlesproxy.com/documentation/proxying/reverse-proxy/" title="reverse proxy" target="_blank">reverse proxy</a> to intercept all the calls made to a specific host. Instead of making the call to the actual server, make the call towards the reverse proxy. This in turn will forward the call to the real domain but will also log the request and response information.</p>
<p>To set this up, enable <code>Reverse Proxies</code> from Charles&#8217; <code>Proxy</code> menu then include the host to which you target your calls in the <code>Recording Settings</code> (the <code>Include</code> tab), for eg. <code>myhostname</code> if the domain is <code>http://myhostname/</code>.</p>
<p>On the Android device you don&#8217;t need to modify any wifi settings.</p>
<p>In your service code, you can configure a method to read the base domain for your calls from a resource string, depending if you want to use a reverse proxy and if the application is in debug mode. Something on the line of this:</p>
<pre class="brush: java; title: ; notranslate">
private static String getDomain() {
		if (Utils.isDebugMode(BaseApplication.getInstance())) {
			// in case you want to use a reverse proxy to sniff the server calls
			final Resources res = BaseApplication.getInstance().getResources();
			if (&quot;yes&quot;.equalsIgnoreCase(res.getString(R.string.use_debug_proxy))) {
				return res.getString(R.string.debug_proxy);
			}
		}
		return REAL_DOMAIN;
	}
</pre>
<p>And the utility method, which simply reads the <code>android:debuggable</code> flag from <em><code>AndroidManifest.xml</code></em>, which, if not manually overridden, ADT knows to automatically set to <em>true</em> when you plug in a device with a debuggable usb connection.</p>
<pre class="brush: java; title: ; notranslate">
	public static boolean isDebugMode(final Context context) {
		final ApplicationInfo info = context.getApplicationInfo();
		final int appFlags = info.flags;
		return (appFlags &amp; ApplicationInfo.FLAG_DEBUGGABLE) != 0;
	}
</pre>
<p>The debug proxy must be set using your computer&#8217;s ip and a given proxy, for e.g: <code>http://192.168.0.13:55699</code>.</p>
<p>It&#8217;s a fairly simple process but can save you a fair amount of time while debugging. Enjoy! <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/10/sniff-http-traffic-for-debug-purposes-on-an-android-device-using-a-reverse-proxy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Android Dynamic Form Fragment</title>
		<link>http://android.codeandmagic.org/2011/08/android-dynamic-form-fragment/</link>
		<comments>http://android.codeandmagic.org/2011/08/android-dynamic-form-fragment/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 19:23:51 +0000</pubDate>
		<dc:creator>Evelina Vrabie</dc:creator>
				<category><![CDATA[API]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=134</guid>
		<description><![CDATA[Continuing on the same topic of saving the state of a fragment across screen flips, I&#8217;ve recently encountered a rather strange issue. I wanted a fragment representing a simple form, with a bunch of TextView as labels and EditText as fields. The real case scenario involved fetching some data over the network and based on [...]]]></description>
			<content:encoded><![CDATA[<p>Continuing on the same topic of saving the state of a fragment across screen flips, I&#8217;ve recently encountered a rather strange issue.</p>
<p>I wanted a fragment representing a simple form, with a bunch of TextView as labels and EditText as fields. The real case scenario involved fetching some data over the network and based on that data, building a dynamic form. I thought this was going to be a simple case of using a loader (like AsyncTaskLoader), fetching the data and building the view hierarchy as soon as the loader returned the required information. Since I&#8217;m growing fond of using the <a title="setRetainInstance()" href="http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)" target="_blank">setRetainInstance()</a> method to automatically save a fragment&#8217;s state across screen configuration changes, I thought that this would work in my case without problems.</p>
<p>It turns out I was not paying enough attention to an important method in the fragment&#8217;s lifecycle: <a title="onCreateView()" href="http://developer.android.com/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)" target="_blank">onCreateView()</a>. This method is called for every fragment that has a view hierarchy in order to instantiate its interface view. Normally,  you inflate an XML layout file and return it as the root of this fragment&#8217;s hierarchy.</p>
<p>But there&#8217;s a problem. If your view hierarchy is made of dynamically added views, after changing the screen orientation you&#8217;d want to keep that hierarchy intact, including all the view&#8217;s states (like EditText input, Spinner selection etc.). If you inflate the XML layout again, you will loose all of these views without any chance of saving the user input. So what&#8217;s the solution?</p>
<p>It turns out the solution is quite simple. You can keep the root of your hierarchy as a variable in the fragment, so it&#8217;s saved after the configuration change. But the thing is, this view is still attached to the old hierarchy, so you need to remove it and re-attach it to the current hierarchy for this saved and resurrected fragment.</p>
<pre class="brush: java; title: ; notranslate">
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
 Bundle savedInstanceState) {
 Log.d(TAG, &quot;onCreateView(): container = &quot; + container
 + &quot;savedInstanceState = &quot; + savedInstanceState);

if (mScrollView == null) {
 // normally inflate the view hierarchy
 mScrollView = (ScrollView) inflater.inflate(R.layout.fragment,
 container, false);
 mFormView = (LinearLayout) mScrollView.findViewById(R.id.form);
 mProgressView = (ProgressBar) mScrollView
 .findViewById(R.id.loading);
 } else {
 // mScrollView is still attached to the previous view hierarchy
 // we need to remove it and re-attach it to the current one
 ViewGroup parent = (ViewGroup) mScrollView.getParent();
 parent.removeView(mScrollView);
 }
 return mScrollView;
 }
 </pre>
<p>Another important thing is to remember that if your loader has finished loading the required data when the screen is flipped, it will automatically trigger the <a title="onLoadFinished()" href="http://developer.android.com/reference/android/app/LoaderManager.LoaderCallbacks.html#onLoadFinished(android.content.Loader%3CD%3E%2C%20D)" target="_blank">onLoadFinished()</a> method. If you build your form there, you should make sure not to duplicate your view hierarchy. The simplest thing to do is to have a boolean variable to keep track of whether that form was built or not.</p>
<pre class="brush: java; title: ; notranslate">
private void buildForm() {
		// if the view hierarchy was already build, skip this
		if (mDone)
			return;

		addFormField(&quot;First Name&quot;, InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
		addFormField(&quot;Last Name&quot;, InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
		addFormField(&quot;Age&quot;, InputType.TYPE_CLASS_NUMBER);
		addFormField(&quot;Phone&quot;, InputType.TYPE_CLASS_PHONE);

		// the view hierarchy is now complete
		mDone = true;
	}
</pre>
<p>Take a look at the source code of this little Android project if you want to test it in action. Enjoy! <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://android.codeandmagic.org/wp-content/uploads/2011/08/android-dynamic-form-fragment.zip">android-dynamic-form-fragment.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/08/android-dynamic-form-fragment/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Android Fragments, Saving State and Screen Rotation</title>
		<link>http://android.codeandmagic.org/2011/07/android-fragments-saving-state-and-screen-rotation/</link>
		<comments>http://android.codeandmagic.org/2011/07/android-fragments-saving-state-and-screen-rotation/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 20:14:36 +0000</pubDate>
		<dc:creator>Evelina Vrabie</dc:creator>
				<category><![CDATA[API]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=112</guid>
		<description><![CDATA[Since the introduction of Loaders in Honeycomb and Compatibility Library, the Android world has changed for the better. However, it took me quite some time to dissect and understand the rather scarce documentation about how to work with these on special cases, like the hated case of screen configuration change &#8211; aka screen flips. It turns [...]]]></description>
			<content:encoded><![CDATA[<p>Since the introduction of <em><a title="Loaders" href="http://developer.android.com/guide/topics/fundamentals/loaders.html" target="_blank">Loaders</a></em> in <em>Honeycomb</em> and <em>Compatibility Library</em>, the Android world has changed for the better. However, it took me quite some time to dissect and understand the rather scarce documentation about how to work with these on special cases, like the hated case of screen configuration change &#8211; aka screen flips.</p>
<p>It turns out it&#8217;s a pretty straightforward concept &#8211; of course, that after you go through a lot of trials and errors, read all the available documentation including the one from the compatibility library&#8217;s source code etc&#8230;</p>
<p>I&#8217;m going to illustrate it below in a simple, but very common case. Let&#8217;s suppose I have a button that once pressed, starts fetching some data in a background thread, using an <em><a title="AsyncTaskLoader" href="http://developer.android.com/reference/android/content/AsyncTaskLoader.html" target="_blank">AsyncTaskLoader</a></em>. Meanwhile, to make my little example more useful, I am displaying a progress dialog with a simple &#8220;Loading&#8230;&#8221; message on top of my activity. If I flip the screen and the background thread still has work to do, I pretty much expect to see the loading dialog &#8220;on the other side&#8221; (after the screen configuration change). I also expect that my loader is still busy doing the work in background until it&#8217;s done, like nothing has happened.</p>
<p>The <em><a title="LoaderManager" href="http://developer.android.com/reference/android/app/LoaderManager.html" target="_blank">LoaderManager</a></em> class has two methods:</p>
<pre class="brush: java; title: ; notranslate">
public abstract &lt;D&gt; Loader&lt;D&gt; initLoader(int id, Bundle args,
            LoaderManager.LoaderCallbacks&lt;D&gt; callback);
</pre>
<p>and</p>
<pre class="brush: java; title: ; notranslate">
public abstract &lt;D&gt; Loader&lt;D&gt; restartLoader(int id, Bundle args,
            LoaderManager.LoaderCallbacks&lt;D&gt; callback);
</pre>
<p>The first is supposed to<em> start a new loader with the given id</em> or to <em>re-connect with an existing loader with that id</em>. The second one is supposed to <em>start a new loader with the give id</em> OR &#8211; and this is different from the <code>initLoader()</code> &#8211; <em>re-start an existing loader with that id</em>.</p>
<p>This means, in the case of my AsyncTaskLoader, that if I call <code>restartLoader()</code>, my loader will execute the background work again. If I call <code>initLoader()</code> it WILL NOT execute the background data again, but if that loader has finished its job, it will immediately return the last valid result.</p>
<p>Let&#8217;s take a look at the sample below.</p>
<pre class="brush: java; title: ; notranslate">
@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		// this is really important in order to save the state across screen
		// configuration changes for example
		setRetainInstance(true);

		// LoaderManager.enableDebugLogging(true);

		mRes = getResources();
		mInflater = LayoutInflater.from(getActivity());

		mBtnReload = (Button) getActivity().findViewById(R.id.btn);
		mBtnReload.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// first time
				if (mFirstRun) {

					mFirstRun = false;
					mBtnReload.setText(mRes.getString(R.string.restart));

					startLoading();
				}
				// already started once
				else {
					restartLoading();
				}
			}
		});

		// you only need to instantiate these the first time your fragment is
		// created; then, the method above will do the rest
		if (mAdapter == null) {
			mItems = new ArrayList&lt;String&gt;();
			mAdapter = new MyAdapter(getActivity(), mItems);
		}
		getListView().setAdapter(mAdapter);

		// ---- magic lines starting here -----
		// call this to re-connect with an existing
		// loader (after screen configuration changes for e.g!)
		LoaderManager lm = getLoaderManager();
		if (lm.getLoader(0) != null) {
			lm.initLoader(0, null, this);
		}
		// ----- end magic lines -----

		if (!mFirstRun) {
			mBtnReload.setText(mRes.getString(R.string.restart));
		}
	}

	protected void startLoading() {
		showDialog();

		// first time we call this loader, so we need to create a new one
		getLoaderManager().initLoader(0, null, this);
	}

	protected void restartLoading() {
		showDialog();

		mItems.clear();
		mAdapter.notifyDataSetChanged();
		getListView().invalidateViews();

		// --------- the other magic lines ----------
		// call restart because we want the background work to be executed
		// again
		Log.d(TAG, &quot;restartLoading(): re-starting loader&quot;);
		getLoaderManager().restartLoader(0, null, this);
		// --------- end the other magic lines --------
	}

	@Override
	public Loader&lt;Void&gt; onCreateLoader(int id, Bundle args) {
		AsyncTaskLoader&lt;Void&gt; loader = new AsyncTaskLoader&lt;Void&gt;(getActivity()) {

			@Override
			public Void loadInBackground() {
				try {
					// simulate some time consuming operation going on in the
					// background
					Log.d(TAG, &quot;loadInBackground(): doing some work....&quot;);
					for (int i = 0; i &lt; SIZE; ++i) {
						mItems.add(WORDS[i]);
					}

					Thread.sleep(SLEEP);
				} catch (InterruptedException e) {
				}
				return null;
			}
		};
		// somehow the AsyncTaskLoader doesn't want to start its job without
		// calling this method
		loader.forceLoad();
		return loader;
	}

	@Override
	public void onLoadFinished(Loader&lt;Void&gt; loader, Void result) {

		mAdapter.notifyDataSetChanged();
		hideDialog();
		Log.d(TAG, &quot;onLoadFinished(): done loading!&quot;);

	}
</pre>
<p>If I comment the magic lines (44 &#8211; 47) and I flip the phone to change the layout, from portrait to landscape or vice-versa, my loader state WILL BE LOST (oh no!) and I will never receive the <code>onLoadFinish()</code> callback call to tell me that the job is done. Since I display a loading dialog while the data is being processed in the background, this means that this dialog it will &#8220;hang&#8221; on the screen forever and ever without being hidden. That is because we need to <em>re-connect</em> - aka <em><code>initLoader()</code></em> - with all our current loaders in order to receive feedback after a screen configuration change or whatever made that fragment be restored.</p>
<p>Also, if I replace <code>restartLoader()</code> in the other magic line (line 73) with <code>initLoader()</code>, the second time I press the &#8220;Restart&#8221; button it WILL NOT do the background work again (meaning to re-add all the items in the list).  So, nothing will happen and the list will remain empty.  If that were a <em><a title="CursorLoader" href="http://developer.android.com/reference/android/content/CursorLoader.html" target="_blank">CursorLoader</a></em> instead, if a previous load would have been completed with valid results, those results will be returned immediately.</p>
<p>That being said, I&#8217;m attaching the sources if you want to try out for yourself. Enjoy! <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://android.codeandmagic.org/wp-content/uploads/2011/07/FragmentWithDialog.tar.gz">FragmentWithDialog.tar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/07/android-fragments-saving-state-and-screen-rotation/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Reading text files is damn slow on Android!</title>
		<link>http://android.codeandmagic.org/2011/07/reading-text-files-is-damn-slow-on-android/</link>
		<comments>http://android.codeandmagic.org/2011/07/reading-text-files-is-damn-slow-on-android/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 08:04:52 +0000</pubDate>
		<dc:creator>Cristian Vrabie</dc:creator>
				<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=108</guid>
		<description><![CDATA[In a Android application I wanted to use Scanner class to read a list of floats from a text file (it&#8217;s a list of vertex coordinates for OpenGL). Exact code is: It seems however that this is incredibly slow (it took 30 minutes to read 10,000 floats!) &#8211; as tested on the 2.1 emulator. Run [...]]]></description>
			<content:encoded><![CDATA[<p>In a Android application I wanted to use Scanner class to read a list of floats from a text file (it&#8217;s a list of vertex coordinates for OpenGL). Exact code is:</p>
<pre class="brush: java; title: ; notranslate">
Scanner in = new Scanner(new BufferedInputStream(getAssets().open(&quot;vertexes.off&quot;)));
final float[] vertexes = new float[nrVertexes];
for(int i=0;i    vertexes[i] = in.nextFloat();
}
</pre>
<p>It seems however that this is incredibly slow (it took <strong>30 minutes</strong> to read <strong>10,000 floats</strong>!) &#8211; as tested on the 2.1 emulator. Run on an actual device this is a bit faster but still very slow &#8211; order of minutes. On a PC Java application it takes <strong>1 second</strong> to read <strong>20,000 floats</strong> (with the same code). I profiled it (for 100 floats) and it seems that the calls to nextFloat take all the time. Because of the BufferedInputStream only 2 calls are made to read from the input and they take very little time (35ms/call). However calls to nextFloat take 435ms/call which is huge. By looking at children calls it seems that calls inside NumberFormat and Pattern are the killers. There are a lot of memory allocations and the Android VM and GC doesn&#8217;t seem to be as optimized  as the PC one.</p>
<p>As a solution I found the following to work very well: first I parse my input file on the PC and transform it into binary data, then I read it on the device byte by byte (buffered) and reconstruct the numbers. This is MUCH faster. It takes <strong>1.5s</strong> to read <strong>20,000 floats</strong>. I say it&#8217;s a enormous improvement from 1 hour <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Have a look at <a href="http://stackoverflow.com/questions/2446805/is-java-util-scanner-that-slow">this StackOverflow discussion</a> for more ideas.</p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/07/reading-text-files-is-damn-slow-on-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Method calls through interface references are slower</title>
		<link>http://android.codeandmagic.org/2011/07/method-calls-through-interface-references-are-slower/</link>
		<comments>http://android.codeandmagic.org/2011/07/method-calls-through-interface-references-are-slower/#comments</comments>
		<pubDate>Mon, 11 Jul 2011 07:37:16 +0000</pubDate>
		<dc:creator>Cristian Vrabie</dc:creator>
				<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=96</guid>
		<description><![CDATA[In the 2009 Google I/O talk about writing real-time games for Android it is recommended that for performance we don&#8217;t use interfaces. Supposedly the calls through an interface reference are about 30% slower. It is also mentioned that calls to static methods are faster. In these circumstances, i asked myself if all calls to a [...]]]></description>
			<content:encoded><![CDATA[<p>In the 2009 Google I/O <a href="http://developer.android.com/videos/index.html#v=U4Bk5rmIpic">talk about writing real-time games for Android</a> it is recommended that for performance we don&#8217;t use interfaces. Supposedly the calls through an interface reference are about 30% slower. It is also mentioned that calls to static methods are faster.</p>
<p>In these circumstances, i asked myself if all calls to a non-direct reference are slower. I&#8217;m not an expert at low level stuff, but it looks to me that calling a method through a interface reference is about the same thing as calling a method through a reference to a parent class. But this would mean that we shouldn&#8217;t use inheritance at all. And that, for someone like me that usually trades performance for scalability, it sounds crazy.</p>
<p>I decided to make a quick test to see if this is true. You can check <a href="http://pastebin.com/m7c7c0043">the code I used</a> on Pastebin.</p>
<p>First I ran it on my PC and I was stupefied to find results like these at every run (values are in nanoseconds necessary to run 1,000,000,000 method calls):</p>
<table class="datatable">
<thead>
<tr>
<th>Direct refference</th>
<th>Parent refference</th>
<th>Interface refference</th>
<th>Static refference</th>
</tr>
</thead>
<tbody>
<tr>
<td class="value">1,596,318,257</td>
<td class="value">1,550,725,582</td>
<td class="value">1,552,626,591</td>
<td class="value">1,751,394,872</td>
</tr>
</tbody>
</table>
<p>Then I tested it in an Android application, using a HTC Hero Phone. (Note: I reduced the number of iterations from 1000000000L to 5000000L).</p>
<table class="datatable">
<thead>
<tr>
<th>Direct refference</th>
<th>Parent refference</th>
<th>Interface refference</th>
<th>Static refference</th>
</tr>
</thead>
<tbody>
<tr>
<td class="value">3,767,791,749</td>
<td class="value">3,477,020,264</td>
<td class="value">4,690,185,547</td>
<td class="value">3,327,636,719</td>
</tr>
</tbody>
</table>
<p>So the interfaces are slower. I can now confirm with my own test. I guess the virtual machine is quite different.<br />
The good thing is that calls through parent references are not slower. Wohoo! OOP for life <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p><em>Note:</em> I also re-run the test to include a final method call that should be the only one non-virtual. I could not notice any improvement which is at least weird. Posted a question on JavaRanch. Maybe someone can come with a explanation for this.</p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/07/method-calls-through-interface-references-are-slower/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Tabs with Fragments</title>
		<link>http://android.codeandmagic.org/2011/07/android-tabs-with-fragments/</link>
		<comments>http://android.codeandmagic.org/2011/07/android-tabs-with-fragments/#comments</comments>
		<pubDate>Sun, 10 Jul 2011 12:41:50 +0000</pubDate>
		<dc:creator>Evelina Vrabie</dc:creator>
				<category><![CDATA[UX]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=59</guid>
		<description><![CDATA[I&#8217;ve been recently using the Android Compatibility Library in a project where I  found myself in the need for a tabbed layout, in which each of the tab&#8217;s children would be a fragment.  The usual way to do this is for the activity you need the tabs in to extend TabActivity. However, if you want to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been recently using the <a title="Android Compatibility Library" href="http://developer.android.com/sdk/compatibility-library.html" target="_blank">Android Compatibility Library</a> in a project where I  found myself in the need for a tabbed layout, in which each of the tab&#8217;s children would be a fragment.  The usual way to do this is for the activity you need the tabs in to extend <a title="TabActivity" href="http://developer.android.com/reference/android/app/TabActivity.html" target="_blank">TabActivity</a>. However, if you want to use fragments in your activity, you must extend <em>android.support.v4.app.FragmentActivity</em> instead. Since Java doesn&#8217;t allow multiple class inheritance, you find yourself in a bit of dilemma.</p>
<p>Well, there&#8217;s a simple solution for making this work. What you need is basically to use a <a title="TabHost" href="http://developer.android.com/reference/android/widget/TabHost.html" target="_blank">TabHost</a> to hold both the <a title="TabWidget" href="http://developer.android.com/reference/android/widget/TabWidget.html" target="_blank">TabWidget</a> (which are the actual tab labels) and their content. Since the TabHost is nothing more than a View, you can place that anywhere, including in the root of a fragment defined in XML, like the one below (<em>tabs_fragment.xml</em>). I am hoping the comments in the code are self-explanatory enough.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;TabHost
	xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
	android:id=&quot;@android:id/tabhost&quot;
	android:layout_width=&quot;fill_parent&quot;
	android:layout_height=&quot;fill_parent&quot;
	android:background=&quot;#EFEFEF&quot;&gt;

	&lt;LinearLayout
		android:orientation=&quot;vertical&quot;
		android:layout_width=&quot;fill_parent&quot;
		android:layout_height=&quot;fill_parent&quot;&gt;

		&lt;TabWidget
			android:id=&quot;@android:id/tabs&quot;
			android:layout_width=&quot;fill_parent&quot;
			android:layout_height=&quot;wrap_content&quot; /&gt;

			&lt;FrameLayout
				android:id=&quot;@android:id/tabcontent&quot;
				android:layout_width=&quot;fill_parent&quot;
				android:layout_height=&quot;fill_parent&quot;&gt;

				&lt;FrameLayout
					android:id=&quot;@+id/tab_1&quot;
					android:layout_width=&quot;fill_parent&quot;
					android:layout_height=&quot;fill_parent&quot; /&gt;

				&lt;FrameLayout
					android:id=&quot;@+id/tab_2&quot;
					android:layout_width=&quot;fill_parent&quot;
					android:layout_height=&quot;fill_parent&quot; /&gt;

			&lt;/FrameLayout&gt;
	&lt;/LinearLayout&gt;
&lt;/TabHost&gt;
</pre>
<p>Don&#8217;t forget to use the correct ids (<em>@android:id/tabhost</em>, <em>@android:id/tabs</em> and <em>@android:id/tabcontent</em>) because the TabHost expects exactly these in order to retrieve the references for each component of the view. If you want to use a custom style for your tabs, it is easy to do so by creating a <em>tab_selector.xml</em> in <em>/res/drawables</em> in which you can use different colors or backgrounds for each tab state. You can find an example in the attached zip.</p>
<p>The equivalent code for actually creating the tabs is in <em>TabsFragment.java</em> below.</p>
<pre class="brush: java; title: ; notranslate">
package org.codeandmagic.android;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;

public class TabsFragment extends Fragment implements OnTabChangeListener {

	private static final String TAG = &quot;FragmentTabs&quot;;
	public static final String TAB_WORDS = &quot;words&quot;;
	public static final String TAB_NUMBERS = &quot;numbers&quot;;

	private View mRoot;
	private TabHost mTabHost;
	private int mCurrentTab;

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		mRoot = inflater.inflate(R.layout.tabs_fragment, null);
		mTabHost = (TabHost) mRoot.findViewById(android.R.id.tabhost);
		setupTabs();
		return mRoot;
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		setRetainInstance(true);

		mTabHost.setOnTabChangedListener(this);
		mTabHost.setCurrentTab(mCurrentTab);
		// manually start loading stuff in the first tab
		updateTab(TAB_WORDS, R.id.tab_1);
	}

	private void setupTabs() {
		mTabHost.setup(); // you must call this before adding your tabs!
		mTabHost.addTab(newTab(TAB_WORDS, R.string.tab_words, R.id.tab_1));
		mTabHost.addTab(newTab(TAB_NUMBERS, R.string.tab_numbers, R.id.tab_2));
	}

	private TabSpec newTab(String tag, int labelId, int tabContentId) {
		Log.d(TAG, &quot;buildTab(): tag=&quot; + tag);

		View indicator = LayoutInflater.from(getActivity()).inflate(
				R.layout.tab,
				(ViewGroup) mRoot.findViewById(android.R.id.tabs), false);
		((TextView) indicator.findViewById(R.id.text)).setText(labelId);

		TabSpec tabSpec = mTabHost.newTabSpec(tag);
		tabSpec.setIndicator(indicator);
		tabSpec.setContent(tabContentId);
		return tabSpec;
	}

	@Override
	public void onTabChanged(String tabId) {
		Log.d(TAG, &quot;onTabChanged(): tabId=&quot; + tabId);
		if (TAB_WORDS.equals(tabId)) {
			updateTab(tabId, R.id.tab_1);
			mCurrentTab = 0;
			return;
		}
		if (TAB_NUMBERS.equals(tabId)) {
			updateTab(tabId, R.id.tab_2);
			mCurrentTab = 1;
			return;
		}
	}

	private void updateTab(String tabId, int placeholder) {
		FragmentManager fm = getFragmentManager();
		if (fm.findFragmentByTag(tabId) == null) {
			fm.beginTransaction()
					.replace(placeholder, new MyListFragment(tabId), tabId)
					.commit();
		}
	}

}
</pre>
<p>Now that you have the content of your fragment in place, you need to create the tab&#8217;s children (which are fragments, like the title says). You can subclass the <em> android.support.v4.app.Fragment</em> (I used a <em>ListFragment</em> in this example). You can also use <em><a title="loaders" href="http://developer.android.com/guide/topics/fundamentals/loaders.html" target="_blank">loaders</a></em> if your fragment needs to do some background work. In the example below, I use an <em>AsyncTaskLoader</em> to simulate a time-consuming operation in background, at the end of which some words or numbers are added into the list&#8217;s adapter and displayed inside a tab. You also need a <em><a title="LoaderCallback" href="http://developer.android.com/reference/android/app/LoaderManager.LoaderCallbacks.html" target="_blank">LoaderCallback</a> </em>object (or your fragment can directly implement this interface) in order to communicate with the <em><a title="LoaderManager" href="http://developer.android.com/reference/android/app/LoaderManager.html" target="_blank">LoaderManager</a></em> to create your loader and also know when its job is done.</p>
<pre class="brush: java; title: ; notranslate">
package org.codeandmagic.android;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class MyListFragment extends ListFragment implements
		LoaderCallbacks&lt;Void&gt; {

	private static final String TAG = &quot;FragmentTabs&quot;;

	private String mTag;
	private MyAdapter mAdapter;
	private ArrayList&lt;String&gt; mItems;
	private LayoutInflater mInflater;
	private int mTotal;
	private int mPosition;

	private static final String[] WORDS = { &quot;Lorem&quot;, &quot;ipsum&quot;, &quot;dolor&quot;, &quot;sit&quot;,
			&quot;amet&quot;, &quot;consectetur&quot;, &quot;adipiscing&quot;, &quot;elit&quot;, &quot;Fusce&quot;, &quot;pharetra&quot;,
			&quot;luctus&quot;, &quot;sodales&quot; };
	private static final String[] NUMBERS = { &quot;I&quot;, &quot;II&quot;, &quot;III&quot;, &quot;IV&quot;, &quot;V&quot;,
			&quot;VI&quot;, &quot;VII&quot;, &quot;VIII&quot;, &quot;IX&quot;, &quot;X&quot;, &quot;XI&quot;, &quot;XII&quot;, &quot;XIII&quot;, &quot;XIV&quot;, &quot;XV&quot; };

	private static final int SLEEP = 1000;

	private final int wordBarColor = R.color.word_bar;
	private final int numberBarColor = R.color.number_bar;

	public MyListFragment() {
	}

	public MyListFragment(String tag) {
		mTag = tag;
		mTotal = TabsFragment.TAB_WORDS.equals(mTag) ? WORDS.length
				: NUMBERS.length;

		Log.d(TAG, &quot;Constructor: tag=&quot; + tag);
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		// this is really important in order to save the state across screen
		// configuration changes for example
		setRetainInstance(true);

		mInflater = LayoutInflater.from(getActivity());

		// you only need to instantiate these the first time your fragment is
		// created; then, the method above will do the rest
		if (mAdapter == null) {
			mItems = new ArrayList&lt;String&gt;();
			mAdapter = new MyAdapter(getActivity(), mItems);
		}
		getListView().setAdapter(mAdapter);

		// initiate the loader to do the background work
		getLoaderManager().initLoader(0, null, this);
	}

	@Override
	public Loader&lt;Void&gt; onCreateLoader(int id, Bundle args) {
		AsyncTaskLoader&lt;Void&gt; loader = new AsyncTaskLoader&lt;Void&gt;(getActivity()) {

			@Override
			public Void loadInBackground() {
				try {
					// simulate some time consuming operation going on in the
					// background
					Thread.sleep(SLEEP);
				} catch (InterruptedException e) {
				}
				return null;
			}
		};
		// somehow the AsyncTaskLoader doesn't want to start its job without
		// calling this method
		loader.forceLoad();
		return loader;
	}

	@Override
	public void onLoadFinished(Loader&lt;Void&gt; loader, Void result) {

		// add the new item and let the adapter know in order to refresh the
		// views
		mItems.add(TabsFragment.TAB_WORDS.equals(mTag) ? WORDS[mPosition]
				: NUMBERS[mPosition]);
		mAdapter.notifyDataSetChanged();

		// advance in your list with one step
		mPosition++;
		if (mPosition &lt; mTotal - 1) {
			getLoaderManager().restartLoader(0, null, this);
			Log.d(TAG, &quot;onLoadFinished(): loading next...&quot;);
		} else {
			Log.d(TAG, &quot;onLoadFinished(): done loading!&quot;);
		}
	}

	@Override
	public void onLoaderReset(Loader&lt;Void&gt; loader) {
	}

	private class MyAdapter extends ArrayAdapter&lt;String&gt; {

		public MyAdapter(Context context, List&lt;String&gt; objects) {
			super(context, R.layout.list_item, R.id.text, objects);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View view = convertView;
			Wrapper wrapper;

			if (view == null) {
				view = mInflater.inflate(R.layout.list_item, null);
				wrapper = new Wrapper(view);
				view.setTag(wrapper);
			} else {
				wrapper = (Wrapper) view.getTag();
			}

			wrapper.getTextView().setText(getItem(position));
			wrapper.getBar().setBackgroundColor(
					mTag == TabsFragment.TAB_WORDS ? getResources().getColor(
							wordBarColor) : getResources().getColor(
							numberBarColor));
			return view;
		}

	}

	// use an wrapper (or view holder) object to limit calling the
	// findViewById() method, which parses the entire structure of your
	// XML in search for the ID of your view
	private class Wrapper {
		private final View mRoot;
		private TextView mText;
		private View mBar;

		public Wrapper(View root) {
			mRoot = root;
		}

		public TextView getTextView() {
			if (mText == null) {
				mText = (TextView) mRoot.findViewById(R.id.text);
			}
			return mText;
		}

		public View getBar() {
			if (mBar == null) {
				mBar = mRoot.findViewById(R.id.bar);
			}
			return mBar;
		}
	}
}
</pre>
<p>Now, all you need to do is create a <em>FragmentActivity</em> to accommodate your tabs fragment. You can either instantiate the fragment programmatically using the methods in the <em><a title="FragmentManager" href="http://developer.android.com/reference/android/app/FragmentManager.html" target="_blank">FragmentManager</a></em> or by putting it directly in XML, like below (<em>main.xml</em>).</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:orientation=&quot;vertical&quot;
	android:layout_width=&quot;fill_parent&quot;
	android:layout_height=&quot;fill_parent&quot;&gt;

	&lt;fragment
		class=&quot;org.codeandmagic.android.TabsFragment&quot;
		android:id=&quot;@+id/tabs_fragment&quot;
		android:layout_width=&quot;fill_parent&quot;
		android:layout_height=&quot;fill_parent&quot; /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>With that, your job is pretty much done. You can see  in the screenshot the result and also can download the project that&#8217;s available in the attached zip. Enjoy! <img src='http://android.codeandmagic.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<a href='http://android.codeandmagic.org/2011/07/android-tabs-with-fragments/tab1-2/' title='tab1'><img width="150" height="150" src="http://android.codeandmagic.org/wp-content/uploads/2011/07/tab11-150x150.png" class="attachment-thumbnail" alt="tab1" title="tab1" /></a>
<a href='http://android.codeandmagic.org/2011/07/android-tabs-with-fragments/tab2-2/' title='tab2'><img width="150" height="150" src="http://android.codeandmagic.org/wp-content/uploads/2011/07/tab21-150x150.png" class="attachment-thumbnail" alt="tab2" title="tab2" /></a>

<p><a href="http://android.codeandmagic.org/wp-content/uploads/2011/07/FragmentTabs.tar.gz">FragmentTabs.tar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/07/android-tabs-with-fragments/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Proper way to add/remove OverlayItems</title>
		<link>http://android.codeandmagic.org/2011/07/proper-way-to-add-remove-overlayitem/</link>
		<comments>http://android.codeandmagic.org/2011/07/proper-way-to-add-remove-overlayitem/#comments</comments>
		<pubDate>Wed, 06 Jul 2011 06:37:43 +0000</pubDate>
		<dc:creator>Cristian Vrabie</dc:creator>
				<category><![CDATA[3rd party API]]></category>

		<guid isPermaLink="false">http://android.codeandmagic.org/?p=43</guid>
		<description><![CDATA[Some time ago I contributed to an app for Android which had to manage a lot of Google map OverlayItems. The Google API support and performance for overlay items is satisfactory while you have a manageable amount of items but gets messy if you have lots and lots of items. Further more, it seems that [...]]]></description>
			<content:encoded><![CDATA[<p><!-- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica} -->Some time ago I contributed to an app for Android which had to manage a lot of Google map OverlayItems. The Google API support and performance for overlay items is satisfactory while you have a manageable amount of items but gets messy if you have lots and lots of items. Further more, it seems that the API was made with the idea that the items don&#8217;t really change once you added them to the map. Here are a few pointers that I discovered about how to add/ properly handle items:</p>
<h3>1. Call <code>populate()</code> for batch operations</h3>
<p>After each <em>change</em> the maps api says to call <code>populate()</code> on the overlay. This method basically recalculates and redisplays everything. The problem is that many of the people that posted code samples on the internet took it literally. After each item addition/removal they call populate so if you&#8217;re adding 100 items at once, they call populate after each add. Instead, populate should be more like a transaction commit. After you added all 100 items, then you should finish with a populate. This will considerably speed things up.</p>
<h3>2. Properly handle changes</h3>
<p>As I said, the api was probably made with the idea the the items don&#8217;t change much. For exemple, if you remove an item weird stuff start to happend. The map will get properly drawn but if you press in the place where the removed item was you might (or not) get this exception:</p>
<pre>ERROR/AndroidRuntime(16446): java.lang.ArrayIndexOutOfBoundsException
ERROR/AndroidRuntime(16446):     at com.google.android.maps.ItemizedOverlay.maskHelper(ItemizedOverlay.java:562)
ERROR/AndroidRuntime(16446):     at com.google.android.maps.ItemizedOverlay.setFocus(ItemizedOverlay.java:365)
ERROR/AndroidRuntime(16446):     at com.google.android.maps.ItemizedOverlay.focus(ItemizedOverlay.java:539)
ERROR/AndroidRuntime(16446):     at com.google.android.maps.ItemizedOverlay.onTap(ItemizedOverlay.java:455)
ERROR/AndroidRuntime(16446):     at com.google.android.maps.OverlayBundle.onTap(OverlayBundle.java:83)
ERROR/AndroidRuntime(16446):     at com.google.android.maps.MapView$1.onSingleTapUp(MapView.java:347)
ERROR/AndroidRuntime(16446):     at com.google.android.maps.GestureDetector.onTouchEvent(GestureDetector.java:533)
ERROR/AndroidRuntime(16446):     at com.google.android.maps.MapView.onTouchEvent(MapView.java:647)</pre>
<p>To solve this I discovered that together with populate you need to reset the last focused item:</p>
<pre class="brush: java; title: ; notranslate">public void doPopulate(){
    populate();
    setLastFocusedIndex(-1);
}</pre>
<h3>3. Filter pins by zoom level</h3>
<p>If you have hundreds or thousands of items at once, most of them in the same area, the map will do a pretty good job optimizing when you&#8217;re zoomed in so that you see only few of them. But if you try to zoom out, the map will try to display all of them. Besides the visual mess of having them on top of each other, the map will start to scroll really really slow.</p>
<div id="attachment_49" class="wp-caption aligncenter" style="width: 330px"><a href="http://android.codeandmagic.org/wp-content/uploads/2011/07/device-2011-07-05-224926.png"><img class="size-full wp-image-49" title="device-2011-07-05-224926" src="http://android.codeandmagic.org/wp-content/uploads/2011/07/device-2011-07-05-224926.png" alt="Unfiltered overlay items" width="320" height="480" /></a><p class="wp-caption-text">Many overlay items don&#39;t look good at lower zoom levels and reduce performance.</p></div>
<p>So what I tried is to filter them based on the zoom level. It&#8217;s obvious that once you&#8217;re so far zoomed out that your screen can fit a continent, you can use only one item to represent a city. Once you get to a workable zoom level, all of them should be displayed. What&#8217;s in between though is specific to your application and should be done with great care so that the user doesn&#8217;t miss anything. In my case, all the items had the same importance so I used an exponential increase together with a dispersion algorithm to cover a greater geographical area. This way all neighborhoods would contain items.</p>
<div id="attachment_50" class="wp-caption aligncenter" style="width: 330px"><a href="http://android.codeandmagic.org/wp-content/uploads/2011/07/device-2011-07-05-225129.png"><img class="size-full wp-image-50" title="device-2011-07-05-225129" src="http://android.codeandmagic.org/wp-content/uploads/2011/07/device-2011-07-05-225129.png" alt="Filtered overlay items" width="320" height="480" /></a><p class="wp-caption-text">It better to filter out items if the user can&#39;t use them at that zoom level.</p></div>
<p>To get you started with filtering here&#8217;s some code. First you need a interface for the ones listening to zoom events.</p>
<pre class="brush: java; title: ; notranslate">public interface ZoomListener {
	public void onZoom(int oldZoom, int newZoom);
}</pre>
<p>Yes, Google Api has something like this (<code>OnZoomListener</code>) but it only notifies you when a zoom in/out button is pressed, not when the user pinches the map. So you need a custom MapView to use not only that, but also detect pinch to zoom events and call a more useful callback (some code removed for visibility):</p>
<pre class="brush: java; title: ; notranslate">
public class ArtMapView extends MapView implements OnZoomListener {
	private int zoom;
	private ZoomListener zoomListener;
	public void setZoomLevel(int zoom) {
		this.zoom = zoom;
		this.getController().setZoom(zoom);
	}
	public ZoomListener getZoomListener() {
		return zoomListener;
	}
	public void setZoomListener(ZoomListener listener) {
		this.zoomListener = listener;
		this.getZoomButtonsController().setOnZoomListener(this);
	}
	public boolean onTouchEvent(MotionEvent event) {
		boolean result = super.onTouchEvent(event);
		if (event.getAction() == MotionEvent.ACTION_UP) {
			checkForZoomEvent();
		}
		return result;
	}
	private void checkForZoomEvent() {
		if (this.zoomListener != null) {
			int newZoom = this.getZoomLevel();
			if (newZoom != zoom) {
				this.zoomListener.onZoom(zoom, newZoom);
			}
			zoom = newZoom;
		}
	}
	public void onZoom(boolean zoomIn) {
		int oldZoom = this.zoom;
		this.setZoomLevel(oldZoom + (zoomIn ? 1 : -1));
		if (this.zoomListener != null) {
			this.zoomListener.onZoom(oldZoom, this.zoom);
		}
	}
}
</pre>
<p>In the place that constructs your MapView (probably an Activity) you need to implement the zoom listener and start listening to events. On each zoom change you recalculate the number of items to be displayed. One simple way to do it is shown below.</p>
<pre class="brush: java; title: ; notranslate">
private void getNrPinsToDisplay(List items) {
	if (items == null || items.size() == 0) return;
	int allNrPins = items.size();
	if (newZoom  ZOOM_MAX_LEVEL)
		nrPinsForZoomLevel = allNrPins;
	else
		nrPinsForZoomLevel = MAX_PINS_PER_ZOOM[newZoom - ZOOM_MIN_LEVEL - 1];
}
</pre>
<p><code>ZOOM_MIN_LEVEL</code> is the zoom level under which only 1 item is shown (per group of data &#8211; example per city)<br />
<code>ZOOM_MAX_LEVEL</code> is the zoom level over which all items are shown<br />
<code>ZOOM_MAX_LEVEL</code> is an array which contains the number of items to be display for the levels in between</p>
<p>All you have to do next is to hook the magic <code>nrPinsForZoomLevel</code> value in the item display function. You can have a look at the <a title="ArtAround" href="https://github.com/ArtAround/artaround-android" target="_blank">ArtAround</a> project on GitHub to see a sample of this being used. There&#8217;s room for a lot of improvement and inovation but hope this gave you a few good ideas to get you started.</p>
]]></content:encoded>
			<wfw:commentRss>http://android.codeandmagic.org/2011/07/proper-way-to-add-remove-overlayitem/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

