<?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>Mind The Robot</title>
	<atom:link href="http://mindtherobot.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://mindtherobot.com/blog</link>
	<description>Android™ Dev Insight</description>
	<lastBuildDate>Thu, 17 Feb 2011 10:37:39 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>MTR: Turning the page</title>
		<link>http://mindtherobot.com/blog/753/mtr-turning-the-page/</link>
		<comments>http://mindtherobot.com/blog/753/mtr-turning-the-page/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 10:37:39 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[meta]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=753</guid>
		<description><![CDATA[Guys &#038; Girls, all MTR readers &#8211; as you might have noticed, I haven&#8217;t been writing for MTR for a while already. So at this point, I would like to announce that I will no longer be able to write new articles for this blog any more. MTR has been a successful project for me. [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F753%2Fmtr-turning-the-page%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F753%2Fmtr-turning-the-page%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Guys &#038; Girls, all MTR readers &#8211; as you might have noticed, I haven&#8217;t been writing for MTR for a while already. So at this point, I would like to announce that I will no longer be able to write new articles for this blog any more.</p>
<p>MTR has been a successful project for me. I exchanged a lot of knowledge, found many friends all over the world and started my own cool Android project with a guy who I met here in this blog.</p>
<p>I am moving to a new exciting position in my company where I will need to keep focused on the higher level picture of IT trends, which includes the mobile world but is not limited to it. I am also highly devoted to my app, Su-Preme MPA, which is supposed to see its first full version released very soon. Thus, to avoid spreading myself too thin, I decided to cease my work on Mind The Robot.</p>
<p>However, this by no means should be the end of MTR itself! </p>
<p>First of all, I will keep the blog hosted and up and will try to answer your comments as often as I can. </p>
<p>Second, if you feel like writing an Android article for MTR, I will be happy to give you an account so you can post it. The blog currently has about 700-800 visits per day so your article will definitely be seen. Just contact me at ivan@mindtherobot.com.</p>
<p>Again, thanks for all your feedback, your comments and everything. </p>
<p>Sincerely yours,<br />
Ivan @ MTR</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/753/mtr-turning-the-page/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Su-Preme MPA: The first demo video of my first app!</title>
		<link>http://mindtherobot.com/blog/748/su-preme-mpa-the-first-demo-video-of-my-first-app/</link>
		<comments>http://mindtherobot.com/blog/748/su-preme-mpa-the-first-demo-video-of-my-first-app/#comments</comments>
		<pubDate>Thu, 23 Dec 2010 10:37:57 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[mpa]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=748</guid>
		<description><![CDATA[Check out the first demo vid of Su-Preme MPA &#8211; my first Android app to be released on the market in few days! MPA is a sample based music production app that mimics the look and feel of a classic analog device that is widely popular among urban music producers. I&#8217;m proud to say that [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F748%2Fsu-preme-mpa-the-first-demo-video-of-my-first-app%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F748%2Fsu-preme-mpa-the-first-demo-video-of-my-first-app%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Check out the first demo vid of <b>Su-Preme MPA</b> &#8211; my first Android app to be released on the market in few days! </p>
<p>MPA is a sample based music production app that mimics the look and feel of a classic analog device that is widely popular among urban music producers. </p>
<p>I&#8217;m proud to say that MPA is not a toy. We really mean it to be used by actual music producers to make actual beats. </p>
<p>The app was co-designed and will be promoted by Alaric &#8220;Supreme&#8221; Wilder of Wu-Tang Clan fame. He also did the video!</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/vQ5Ge-7XbJ4?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/vQ5Ge-7XbJ4?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/748/su-preme-mpa-the-first-demo-video-of-my-first-app/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Android Hacks: Scan Android classpath</title>
		<link>http://mindtherobot.com/blog/737/android-hacks-scan-android-classpath/</link>
		<comments>http://mindtherobot.com/blog/737/android-hacks-scan-android-classpath/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 10:07:46 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[hacks]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=737</guid>
		<description><![CDATA[Why scan the classpath? There are various patterns that are often used in enterprise Java applications that require scanning of classpath and getting the list of all classes that are present in the application. For example, if you want to discover all classes with a certain annotation (such as @Component in Spring Framework) to process [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F737%2Fandroid-hacks-scan-android-classpath%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F737%2Fandroid-hacks-scan-android-classpath%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://mindtherobot.com/blog/wp-content/uploads/2010/12/cpscan-pic.png" alt="" width="464" height="125" class="aligncenter size-full wp-image-740" /></p>
<p>Why scan the classpath? There are various patterns that are often used in enterprise Java applications that require scanning of classpath and getting the list of all classes that are present in the application.</p>
<p>For example, if you want to discover all classes with a certain annotation (such as <strong>@Component</strong> in Spring Framework) to process them in a special way, you need a way to go over all classes in your application and select some of them based on which annotations they have.</p>
<p>However, neither Java SE nor Android have built-in facilities to safely get the list of all classes in your application in runtime. The reason for that is the theory behind classloaders in Java &#8211; the ability to go over all classes is neither needed in classic OOP nor feasible for all theoretically possible classloader implementations. However, in practice, scanning classpath and discovering the classes you need is quite possible in most cases, both in your web app and on Android. This is always going to be more or less a hack, but if it has been useful in web applications, it can also be useful in Android apps &#8211; with some caution, of course.</p>
<p>Thus, in this article I will show and explain a piece of code that does exactly that &#8211; scans your classpath and gives you the ability to go over all classes in your app.<br />
<span id="more-737"></span></p>
<h3>Action plan</h3>
<p>So here&#8217;s how we could approach the problem of going over the set of application classes in runtime:</p>
<ol>
<li>We assume that Android <strong>PathClassLoader</strong> (<a href="http://android.git.kernel.org/?p=platform/libcore.git;a=blob;f=dalvik/src/main/java/dalvik/system/PathClassLoader.java;h=5d7333e13609a49605ff2dbde703a4619ae2f58a;hb=HEAD" target="_blank">see source here</a>) is used for classloading in your app.</li>
<li>As you can see in the source above, the list of DEX files (typically one but theoretically more) that contain your app classes, is kept in the private field called <strong>mDexs</strong>. We can use invasive reflection to get the field value and thus the list of DEXs.</li>
<li>Once we get the list of DEXs, we can use the API of the <strong>DexFile</strong> class to get the list of its entries (which are class names) and there you go.</li>
</ol>
<p>As I said above, this plan is 90% hacking so we should take whatever assumptions we make with a grain of salt, and do as much error handling and checking as possible, if we actually choose to use this approach in a production app.</p>
<p>Now let&#8217;s write some code.</p>
<h3>Code example</h3>
<p>Say we have an annotation called <strong>Foo</strong> and few classes decorated with it:</p>
<pre class="brush: java; title: ; notranslate">
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo {
	String value();
}

@Foo(&quot;person&quot;)
public class Person {

}

@Foo(&quot;order&quot;)
public class Order {

}
</pre>
<p>Here&#8217;s a simple class that goes over all classes in your app in runtime, finds those marked with <strong>@Foo</strong> and get the value of the annotation. <strong>Do not copy and paste this code into your app</strong> &#8211; it has a lot to be fixed and added, as described below the code.</p>
<pre class="brush: java; title: ; notranslate">
public class ClasspathScanner {
	private static final String TAG = ClasspathScanner.class.getSimpleName();

	private static Field dexField;
	
	static {
		try {
			dexField = PathClassLoader.class.getDeclaredField(&quot;mDexs&quot;);
			dexField.setAccessible(true);
		} catch (Exception e) {
			// TODO (1): handle this case gracefully - nobody promised that this field will always be there
			Log.e(TAG, &quot;Failed to get mDexs field&quot;);
		} 
	}
	
	public void run() {
		try {
			// TODO (2): check here - in theory, the class loader is not required to be a PathClassLoader
			PathClassLoader classLoader = (PathClassLoader) Thread.currentThread().getContextClassLoader();

			DexFile[] dexs = (DexFile[]) dexField.get(classLoader);
			for (DexFile dex : dexs) {
				Enumeration&lt;String&gt; entries = dex.entries();
				while (entries.hasMoreElements()) {
					// (3) Each entry is a class name, like &quot;foo.bar.MyClass&quot;
					String entry = entries.nextElement();
					Log.d(TAG, &quot;Entry: &quot; + entry);

					// (4) Load the class
					Class&lt;?&gt; entryClass = dex.loadClass(entry, classLoader);
					if (entryClass != null) {
						Foo annotation = entryClass.getAnnotation(Foo.class);
						if (annotation != null) {
							Log.d(TAG, entry + &quot;: &quot; + annotation.value());
						}
					}
				}
			}
		} catch (Exception e) {
			// TODO (5): more precise error handling
			Log.e(TAG, &quot;Error&quot;, e);
		}
	}
}
</pre>
<p>Let&#8217;s review what we have there.</p>
<ul>
<li>(1) A future version of Android might change the internal structure of <strong>PathClassLoader</strong> and the field might not be found. Production code should somehow deal with it. </li>
<li>(2) A future version of the platform might use other classloader than <strong>PathClassLoader</strong> &#8211; another thing to be handled in real code.</li>
<li>(3) To save some time, you might scan only some specific packages rather than everything.</li>
<li>(4) A real good improvement would be to get class metadata without loading the class &#8211; something that <a href="http://www.javassist.org/" target="_blank">javassist</a> can do in Java SE. In this implementation, every class will actually be loaded which is slow.</li>
<li>(5) And of course you should handle each possible exception type specifically.</li>
</ul>
<p>As you can see, the solution can&#8217;t really be called reliable or future-proof. Use with caution.</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/737/android-hacks-scan-android-classpath/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Business Android: Enterprise APIs missing in the platform</title>
		<link>http://mindtherobot.com/blog/700/android-architecture-enterprise-apis/</link>
		<comments>http://mindtherobot.com/blog/700/android-architecture-enterprise-apis/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 05:04:36 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=700</guid>
		<description><![CDATA[My definition or, rather, my perception of an enterprise mobile app is generally the following: The app in question is a mobile client for a multi-user client-server application. It can either be the only kind of client for the app, or co-exist with a web interface or, for example, a PC desktop client for the [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F700%2Fandroid-architecture-enterprise-apis%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F700%2Fandroid-architecture-enterprise-apis%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>My definition or, rather, my perception of an <i>enterprise mobile app</i> is generally the following:<br />
<img src="http://mindtherobot.com/blog/wp-content/uploads/2010/12/office_building_commercial_loan.jpg" alt="" title="office_building_commercial_loan" width="315" height="209" class="alignleft size-full wp-image-716" style="margin-right:30px;" /></p>
<ul>
<li>The app in question is a <strong>mobile client for a multi-user client-server application</strong>. It can either be the only kind of client for the app, or co-exist with a web interface or, for example, a PC desktop client for the same server app.</li>
<li>It has a <strong>&#8220;serious&#8221; user interface</strong> &#8211; rather than trying to impress the end-user with a slick, non-typical UI, it aims to be as straightforward and predictable as possible. It tends to have various forms, charts, trees and lists of various complexity.</li>
<li>Conceptually, very often a big part of the app is dedicated to <strong>managing (CRUDing) a set of entities</strong> such as users, documents, reports etc. Domain models can get quite complex, often with tree-like structures, fine-grained user permissions with different access levels and profiles.</li>
<li>Internally the app uses <strong>typical client-server protocols</strong> like SOAP, XML-RPC or even CORBA. Often in-house protocols and frameworks are used on top of those generic ones or instead of them. You get the picture.</li>
</ul>
<p>Enterprise apps might not seem to be the most interesting kind to work on. However, they are attractive for many studios because customers usually pay well for them. In addition, as a developer, you will find that they are often challenging to implement &#8211; at least with functional and internal quality that will satisfy both the customer and you.</p>
<p>In this article, I would like to cover a list of typical facilities that Android developers need when developing such kind of apps.  The platform does not really have that much to offer (as we will see), and many developers build their own ad-hoc frameworks that they try to reuse as needs arise.</p>
<p>I will share some thoughts that I have about that, and will be happy to know your stories too.<br />
<span id="more-700"></span></p>
<h4>UI Framework</h4>
<p><a href="http://mindtherobot.com/blog/wp-content/uploads/2010/12/android_codicefiscale_form.png" target="_blank"><img src="http://mindtherobot.com/blog/wp-content/uploads/2010/12/android_codicefiscale_form-200x300.png" alt="" title="android_codicefiscale_form" width="200" height="300" class="alignright size-medium wp-image-725" /></a></p>
<p>One of the most important facilities you need in a typical enterprise mobile client app is a framework that will allow you to quickly put together a form that consists of a set of fields of various types represented by various UI controls. Have a look at the example on the right &#8211; it is <strong>Alessandro La Rosa&#8217;s</strong> <a href="http://www.jappit.com/blog/2009/05/04/first-android-app-calculate-your-italian-tax-id-codice-fiscale/" target="_blank">example app to calculate your taxes if you live in Italy</a> (click to see full-size).</p>
<p>It might seem that Android has enough built-in UI APIs not to make you think about adding any framework layer of your own. However, some things are missing:</p>
<ul>
<li>There is no <strong>dedicated layout class</strong> that allows to make quick and efficient (especially for various display sizes) form-like UIs where you have a set of controls and labels attached to them. You will probably either use <b>LinearLayout</b> or <b>TableLayout</b>, or build your own FormLayout on top of them.</li>
<li>There is no <strong>data-binding framework</strong>. Remember <a href="http://mindtherobot.com/blog/675/android-architecture-message-based-mvc/" target="_blank">I talked about MVC multiple times already</a>. What I want to say here is that you&#8217;d like user&#8217;s input automatically bound to your POJO model object rather than kept inside a set of UI controls like <b>TextView</b>s and <b>Spinner</b>s. <b>Adapter</b>s seem to do a part of the job for lists as they work one-way (from data to UI) rather than two-way. In any case, what we usually want is a control-level solution, such as one that allows you to bind an underlying bean&#8217;s property <i>name</i> to a <b>TextView</b> with the ID <i>name_view</i>.</li>
<li>There is no common way to detect and express <strong>validation errors</strong>. Almost any form lets the user enter invalid data and then rejects it and helps the user find and fix their error. There are two parts of this facility &#8211; an engine that allows you to specify your validation constraints and get the list of errors given an input, and a common way to present those errors in the UI. The platform does not have either of those, so you will have to decide how you do it. If you have created a data binding/MVC solution as described in the previous point, then it will typically take over validation as a phase in its UI-to-data process. When you want to display the errors you found, you can show a popup dialog, or insert a yellow bar at the top of the form, or show each error near the field that it is related to etc. You&#8217;ll have to do it manually for each form, or build a set of reusable classes that will help you.</li>
<li>If you have really many forms in your app, you might consider building <strong>a form-generating framework</strong> (like those often found in RAD environments) that allows generating dynamic forms based on your POJO beans (that you will perhaps annotate with helper UI annotations such as <i>@MediumText</i> or <i>@Spinner(min=1, max=100)</i> etc.) with minimum work spent on UI.</li>
</ul>
<p>In addition to the form problem, there are many views missing in the platform that are typically needed for enterprise apps, such as a <strong>sortable paginated data table</strong>, various charts etc. If you do build those components, make sure they are as generic as possible &#8211; there is real value in reusable views when you build your next app.</p>
<h4>Server connection</h4>
<p>The most obvious missing part in the Android core platform in terms of remote connections is <strong>SOAP</strong>. There is no SOAP client framework in the platform. This might in fact be a good thing as it should be pretty easy to port the most suitable among the Java SE libraries that do SOAP to Android. The HTTP client that <i>is</i> included in the platform is based on <a href="http://hc.apache.org/httpclient-3.x/" target="_blank">Apache Commons HTTP Client</a> which is a respected and stable piece of code that will serve as a foundation for your SOAP framework. </p>
<p>If your SOAP/XML/JSON-based protocol is complicated, or if you plan well ahead, you will think of including a solution to <strong>bind your model beans (POJOs) to XML/JSON and back</strong> so that you deal with as little XML as possible. Again, there are existing solutions for that in Java SE, but you will have to think if they fit your performance expectations when ported to Android.</p>
<p>A very common requirement is to keep a server connection open to listen to push-type server events. Luckily, Android has <b>Service</b> (you can read <a href="http://mindtherobot.com/blog/37/android-architecture-tutorial-developing-an-app-with-a-background-service-using-ipc/" target="_blank">one of the first articles on this blog</a> to learn more about it). If you want to build a higher-level abstract that represents a <i>service-that-keeps-server-connection</i>, I think it could be a good idea and quite reusable in various apps.</p>
<p>What I would also recommend is that if you decide to let a Service do some of your server requests, then it should probably do all of them. You shouldn&#8217;t generally do server requests both from Activities and Services. If an Activity needs to issue a server request, you can use IPC to pass it to the Service. Doing all of your server requests in one place allows you to queue them up gracefully, maybe optimize them, and avoid unexpected network load.</p>
<p>In any case, what you would like to do in enterprise apps is to abstractize from the low-level details of opening connections, retrying requests and parsing HTTP and XML data. There is little platform support, but it is possible to do yourself.</p>
<h4>Local storage</h4>
<p>Android has multiple ways for you to store some data on the device. You can use SQLite behind a <b>ContentProvider</b>, or plain SQLite using <strong>SQLiteDatabase</strong>, or files using serialization, parcelization or whatever other format.</p>
<p>What I am missing here, again, is a way to <b>bind model data to storage and back</b>. Serialization is not as affected by this problem but it has various other issues such as keeping track of class versions and incompatibility with anything else but Java.</p>
<p>Don&#8217;t get me wrong, I&#8217;m not saying we need to port <strong>Hibernate</strong> to Android &#8211; at least not now. But a more lightweight and Android-optimized framework to save you from doing it all manually could be very useful. Perhaps a good solution would be to generate source or byte code, or just the necessary SQL strings at the compilation stage. Any automated solution would be better than writing SQL manually as Java strings if you ask me.</p>
<p>In addition, the server connection part of your framework can be combined with the local storage part to build solutions for <strong>synchronization</strong>, <strong>caching</strong> and <strong>offline access</strong> in your app &#8211; all of which are appreciated in enterprise applications. </p>
<h4>Conclusion</h4>
<p>I just covered the &#8220;most missing&#8221; parts of API that we need and we develop for our enterprise apps. There are other things too, such as building custom UI themes (which is not so easy), security issues when allowing to sign in using different server accounts, encryption etc.</p>
<p>What I was trying to say with this article is not that the Android platform is poor in its enterprise features. Well, maybe a little. But we Android devs as a community should be looking towards sharing and open-sourcing more of what we do when it comes to reusable components, be it enterprise or any other genre of apps. At some point, we should introduce a Spring Framework equivalent, a Hibernate equivalent and a JSF (or whatever) equivalent that are all built specifically for Android. What do you think?</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/700/android-architecture-enterprise-apis/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Android Architecture: Message-based MVC</title>
		<link>http://mindtherobot.com/blog/675/android-architecture-message-based-mvc/</link>
		<comments>http://mindtherobot.com/blog/675/android-architecture-message-based-mvc/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 14:31:00 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[handler]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[queue]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=675</guid>
		<description><![CDATA[How do you separate application state, user interaction logic and data presentation in your Android apps? Platform designers did not enforce any high-level application architecture framework upon us but left us enough options to implement our own solutions based on application requirements and scale. Most simple applications will get away with just storing data in [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F675%2Fandroid-architecture-message-based-mvc%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F675%2Fandroid-architecture-message-based-mvc%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://mindtherobot.com/blog/wp-content/uploads/2010/11/asyncmvc1.jpg" alt="" title="asyncmvc" class="alignright size-full wp-image-693" /></p>
<p>How do you separate application state, user interaction logic and data presentation in your Android apps?</p>
<p>Platform designers did not enforce any high-level application architecture framework upon us but left us enough options to implement our own solutions based on application requirements and scale. Most simple applications will get away with just storing data in their widgets (such as in text fields, spinners etc.) and their state manipulation right in event handlers such as <b>OnClickListener</b>&#8216;s. However, if you are going to write a complex application or plan to sophisticate your simple app further, you should really think how to layer it well so that the architecture supports adding new features and satisfies the expected performance, flexibility, responsiveness and other requirements, and your code does not become a mess.</p>
<p>In this article, I will show you one practical approach to dividing application code into three layers according the MVC paradigm and connecting the view to the controller using the Android messaging framework. I used it in my own code and although it might not be 100% academically correct or applicable for every possible app, I love the benefits it gives to me as my app grows more and more complex.<br />
<span id="more-675"></span></p>
<h3>Intro</h3>
<p>I will not go deep into explaining the MVC architecture pattern &#8211; there&#8217;s a lot of places where you can read about it. I wrote <a href="http://www.wiseandroid.com/post/2010/07/19/Use-MVC-and-develop-a-simple-Star-Rating-widget-on-Android.aspx" target="_blank">an article on how to apply this architecture to a single component</a> but it can also be applied to the entire application. I expect you understand what the Model, View and Controller layers are expected to be there for.</p>
<p>In addition, if you did not read <a href="http://mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers/" target="_blank">the article on Handler</a>, please do so. Although it does not cover messaging per se, it gives you understanding of the threading model that is behind it.</p>
<p>I wrote a sample app that I will use throughout this article. You can download the complete source at the end of the article.</p>
<h3>Part 1: Model</h3>
<p>It is a good sign when the Model layer is generic and is only tied to the domain logic. In our demo app, it is completely obvious and boring, except for few things.</p>
<p>First, there is a separate class that contains the model &#8220;data&#8221;, in other words, whatever state that might change in the Model layer during the application lifecycle:</p>
<pre class="brush: java; title: ; notranslate">
@Immutable
public final class ModelData implements Serializable {

	private static final long serialVersionUID = 1L;

	private final int answer;
	
	public ModelData(int answer) {
		this.answer = answer;
	}
	
	public final int getAnswer() {
		return answer;
	}
}
</pre>
<p>As you can see, I like to put a descriptive annotation like <b>@Immutable</b> so that I remember this class is actually immutable which gives a lot of benefits such as the ability to share instances between threads and others. In addition, I made the class <b>Serializable</b> &#8211; serializing it would allow to, for example, implement a &#8220;Save/Load&#8221; feature.</p>
<p>As for the Model class itself, here it is:</p>
<pre class="brush: java; title: ; notranslate">
@ThreadSafe
public class Model {
	public interface Listener {
		void onModelStateUpdated(Model model);
	}
	
	private ModelData data = new ModelData(0);
	
	private final List&lt;Listener&gt; listeners = new ArrayList&lt;Listener&gt;();
	
	public Model() {
		
	}
	
	public final ModelData getData() {
		synchronized (this) {
			return data;
		}
	}
	
	public final void updateData() { // takes a while!
		SystemClock.sleep(5000);
		ModelData newData = new ModelData(new Random().nextInt(10) + 1);
		
		synchronized (this) {
			data = newData;
		}
		
		synchronized (listeners) {
			for (Listener listener : listeners) {
				listener.onModelStateUpdated(this);
			}
		}
	}
	
	public final void addListener(Listener listener) {
		synchronized (listeners) {
			listeners.add(listener);
		}
	}
	
	public final void removeListener(Listener listener) {
		synchronized (listeners) {
			listeners.remove(listener);
		}
	}
}
</pre>
<p>As you can see, the <b>updateData()</b> method is written so that it takes some time to execute, which in the real life could be a request to the server and/or a heavy computation. The data is kept protected from concurrent access using <b>synchronized</b>. Listeners can also be added and removed from concurrent threads. If you actually understood MVC, you should realize that model listeners are a core part of the pattern &#8211; they allow you to tie any code to the model without the model knowing anything about it (and thus the model code avoids any non-business logic injection).</p>
<p>Now to the most interesting part &#8211; the Controller layer.</p>
<h3>Part 2: Controller</h3>
<p>At this point you can implement the Controller layer in various ways. The way I chose to present is based on <b>Handler</b>, <b>HandlerThread</b> and <b>Message</b> classes. Again, you should have a basic understanding of how they work.</p>
<p>In essence, with those classes the Android platform allows you to implement effective, safe and powerful messaging between various pieces of your app. In our case, what I&#8217;d like to do is:</p>
<ul>
<li>Give the Controller an <b>inbox</b> handler &#8211; so that the View layer can send messages to it, such as &#8220;the user asked us to quit&#8221; or &#8220;the user asked us to update the data&#8221;. </li>
<li>Give the ability to attach one or multiple <b>outbox</b> handlers to the Controller, so that the Controller can send its own messages to the View (or Views) &#8211; such as &#8220;model update finished&#8221; or &#8220;destroy yourself, we are quitting&#8221; etc.</li>
<li>This way, the View can only turn user events into messages and send them to Controller without thinking of how to react to them, and whenever the Controller gives any message to the View, the View will mindlessly execute whatever the Controller tells it while presenting the application status to the user. Thus we get a clean implementation of the MVC paradigm.</li>
</ul>
<p>Now, since every <b>Handler</b> needs a <b>Looper</b>, we need to choose a thread where we will run the Controller&#8217;s inbox handler. We could either do it on the UI thread (and it will process both UI messages and Controller&#8217;s messages) or on a new separate <b>HandlerThread</b>. Normally our Controller is going to process its messages without blocking on slow operations so that it can stay responsive to the View. Any slow operations will be run in background threads. Thus, we could use the UI thread for Controller&#8217;s messages without worrying much. However, I chose to run a separate thread just because I think that is a cleaner architecture and perhaps it could be a bit more responsive. Since the messaging framework saves us from many concurrency headaches, we can easily jump from one solution to the other without changing much code. </p>
<p>This is how we manage the inbox and outbox handlers in the code:</p>
<pre class="brush: java; title: ; notranslate">
public class Controller {

        // ... some code omitted ...

	private final HandlerThread inboxHandlerThread;
	private final Handler inboxHandler;
	private final List&lt;Handler&gt; outboxHandlers = new ArrayList&lt;Handler&gt;();
	
        // ... some code omitted ...

	public Controller(Model model) {
		this.model = model;
		
		inboxHandlerThread = new HandlerThread(&quot;Controller Inbox&quot;); // note you can also set a priority here
		inboxHandlerThread.start();
		 
        // ... some code omitted ...

		inboxHandler = new Handler(inboxHandlerThread.getLooper()) {
			@Override
			public void handleMessage(Message msg) {
				Controller.this.handleMessage(msg);
			}
		};
	}
	
	public final void dispose() {
		// ask the inbox thread to exit gracefully
		inboxHandlerThread.getLooper().quit();
	}
	
	public final Handler getInboxHandler() {
		return inboxHandler;
	}
	
	public final void addOutboxHandler(Handler handler) {
		outboxHandlers.add(handler);
	}

	public final void removeOutboxHandler(Handler handler) {
		outboxHandlers.remove(handler);
	}
	
	final void notifyOutboxHandlers(int what, int arg1, int arg2, Object obj) {
		if (outboxHandlers.isEmpty()) {
			Log.w(TAG, String.format(&quot;No outbox handler to handle outgoing message (%d)&quot;, what));
		} else {
			for (Handler handler : outboxHandlers) {
				Message msg = Message.obtain(handler, what, arg1, arg2, obj);
				msg.sendToTarget();
			}
		}
	}

        // ... some code omitted ...
}
</pre>
<p>This is not the complete code for Controller, we&#8217;ll come back to it later. OK, so what you can see is how we initialize and bring down the inbox handler and its thread, how you can subscribe your handler as an outbox one and you how you notify all outbox handlers with a message.</p>
<p>With this code, we can take the inbox handler and send message to it from the View layer and at the same time have a View-bound handler registered as an outbox handler for the Controller, and that will allow the Controller and the View to exchange async messages effectively.</p>
<p>Now in order to actually handle incoming messages and do something, we need to implement the <b>handleMessage()</b> method in the <b>Controller</b> class. In most applications you will want to implement an instance of the <b>State design pattern</b> here because depending on what the application is doing right now it might handle the same messages differently, or ignore some of them. For example, in our application, once you start refreshing the Model, we wouldn&#8217;t like the user to allow refreshing it again until we&#8217;re done. To illustrate that, here&#8217;s the <b>ControllerState</b> interface and its <b>ReadyState</b> implementation:</p>
<pre class="brush: java; title: ; notranslate">
public interface ControllerState {
	boolean handleMessage(Message msg);
}

final class ReadyState implements ControllerState {

	private final Controller controller;
	
	public ReadyState(Controller controller) {
		this.controller = controller;
	}
	
	@Override
	public final boolean handleMessage(Message msg) {
		switch (msg.what) {
		case V_REQUEST_QUIT:
			onRequestQuit();
			return true;
		case V_REQUEST_UPDATE:
			onRequestUpdate();
			return true;
		case V_REQUEST_DATA:
			onRequestData();
			return true;
		}
		return false;
	}

	private void onRequestData() {
		// send the data to the outbox handlers (view)
		controller.notifyOutboxHandlers(C_DATA, 0, 0, controller.getModel().getData());
	}

	private void onRequestUpdate() {
		// we can't just call model.updateState() here because it will block
		// the inbox thread where this processing is happening.
		// thus we change the state to UpdatingState that will launch and manage
		// a background thread that will do that operation

		controller.changeState(new UpdatingState(controller));
	}

	private void onRequestQuit() {
		controller.quit();
	}
}
</pre>
<p>By putting the Controller and its states to the same package, we can give them access to Controller&#8217;s internals using the default access level. I won&#8217;t put <b>UpdatingState</b> code here, it&#8217;s in the package at the bottom of the page.</p>
<p>Now here&#8217;s how Controller delegates message processing to its state:</p>
<pre class="brush: java; title: ; notranslate">
public class Controller {

        // ... some code omitted ...
	private ControllerState state;
	
	public Controller(Model model) {
		this.model = model;
		
        // ... some code omitted ...
		 
		this.state = new ReadyState(this);

        // ... some code omitted ...
	}
	
        // ... some code omitted ...

	private void handleMessage(Message msg) {
		Log.d(TAG, &quot;Received message: &quot; + msg);
		
		if (! state.handleMessage(msg)) {
			Log.w(TAG, &quot;Unknown message: &quot; + msg);
		}
	}
	
	final Model getModel() {
		return model;
	}

	final void quit() {
		notifyOutboxHandlers(C_QUIT, 0, 0, null);
	}
	
	final void changeState(ControllerState newState) {
		Log.d(TAG, String.format(&quot;Changing state from %s to %s&quot;, state, newState));
		state = newState;
	}
}
</pre>
<p>And this is basically how the Controller layer looks. Now let&#8217;s bind a View to it.</p>
<h3>Part 3: View</h3>
<p>Without many explanations &#8211; I guess you&#8217;ve got the idea already &#8211; here&#8217;s the View code (<b>DemoActivity</b>):</p>
<pre class="brush: java; title: ; notranslate">
public class DemoActivity extends Activity implements Handler.Callback, OnClickListener {
	
	private static final String TAG = DemoActivity.class.getSimpleName();
	
	private Controller controller;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        
        ((Button) findViewById(R.id.update)).setOnClickListener(this);
        ((Button) findViewById(R.id.quit)).setOnClickListener(this);
        
        controller = new Controller(new Model());
        controller.addOutboxHandler(new Handler(this)); // messages will go to .handleMessage()
        
        controller.getInboxHandler().sendEmptyMessage(V_REQUEST_DATA); // request initial data
    }

	@Override
	protected void onDestroy() {
		// I think it is a good idea to not fail in onDestroy()
		try {
			controller.dispose();
		} catch (Throwable t) {
			Log.e(TAG, &quot;Failed to destroy the controller&quot;, t);
		} 

		super.onDestroy();
	}

	@Override
	public boolean handleMessage(Message msg) {
		Log.d(TAG, &quot;Received message: &quot; + msg);
		 
		switch (msg.what) {
		case C_QUIT:
			onQuit();
			return true;
		case C_DATA:
			onData((ModelData) msg.obj);
			return true;
		case C_UPDATE_STARTED:
			onUpdateStarted();
			return true;
		case C_UPDATE_FINISHED:
			onUpdateFinished();
			return true;
		}
		return false;
	}

	private void onUpdateStarted() {
		ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
		progressBar.setVisibility(View.VISIBLE);
	}

	private void onUpdateFinished() {
		ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
		progressBar.setVisibility(View.GONE);
		
		// request the updated data
		controller.getInboxHandler().sendEmptyMessage(V_REQUEST_DATA);
	}

	private void onData(ModelData data) {
		TextView dataView = (TextView) findViewById(R.id.data_view);
		dataView.setText(&quot;The answer is &quot;+ data.getAnswer());
	}

	private void onQuit() {
		Log.d(TAG, &quot;Activity quitting&quot;);
		finish();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.update:
			controller.getInboxHandler().sendEmptyMessage(V_REQUEST_UPDATE);
			break;
		case R.id.quit:
			controller.getInboxHandler().sendEmptyMessage(V_REQUEST_QUIT);
			break;
		}
	}
}
</pre>
<p>In this demo app, the Activity actually owns the <b>Controller</b> instance which holds the model. However, you might consider moving the Controller to a Service if its lifecycle fits the Controller/Model lifecycle better.</p>
<h4>Summary</h4>
<p>As you can see, the message-based approach really allows building a strong complex Controller and a completely dumb View. That allows us to achieve a good MVC implementation.</p>
<p>As I wrote it in the very beginning, this solution might not be completely valid from the theoretical point of view or not good for any app, however I have experience building a very complex app with many states and it is completely based on messages. There are many weaknesses in this architecture, such as the need to collect message codes somewhere (see <b>ControllerProtocol</b>) and to define message parameters in documentation. But the upside is very good layer separation which gives you enormous benefits as the app grows. </p>
<p><b>Attachment:</b> <a href='http://mindtherobot.com/blog/wp-content/uploads/2010/11/async-mvc.zip'>async-mvc.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/675/android-architecture-message-based-mvc/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>The Robot Is Back</title>
		<link>http://mindtherobot.com/blog/656/the-robot-is-back/</link>
		<comments>http://mindtherobot.com/blog/656/the-robot-is-back/#comments</comments>
		<pubDate>Fri, 12 Nov 2010 06:23:24 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[recommendations]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=656</guid>
		<description><![CDATA[After few months of busy work in the underground laboratories, MTR is back again. As you can see, I have even installed a new theme which looks to me kinda less annoying and more effective in terms of content. What I plan to do is, of course, to continue the series of articles on Android [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F656%2Fthe-robot-is-back%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F656%2Fthe-robot-is-back%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://mindtherobot.com/blog/wp-content/uploads/2010/11/we_get_signal-11.jpg" alt="WE GET SIGNAL" title="we_get_signal (1)" width="350" height="246" class="alignright size-full wp-image-659" /></p>
<p>After few months of busy work in the underground laboratories, MTR is back again. As you can see, I have even installed a new theme which looks to me kinda less annoying and more effective in terms of content.</p>
<p>What I plan to do is, of course, to continue the series of articles on Android development so we can go on sharing our knowledge and experience. Many things have been changing in the Android world. Tablets are here today, and new versions of the platform are soon to come. Android is becoming a more and more widespread and seriously taken platform and at this point, there is no way back.</p>
<p>As for this blog, it is still going to be about useful content (at least content that I consider useful), not about promo articles or high traffic volumes. I am still very interested in general architecture topics, plus multimedia (especially audio) and, sure enough, your questions, issues and achievements.</p>
<p>Some of the topics that are coming up are:<br />
<span id="more-656"></span></p>
<ul>
<li><b>Architecture:</b> Building well-layered model/view/controller app architectures</li>
<li><b>Audio:</b> Mixing multiple audio streams and generating waveform images</li>
<li><b>UI:</b> Making your custom views look good on various devices</li>
</ul>
<p>However, in addition to those topics that you can count on, I would like to know more about what you dear readers actually would love to get. Hence this little poll &#8211; please vote:</p>
Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.
<p>Thank you and have a nice day!</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/656/the-robot-is-back/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Android Performance: Be careful with byte[]</title>
		<link>http://mindtherobot.com/blog/633/android-performance-be-careful-with-byte/</link>
		<comments>http://mindtherobot.com/blog/633/android-performance-be-careful-with-byte/#comments</comments>
		<pubDate>Tue, 21 Sep 2010 22:44:23 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[guts]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=633</guid>
		<description><![CDATA[There are many cases where we use byte[] in our code. In fact, it is the &#8220;rawest&#8221; type possible in Java unless you go native. Thus, byte arrays are often used to store raw data such as bitmaps, audio and various binary objects. The previous two articles on MTR were dedicated to audio decoders, including [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F633%2Fandroid-performance-be-careful-with-byte%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F633%2Fandroid-performance-be-careful-with-byte%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>There are many cases where we use <b>byte[]</b> in our code. In fact, it is the &#8220;rawest&#8221; type possible in Java unless you go native. Thus, byte arrays are often used to store raw data such as bitmaps, audio and various binary objects.</p>
<p>The previous two articles on MTR were dedicated to audio decoders, including <a href="http://mindtherobot.com/blog/580/android-audio-play-a-wav-file-on-an-audiotrack/" target="_blank">WAV</a> and <a href="http://mindtherobot.com/blog/624/android-audio-play-an-mp3-file-on-an-audiotrack/" target="_blank">MP3</a>. In both cases, raw PCM data that was the result of your decoding was a byte array (which you would later write to <b>AudioTrack</b>).</p>
<p>I already mentioned in one of those articles that you should consider streaming any audio that is longer than the reasonable maximum. However, even if your data will definitely fit into the heap, in most cases you can still do better than just using a byte array. Why? Read on (relevant for non-audio <b>byte[]</b>s as well!)<br />
<span id="more-633"></span></p>
<h3>Some low level GC gore</h3>
<p>While we Java developers are used to not take <b>JVM heap</b> topology and <b>garbage collection</b> into account too much (and that is generally the correct mindset), on small devices we should be aware of their existence more than on desktops or all the more on the server side. Yes, JVM will do as much as possible for you to fly free, yet it will not be able to handle extreme cases as smoothly without some assistance from your side.</p>
<p>As you remember from the article on decoding WAVs, a 10 second audio will take about <b>1.7Mb</b> of heap. This is an acceptable size for Android where most devices will allocate either <b>16Mb</b> or <b>24Mb</b> maximum per process. However, storing this data as a large <b>byte[]</b> (which is the straightforward way and the first way that comes to one&#8217;s mind) is not a good idea and here is why.</p>
<p>Internally, byte arrays are represented as, well, byte arrays. For obvious reasons they require a <b>continuous heap chunk</b>. That is, if your heap is <b>fragmented</b>, JVM <b>will have to run GC</b> in order to <b>defrag</b> the heap &#8211; even if technically you had enough space (total!) to fit the amount of data that you needed.</p>
<p>As the result, you will have a lot of objects being transferred back and forth by GC to make room for that big fat array. Things get worse when you have a handful (more than one) large byte arrays that should definitely fit the heap if you look at the numbers (total size and free heap space), but will give GC a real hard time trying to lay them out in the heap space. The more large objects you have, the longer and scarier GC pauses will become.</p>
<h3>Splitting byte[] data into chunks</h3>
<p>The obvious solution would be to split the large <b>byte[]</b> into chunks. And in this case, the obvious thing to do is also a good one. Here&#8217;s a sketch of the <b>ChunkedByteBlob</b> class that implements a nice split byte container:</p>
<pre class="brush: java; title: ; notranslate">
public final class ChunkedByteBlob {
	private final int totalSize;
	private final int chunkSize;
	private final int totalChunks;
	private final byte[][] chunks;
	
	public ChunkedByteBlob(int totalSize, int chunkSize) {
		if (totalSize &lt;= 0) {
			throw new IllegalArgumentException(&quot;totalSize is &lt;= 0: &quot; + totalSize);
		} else if (totalSize &lt; chunkSize) {
			throw new IllegalArgumentException(&quot;totalSize &quot; + totalSize + &quot; is &lt; chunkSize &quot; + chunkSize);
		}
		
		this.totalSize = totalSize;
		this.chunkSize = chunkSize;
		this.totalChunks = (int) Math.ceil((double) totalSize / (double) chunkSize);
		this.chunks = new byte[totalChunks][];
		
		int sizeLeft = totalSize;
		int i = 0;
		while (sizeLeft &gt; 0) {
			int nextChunkSize = Math.min(sizeLeft, chunkSize);
			sizeLeft -= nextChunkSize;
			
			chunks[i] = new byte[nextChunkSize];
			i++;
		}
	}
	
	public int totalSize() {
		return totalSize;
	}
	
	public int totalChunks() {
		return totalChunks;
	}
	
	public byte[] chunk(int i) {
		return chunks[i];
	}	
	
	public void fillFrom(InputStream stream) throws IOException {
		for (int i = 0; i &lt; totalChunks(); ++i) {
			int sizeToRead = chunk(i).length;
			int sizeRead = 0;
			boolean done = false;
			
			while (! done) {
				int readSize = stream.read(chunk(i), sizeRead, sizeToRead - sizeRead);
				if (readSize &lt; 0) {
					throw new EOFException(&quot;unexpected EOF&quot;);					
				}
				sizeRead += readSize;
				
				if (sizeRead &gt;= sizeToRead) {
					done = true;
				}
			}
		}		
	}

	public void writeTo(OutputStream stream) throws IOException {
		for (byte[] chunk : chunks) {
			stream.write(chunk, 0, chunk.length);
		}
	}
}
</pre>
<p>It should be obvious how this code works, but please do not just copy-paste it &#8211; study it, understand it fully and fix the bugs first. <img src='http://mindtherobot.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Introducing this class in my latest app that deals with a lot of audio data <b>removed a big nasty GC pause</b> that happened every time I loaded another audio sample.</p>
<div style="font-size:75%">
<div id='stb-container-7401' class='stb-container'><div id='stb-caption-box-7401' class='stb-warning-caption_box stb_caption' >Why no benchmarks?</div><div id='stb-body-box-7401' class='stb-warning-body_box stb_body' >I intentionally do not provide any benchmarks or numbers here. Optimization stuff like this is highly specific to every use case, and you <b>have to measure the outcome yourself</b>. I believe there are cases where using basic <b>byte[]</b>s would be much better than using the <b>ChunkedByteBlob</b>! The point of this article is to make you aware of the potential problem and know one of the potential solutions to it.<br />
</div></div>
</div>
<h3>AudioTrack won&#8217;t let you do that</h3>
<p>I already wrote <a href="http://mindtherobot.com/blog/555/android-audio-problems-hidden-limitations-and-opensl-es/" target="_blank">an article on shortcomings of Android audio API</a>. Not being a big fan of blog rants, I can&#8217;t but come back to the fact that Android audio APIs are underdocumented, underdesigned and sometimes just broken.</p>
<p>In our case, the problem is that even if you split your large audio sample nicely into chunks, <b>you can only write() <u>once</u> if your AudioTrack is static</b>. Thus, you won&#8217;t be able to write chunks one by one and you will have to keep your entire sample as a single large <b>byte[]</b>.</p>
<p>However, this does not affect <b>MODE_STREAM</b> or other use cases.</p>
<h3>Conclusion</h3>
<p>Some GC awareness is always good. On small devices such as Android phones it&#8217;s even better, and when dealing with extra-large objects it&#8217;s even better. Do not follow this recommendation blindly, but be aware of the problem and this simple solution that might be helpful for you too.</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/633/android-performance-be-careful-with-byte/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>I&#8217;m at JavaOne</title>
		<link>http://mindtherobot.com/blog/631/im-at-javaone/</link>
		<comments>http://mindtherobot.com/blog/631/im-at-javaone/#comments</comments>
		<pubDate>Sun, 19 Sep 2010 20:23:50 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[meta]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=631</guid>
		<description><![CDATA[I&#8217;m in San Francisco for the JavaOne conference. If you want to meet for a coffee and discuss anything Android, just let me know (ivan@mindtherobot.com)]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F631%2Fim-at-javaone%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F631%2Fim-at-javaone%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I&#8217;m in San Francisco for the JavaOne conference.</p>
<p>If you want to meet for a coffee and discuss anything Android, just let me know (ivan@mindtherobot.com)</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/631/im-at-javaone/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Android Audio: Play an MP3 file on an AudioTrack</title>
		<link>http://mindtherobot.com/blog/624/android-audio-play-an-mp3-file-on-an-audiotrack/</link>
		<comments>http://mindtherobot.com/blog/624/android-audio-play-an-mp3-file-on-an-audiotrack/#comments</comments>
		<pubDate>Fri, 17 Sep 2010 10:33:03 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[apps]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[native]]></category>
		<category><![CDATA[ndk]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=624</guid>
		<description><![CDATA[In my previous article I outlined the stages you need to go through if you want to manually decode WAVs to PCM to play them on an AudioTrack. I promised to show how to do the same for MP3s and this is what this post is going to be about. Again, the use case is [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F624%2Fandroid-audio-play-an-mp3-file-on-an-audiotrack%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F624%2Fandroid-audio-play-an-mp3-file-on-an-audiotrack%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://mindtherobot.com/blog/580/android-audio-play-a-wav-file-on-an-audiotrack/" target="_blank">In my previous article</a> I outlined the stages you need to go through if you want to manually decode WAVs to PCM to play them on an <b>AudioTrack</b>. I promised to show how to do the same for MP3s and this is what this post is going to be about.</p>
<p>Again, the use case is more common than you might think. The only way you can play an MP3 file via direct Android API is <b>MediaPlayer</b> which is heavyweight, slow and presents only high-level API. If you need to mix or modify audio streams or manage them with low latency, you are on your own. But I will try to help you right now.<br />
<span id="more-624"></span></p>
<h3>Introduction</h3>
<p>I really suggest that you read <a href="http://mindtherobot.com/blog/580/android-audio-play-a-wav-file-on-an-audiotrack/" target="_blank">the article about playing a WAV</a> first. It contains some general 101 on digital audio that you need to understand what PCM is and how decoders are used.</p>
<p>While WAV files that we loaded in the previous article contained raw PCM data (that we might need to only trivially preprocess), MP3s contain audio data that is encoded with a complex algorithm that we don&#8217;t want to learn or implement. Thus, we need some third-party code that will allow us to convert MP3 data to raw PCM that is playable by <b>AudioTrack</b>.</p>
<p>There are two ways we can go &#8211; find a <b>pure Java</b> MP3 decoder or try compile a <b>native</b> MP3 decoder on Android. In this article we will only discuss the pure Java solution in detail. It is fast enough for many purposes, although I have to admit that I use a native solution in my production code (but I still did try the Java one and it worked well &#8211; it was just not fast enough for my use case that was very demanding in terms of performance).</p>
<p>Now, let&#8217;s see if we can find a good pure Java library and how we use it to play some MP3s.</p>
<h3>JLayer</h3>
<p>As the result of my endless search for a native MP3 decoder, I can recommend only one library: <b><a href="http://www.javazoom.net/javalayer/javalayer.html" target="_blank">JLayer</a></b>. It works perfectly and decodes MP3 with good performance. (I used the <b>Java SE</b> version since Android is almost Java SE. Perhaps the Java ME version would be faster &#8211; dunno, try it.) <b>JLayer</b> is under an <b>LGPL license</b> which is friendly to commercial apps.</p>
<p>Before you can use <b>JLayer</b> in your project, you need to include it into your app. I wrote <a href="http://www.wiseandroid.com/post/2010/07/16/Porting-existing-Java-code-to-Android.aspx" target="_blank">an article on porting existing Java code</a> to Android that might help you. Just be sure to include the <b>JLayer</b> code as source because it might need some modifications (as far as I remember, I just removed some unnecessary parts).</p>
<p>Here&#8217;s a piece of code that uses the <b>JLayer</b> API to load some PCM data from an MP3:</p>
<pre class="brush: java; title: ; notranslate">
	public static byte[] decode(String path, int startMs, int maxMs) 
		throws IOException, com.mindtherobot.libs.mpg.DecoderException {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
		
		float totalMs = 0;
		boolean seeking = true;
		
		File file = new File(path);
		InputStream inputStream = new BufferedInputStream(new FileInputStream(file), 8 * 1024);
		try {
			Bitstream bitstream = new Bitstream(inputStream);
			Decoder decoder = new Decoder();
			
			boolean done = false;
			while (! done) {
				Header frameHeader = bitstream.readFrame();
				if (frameHeader == null) {
					done = true;
				} else {
					totalMs += frameHeader.ms_per_frame();

					if (totalMs &gt;= startMs) {
						seeking = false;
					}
					
					if (! seeking) {
						SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
						
						if (output.getSampleFrequency() != 44100
								|| output.getChannelCount() != 2) {
							throw new com.mindtherobot.libs.mpg.DecoderException(&quot;mono or non-44100 MP3 not supported&quot;);
						}
						
						short[] pcm = output.getBuffer();
						for (short s : pcm) {
							outStream.write(s &amp; 0xff);
							outStream.write((s &gt;&gt; 8 ) &amp; 0xff);
						}
					}
					
					if (totalMs &gt;= (startMs + maxMs)) {
						done = true;
					}
				}
				bitstream.closeFrame();
			}
			
			return outStream.toByteArray();
		} catch (BitstreamException e) {
			throw new IOException(&quot;Bitstream error: &quot; + e);
		} catch (DecoderException e) {
			Log.w(TAG, &quot;Decoder error&quot;, e);
			throw new com.mindtherobot.libs.mpg.DecoderException(e);
		} finally {
			IOUtils.safeClose(inputStream);			
		}
	}
</pre>
<p>Of course, this code is raw but you should be able to get the general idea from it.</p>
<h3>Going the native way</h3>
<p>If a pure Java solution just isn&#8217;t good enough for you, you can try porting one of the existing open source MP3 decoder libraries that are written in C. Theoretically, a decoder is just a mathematical algorithm that should be rather portable. In practice though, you will need to spend some time finding a library with a good license and then tailoring the code to make it compile and work on Android NDK. However, this is a possible and pretty beneficial way to go since a native implementation might be around 20x faster than the pure Java one.</p>
<h3>Conclusion</h3>
<p>If you need to decode MP3s in your app, don&#8217;t worry, you can do that. I hope this article was helpful in showing you how.</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/624/android-audio-play-an-mp3-file-on-an-audiotrack/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
		<item>
		<title>Android Audio: Play a WAV file on an AudioTrack</title>
		<link>http://mindtherobot.com/blog/580/android-audio-play-a-wav-file-on-an-audiotrack/</link>
		<comments>http://mindtherobot.com/blog/580/android-audio-play-a-wav-file-on-an-audiotrack/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 09:43:45 +0000</pubDate>
		<dc:creator>ivan</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[beginner]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mindtherobot.com/blog/?p=580</guid>
		<description><![CDATA[If you&#8217;ve managed to hack around the various issues that AudioTrack has, then you are probably enjoying its benefits, such as low latency (in the STATIC mode), ability to generate audio on the fly (in the STREAM mode) and the wonderful ability to access and modify raw sound data before you play it. However, the [...]]]></description>
				<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F580%2Fandroid-audio-play-a-wav-file-on-an-audiotrack%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fmindtherobot.com%2Fblog%2F580%2Fandroid-audio-play-a-wav-file-on-an-audiotrack%2F&amp;style=normal&amp;service=su.pr&amp;service_api=cf2f25e9f82962ff5420d67f35c0bd77&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>If you&#8217;ve managed to hack around the <a href="http://mindtherobot.com/blog/555/android-audio-problems-hidden-limitations-and-opensl-es/" target="_blank">various issues that <b>AudioTrack</b> has</a>, then you are probably enjoying its benefits, such as low latency (in the STATIC mode), ability to generate audio on the fly (in the STREAM mode) and the wonderful ability to access and modify raw sound data before you play it.</p>
<p>However, the problem now is getting that data from a source. Many applications that need to use <b>AudioTrack</b> do not generate PCM audio from scratch (an example of an app that does that would be <a href="http://www.androlib.com/android.application.as-adamsmith-etherealdialpad-zADE.aspx" target="_blank">Ethereal Dialpad</a> and other similar apps). You will probably encounter the need to load and use existing audio samples from file sources such as WAV or MP3 files.</p>
<p>Don&#8217;t expect to be able to use <b>MediaPlayer</b> facilities to decode raw audio from WAVs and MP3s. Although <b>MediaPlayer</b> can play those files pretty well, its logic is almost entirely contained in the native layer and there is no option for us to plug in and use the decoders for our own purposes. Thus, we have to decode PCM from audio files manually. </p>
<p>In this article I will cover WAV files and in the next one we will get advanced and read audio from MP3s.<br />
<span id="more-580"></span></p>
<h3>Introduction: Some digital audio terms</h3>
<p>If your application is not dedicated to digital audio, then you probably need to know several words and acronyms before we continue our discussion. Don&#8217;t worry, it&#8217;s all very simple and we don&#8217;t need to dig very deep.</p>
<ul>
<li><b>PCM (pulse-code modulation)</b> &#8211; the simplest way to turn a physical audio signal into numbers. Basically the signal becomes an array of numbers where each number represents the level of energy (amplitude) of the sound at a specific moment of time. (I&#8217;m sorry if this explanation is scientifically inaccurate.) Believe it or not, you can represent a sound of any complexity with this approach, and then play it back very nicely. We will only be talking about <b>linear PCM</b>, that is where each number in the array is a linear representation of the original amplitude. In some cases logarithmic mapping is used to better represent the original amplitude scale &#8211; but we won&#8217;t discuss those cases.</li>
<li><b>Sampling rate</b> &#8211; how many samples (amplitude-representing numbers) per second your digital sound has. The more it has, the better sound quality you generally get. Numbers used in consumer audio systems today are usually <b>22050</b>, <b>44100</b> and <b>48000 Hz</b> (samples per seconds).</li>
<li><b>Resolution/sample size/bits per sample</b> &#8211; defines the size and format of each number used to represent the amplitude. For example, if you use an <b>8 bit</b> integer number, you can only represent <b>256</b> levels of amplitude, so the original physical waveform will be simplified into <b>256</b> discrete levels (and you will lose audio precision/quality). If you use <b>16 bits</b>, the quality becomes much better. In fact, you will probably use <b>16 bit</b> audio most of the time. Other options are <b>24 bits</b>, <b>32 bits</b> (these are not supported on Android for now) and using <b>float</b> numbers.</li>
<li><b>Channels</b> &#8211; can be <b>mono (1 channel)</b> or <b>stereo (2 channels)</b>, or any greater number (but not on Android).  If you want to have stereo audio, you need to have a separate PCM array per each channel, and thus the amount of information doubles.</li>
</ul>
<p>The definitions above also help you understand the amount of data you need for an audio buffer of a specific format and length. Say you need a buffer to keep <b>5 seconds of 44100 Hz stereo 16-bit linear PCM</b> data. The calculation is:</p>
<pre class="brush: plain; light: true; title: ; notranslate">
5 sec * 44100 samples per sec * 2 bytes per sample * 2 channels = 882,000 bytes
</pre>
<p />
This amount of required memory might be surprising for beginners because when you store audio on disk in an MP3, a 880 Kb file might contain a 1-minute track of the same sampling rate and resolution. That is because advanced formats such as MP3 have very sophisticated ways of compressing audio based on dropping parts of the sound that our brain doesn&#8217;t pay much attention to. However, most low-level audio APIs including Android&#8217;s <b>AudioTrack</b> can only accept linear PCM. That&#8217;s why if we can&#8217;t keep the entire sample in memory, we have to deal with streaming, circular buffers and other clever ways to feed audio to the API.</p>
<p>Hope this explanation did not confuse you too much, now let&#8217;s continue to actually doing some work with digital audio on Android!</p>
<h3>WAV file format</h3>
<p>Our goal is to take an <b>InputStream</b> that provides raw bytes from a <b>WAV</b> file and load PCM data from it in one way or another. Then we can push raw PCM data to a correctly configured AudioTrack using <b>AudioTrack.write()</b>.</p>
<p>A WAV file has a header chunk and a data chunk. We need to read the header chunk to know the format of the data, such as the sampling rate, resolution etc. In addition, we use the header information to make sure the format is supported. WAV can encapsulate a multitude of formats and we won&#8217;t support all of them &#8211; probably, only linear PCM that has reasonable sampling rate, resolution and channels.</p>
<p>The details of WAV format are widely available on the internet &#8211; just do a Google search. However, no matter how long I searched I did not find a good Java library to read WAVs that would be portable to Android. Thus, I wrote some simple code myself.</p>
<p>Below is the method to read a WAV header:</p>
<pre class="brush: java; title: ; notranslate">
	private static final String RIFF_HEADER = &quot;RIFF&quot;;
	private static final String WAVE_HEADER = &quot;WAVE&quot;;
	private static final String FMT_HEADER = &quot;fmt &quot;;
	private static final String DATA_HEADER = &quot;data&quot;;
	
	private static final int HEADER_SIZE = 44;
	
	private static final String CHARSET = &quot;ASCII&quot;;

        /* ... */

	public static WavInfo readHeader(InputStream wavStream) 
throws IOException, DecoderException {

		ByteBuffer buffer = ByteBuffer.allocate(HEADER_SIZE);
		buffer.order(ByteOrder.LITTLE_ENDIAN);

		wavStream.read(buffer.array(), buffer.arrayOffset(), buffer.capacity());

		buffer.rewind();
		buffer.position(buffer.position() + 20);
		int format = buffer.getShort();
		checkFormat(format == 1, &quot;Unsupported encoding: &quot; + format); // 1 means Linear PCM
		int channels = buffer.getShort();
		checkFormat(channels == 1 || channels == 2, &quot;Unsupported channels: &quot; + channels);
		int rate = buffer.getInt();
		checkFormat(rate &lt;= 48000 &amp;&amp; rate &gt;= 11025, &quot;Unsupported rate: &quot; + rate);
		buffer.position(buffer.position() + 6);
		int bits = buffer.getShort();
		checkFormat(bits == 16, &quot;Unsupported bits: &quot; + bits);
		int dataSize = 0;
		while (buffer.getInt() != 0x61746164) { // &quot;data&quot; marker
			Log.d(TAG, &quot;Skipping non-data chunk&quot;);
			int size = buffer.getInt();
			wavStream.skip(size);
			
			buffer.rewind();
			wavStream.read(buffer.array(), buffer.arrayOffset(), 8);
			buffer.rewind();
		} 
		dataSize = buffer.getInt();
		checkFormat(dataSize &gt; 0, &quot;wrong datasize: &quot; + dataSize);
		
		return new WavInfo(new FormatSpec(rate, channels == 2), dataSize);
	}
</pre>
<p><small>(Sorry for the messy code guys! Please clean it up <del>after copy-pasting</del> before use!)</small></p>
<p>The missing parts should be obvious. As you can see, I only support 16 bits here but you can modify the code to support 8 bits as well (<b>AudioTrack</b> does not support any other resolution).</p>
<p>This method returns enough information for us to know how to read the rest of the file &#8211; the audio data.</p>
<pre class="brush: java; title: ; notranslate">
	public static byte[] readWavPcm(WavInfo info, InputStream stream) throws IOException {
		byte[] data = new byte[info.getDataSize()];
		stream.read(data, 0, data.length);
		return data;
	}
</pre>
<p>The <b>byte[]</b> array that we read plus the <b>WavInfo</b> structure that has the sampling rate, resolution and channel info are enough for us to play the audio we read.</p>
<p>If we don&#8217;t want to load the entire data array into memory at once, we can make an <b>InputStream</b> out of it and suck it little by little.</p>
<h3>Feeding PCM to AudioTrack</h3>
<p>At this point there are two cases &#8211; either we create a new <b>AudioTrack</b> and are able to choose its format, or we have an existing <b>AudioTrack</b> that might have a different format from the one that our WAV file audio has.</p>
<p>In the first case, things are easy &#8211; we just use <a href="http://developer.android.com/reference/android/media/AudioTrack.html#AudioTrack(int, int, int, int, int, int)" target="_blank">the <b>AudioTrack</b> constructor</a> with the settings that we read from the WAV header. </p>
<p>In the second case we might need to convert our audio to the target format &#8211; the format of the <b>AudioTrack</b> that we are going to feed the audio to. We might need one or several of the following conversions:</p>
<ul>
<li>If the <b>sampling rate</b> is different, we need to either drop or duplicate samples to match the target rate</li>
<li>If the <b>resolution</b> is different, we need to map from the source resolution to the target one &#8211; that is map integers from 16 bit to 8 bit or vice versa</li>
<li>If the <b>channels</b> are different, we either mix stereo channels into one mono channel or duplicate the mono channel data to turn it into quasi-stereo</li>
</ul>
<p>(Do consider moving those algorithms to the native layer as <a href="http://www.wiseandroid.com/post/2010/08/27/Researching-performance-gains-from-using-NDK.aspx" target="_blank">the native layer does give a big advantage when doing such kind of processing</a>.)</p>
<p>In either case, after we&#8217;re sure the formats match, we can use <b>AudioTrack.write()</b> to write the entire buffer or its portions to the <b>AudioTrack</b> for playback.</p>
<p>Remember, if you use the STATIC mode, you have to create an <b>AudioTrack</b> with the exact buffer size to fit our audio and <b>write()</b> the audio data completely before we <b>play()</b>, while in STREAM mode we can <b>write()</b> the data part by part <i>after</i> we <b>play()</b> the <b>AudioTrack</b>.</p>
<h3>Conclusion</h3>
<p>There may be various reasons why you want to play WAV audio on an <b>AudioTrack</b>. Sometimes the size limitations of <b>SoundPool</b> or the latency and high resource usage of <b>MediaPlayer</b> will make you consider going that way. Sometimes you need to modify the audio or mix it on the fly. In any case, in this article I tried to show you how to do it. </p>
<p>In the next post we will do the same with MP3 audio. Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://mindtherobot.com/blog/580/android-audio-play-a-wav-file-on-an-audiotrack/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
	</channel>
</rss>
