<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Mart Roosmaa</title>
	
	<link>http://www.roosmaa.net</link>
	<description>Occasional thoughts and code snippets.</description>
	<lastBuildDate>Wed, 02 Jan 2013 22:32:12 +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>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/roosmaa-net" /><feedburner:info uri="roosmaa-net" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Thoughts for mobile in 2013 and beyond</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/Vm9SIK_xUQ0/</link>
		<comments>http://www.roosmaa.net/thoughts-for-mobile-in-2013-and-beyond/#comments</comments>
		<pubDate>Wed, 02 Jan 2013 22:32:12 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Thoughts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Jolla]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Windows Phone]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=297</guid>
		<description><![CDATA[Today Canonical announced the mobile version of Ubuntu. For me as a Linux fan this is very exciting news, however, the developer in me screams: &#8220;Not another phone I need to target when writing mobile apps&#8221;. I&#8217;m surely not the only one thinking that. Currently the major smartphone OSes on the market are Apple iOS, [...]]]></description>
				<content:encoded><![CDATA[<p>Today Canonical <a title="Engadget: Canonical announces Ubuntu for smartphones, we go hands-on" href="http://www.engadget.com/2013/01/02/ubuntu-for-smartphones/" target="_blank">announced</a> the <a title="Ubuntu for phones" href="http://www.ubuntu.com/devices/phone" target="_blank">mobile version</a> of Ubuntu. For me as a Linux fan this is very exciting news, however, the developer in me screams: &#8220;Not another phone I need to target when writing mobile apps&#8221;. I&#8217;m surely not the only one thinking that.</p>
<p>Currently the major smartphone OSes on the market are Apple iOS, Google Android (and Microsoft Windows Phone). Upcoming OSes that I know of and follow are: Mozilla&#8217;s <a title="Firefox OS" href="http://www.mozilla.org/en-US/firefoxos/" target="_blank">Firefox OS</a>, <a title="Jolla" href="http://jolla.com/" target="_blank">Jolla&#8217;s</a> <a title="Sailfish OS" href="https://sailfishos.org/" target="_blank">Sailfish</a>, Blackberry&#8217;s <a title="Blackberry 10" href="http://global.blackberry.com/blackberry-10.html" target="_blank">BB10</a>, Samsung&#8217;s <a title="Tizen" href="https://www.tizen.org/" target="_blank">Tizen</a> and Canonical&#8217;s Ubuntu. Some of those will be released this year, other in the following years. Some might not be released at all and new ones will also try to enter the market.</p>
<p>The current generation of devices mostly have a OS specific user experience (with an exception of Android where manufacturers can somewhat customise the experience). The clear trend is that device manufacturers and operators want to differentiate themselves with different user experiences and we (as consumers) also want to have a unique device that separates us from our friends, which fits with our personalities &#8211; meaning there is demand and room for different operating systems.</p>
<p>If a new device is to succeed it has to have quite a large repository of apps that the user can use. That can be a taunting task for the newcomers as getting developers to make an app for their device is next to impossible due to the huge costs associated with it. In most cases that process involves rewriting the application from scratch in a different language.</p>
<p>Here is a list of the official languages and native (UI) frameworks for each of the platforms:</p>
<ul>
<li>Android &#8211; Java w/ Android framework</li>
<li>iOS &#8211; objC w/ Cocoa</li>
<li>Windows Phone &#8211; C# w/ Silverlight</li>
<li>Sailfish &#8211; C++ w/ QML</li>
<li>Firefox OS &#8211; JavaScript w/ HTML5</li>
<li>BB10 &#8211; C++ w/ QML</li>
<li>Tizen &#8211; C w/ <a title="E17" href="http://www.enlightenment.org/" target="_blank">Enlightenment Foundation Libraries</a></li>
<li>Ubuntu &#8211; C++ w/ QML</li>
</ul>
<p>As anyone who has been involved in the app developing process knows, it&#8217;s a major headache developing two mostly identical apps, but it&#8217;s more or less manageable. Developing the app for even more platforms would be infeasible (especially financially).</p>
<p>We need tools, which would enable us to stop writing the same code over and over again for multiple platforms. There are various technologies available which do just that and can be used to create 3rd party apps, the most popular of which is the over-hyped HTML5. Others include Flash (for iOS, Android), .NET with Xamarin&#8217;s Mono products (for Android, iOS), various JavaScript based abstraction layers (<a title="PhoneGap" href="http://phonegap.com/" target="_blank">PhoneGap</a>, <a title="Titanium" href="http://www.appcelerator.com/" target="_blank">Titanium</a>, etc) and the list goes on.</p>
<p>Many see HTML5 as the silver bullet here, but I tend to disagree for a couple of reasons. First the bar for performance was set really high by Apple when they released iOS and currently HTML5 cannot get anywhere near it. It is also quite difficult to get a single sane way of integrating with the device user experience due to the fragmented nature of HTML and browser technologies.</p>
<p>Flash based apps do run fine on iOS and Android, but they lack integration with the look and feel of the underlying device. Meaning the technology is only useful for games, where the user doesn&#8217;t expect them to integrate well with the system. There is also a problem of being locked into the platform more than with other technologies &#8211; when Adobe decides to discontinue their Flash products (or export to iOS/Android feature) that&#8217;s that.</p>
<p>The <a title="Xamarin" href="http://xamar.in/r/Roosmaa/xamarin.com" target="_blank">Xamarin</a> team has brought the powerful C# language and .NET framework to both <a title="Xamarin" href="http://xamar.in/r/Roosmaa/xamarin.com" target="_blank">iOS and Android platforms</a>. They have created bindings for almost 100% of the platform provided APIs, so the applications written using their technologies are as good as the ones written with the official platform frameworks. This means that when targeting multiple platforms (Andorid, iOS or Windows Phone) most of the code, which doesn&#8217;t deal with the UI directly, can be reused &#8211; resulting in fewer bugs, faster development time and decreased costs while still providing the user with a native performance and look-n-feel they&#8217;ve grown accustomed to. And because it&#8217;s all based on the open-source <a title="Mono" href="http://www.mono-project.com/" target="_blank">Mono project</a> it is all true and tested, it&#8217;s fast and stable &#8211; even <a title="Unity - Game engine" href="http://unity3d.com/" target="_blank">Unity</a>, the powerful gaming engine, uses Mono as it&#8217;s internal game logic engine.</p>
<p>The last technology, which promises extensive code reuse, native performance and device specific UX is Digia&#8217;s <a title="Qt Quick" href="http://doc.qt.digia.com/qt/qtquick.html" target="_blank">Qt Quick</a> (QML). Most of the new upcoming mobile OS&#8217;es use this technology and Digia <a title="Digia to Acquire Qt from Nokia" href="http://qt.digia.com/About-us/News/Digia-to-Acquire-Qt-from-Nokia/" target="_blank">is committed</a> to enabling the use of this technology on iOS, Android and even Windows 8 devices. The power of Qt Quick is that it separates app code and UI very well, enabling designers to quickly create and experiment with UIs for different form factors and devices. The moment it is available on more than one smartphone platform, this technology will become a serious contender when developing apps for more than one platform, which is one of the reasons why most of the upcoming OSes are using it for their native apps.</p>
<p>And now for some predictions for 2013.</p>
<p>Instead of having to write and maintain several versions for the app in objC, Java and .NET companies and developers will be looking for technologies like .NET/Mono and QML to write performance critical apps and JS/HTML5 to write not-so performance critical apps. Reusing code enables more innovation on the UI side for multiple platforms.</p>
<p>This means that when currently objC/iOS and Java/Android developers are very valuable to companies creating mobile apps, their value will decrease towards the end of the year and .NET/iOS+Android+WP and C++/QML developers will become a sought-after employee in 2014.</p>
<p>There will be many more smartphones which aren&#8217;t iOS or Android devices and which will look and feel awesome, they will have access to most Android apps in addition to apps optimised for those devices. The hardware manufacturers, most of whom currently have almost no way to differentiate their offerings, can regain market share and release cool products that the consumers will want to buy. (Except Nokia. Sorry, but you dance to Microsoft&#8217;s slow and steady beat now. Maybe next year. Probably 2015 though.)</p>
<p>This also means that the user experience will range vastly from device to device. Giving room for experimentation and much more choice. Apps will be available everywhere and they will fit in and be of better quality. The overall application store concept will transcend platforms and a competition of who can provide the best analytical and developer tooling will start.</p>
<p>And now, lets wait and see what the next 12 months brings us; whatever it is, it won&#8217;t be boring!</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/Vm9SIK_xUQ0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/thoughts-for-mobile-in-2013-and-beyond/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/thoughts-for-mobile-in-2013-and-beyond/</feedburner:origLink></item>
		<item>
		<title>Getting ProGuard to work in Eclipse</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/D4UNQpEnXfk/</link>
		<comments>http://www.roosmaa.net/getting-proguard-to-work-in-eclipse/#comments</comments>
		<pubDate>Mon, 16 Jul 2012 10:49:11 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[ProGuard]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=280</guid>
		<description><![CDATA[Up until yesterday, I thought that enabling ProGuard for an Android project would be just adding one or two lines somewhere. I was kind of right — it was adding a single line to enable it, and a day of Googling and experimenting to get it actually working. I wasn&#8217;t using the latest SDK tools [...]]]></description>
				<content:encoded><![CDATA[<p>Up until yesterday, I thought that <a href="http://developer.android.com/tools/help/proguard.html" target="_blank">enabling ProGuard</a> for an Android project would be just adding one or two lines somewhere. I was kind of right — it was adding a single line to enable it, and a day of Googling and experimenting to get it actually working.</p>
<p>I wasn&#8217;t using the latest SDK tools when I started, but while fiddling everything I upgraded to <em>Android SDK Tools rev 20</em> and <em>Android SDK Platform-tools rev 12</em>, so the following applies to those versions, but might work for earlier or future versions as well.</p>
<p>During the trial and error process I encountered several different errors, some of them being more common than others.</p>
<p>The first problem was easy to find a solution on the web; ProGuard was throwing out warnings about the support-v4 library. Those just had to be disabled by adding an extra line to proguard.cfg:</p>
<pre>-dontwarn android.support.**</pre>
<p>After which there was my first encounter with the dreaded  &#8221;Conversion to Dalvik format failed with error 1&#8243; failed. This kept appearing and disappearing a lot. And as there is absolutely no logs as to why it happened my only guess is that ProGuard failed to produce Dalvik compatible bytecode — which in turn means something is wrong somewhere.</p>
<p>There are many-many alleged solutions to this problem on Stackoverflow, but most of them had little or no impact on solving the problem. However, two of them combined worked for me.</p>
<p>First, you need to double-check your build paths (Project Properties → Java Build Path) and under the Source tab remove all <em>&lt;library_project&gt;_src</em> folders if you have any; and under Libraries tab you want to remove everything except the <em>Android x.x</em>. After having done that you need to re-add the library dependencies by invoking Android Tools → Fix Project Properties.</p>
<p>Second, there appears to be an annoying bug in the actual ADT themselves that mess with ProGuard somehow. What you need to do is disable automatic building in Eclipse (Project → Build Automatically), then clean your entire project and then rebuild it (Project → Build All). Credits for this step go to<a href="http://stackoverflow.com/users/576267/regex-rookie" target="_blank"> Regex Rookie</a> on <a href="http://stackoverflow.com/a/11008325/188083" target="_blank">Stack Overflow</a>.</p>
<p>There was a third problem as well, some IllegalArgumentException in ProGuard, saying that some method in the compatibility library was using something from SDK v14 and it couldn&#8217;t find it.</p>
<pre class="brush: plain; highlight: [10]; title: ; notranslate">Unexpected error while evaluating instruction:
  Class       = [android/support/v4/view/AccessibilityDelegateCompat$AccessibilityDelegateJellyBeanImpl]
  Method      = [newAccessiblityDelegateBridge(Landroid/support/v4/view/AccessibilityDelegateCompat;)Ljava/lang/Object;]
  Instruction = [18] areturn
  Exception   = 1 (Can't find any super classes of [android/support/v4/view/AccessibilityDelegateCompatIcs$1] (not even immediate super class [android/view/View$AccessibilityDelegate]))
Unexpected error while performing partial evaluation:
  Class       = [android/support/v4/view/AccessibilityDelegateCompat$AccessibilityDelegateJellyBeanImpl]
  Method      = [newAccessiblityDelegateBridge(Landroid/support/v4/view/AccessibilityDelegateCompat;)Ljava/lang/Object;]
  Exception   = 1 (Can't find any super classes of [android/support/v4/view/AccessibilityDelegateCompatIcs$1] (not even immediate super class [android/view/View$AccessibilityDelegate]))
java.lang.IllegalArgumentException: Can't find any super classes of [android/support/v4/view/AccessibilityDelegateCompatIcs$1] (not even immediate super class [android/view/View$AccessibilityDelegate])
	at proguard.evaluation.value.ReferenceValue.generalize(ReferenceValue.java:287)
	...</pre>
<p>Solution for that was simple: bump up the target SDK version of the project to the latest one. Only thing to watch out with this one is that backwards compatibility stuff won&#8217;t be used when you run your app on newer platforms now &#8211; so you need to know what has changed in the platform and take that into consideration (ie with v14 the default AsyncTask behaviour changed).</p>
<p>And to recap, the check list for getting ProGuard to work:</p>
<ol>
<li>If using support library, bump up your target SDK to latest and add -dontwarn into proguard.cfg</li>
<li>Check your build paths for rogue entries</li>
<li>Disable automatic building, clean everything and rebuild</li>
</ol>
<p>Hope this saves someone a couple of hours trying to figure this out.</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/D4UNQpEnXfk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/getting-proguard-to-work-in-eclipse/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/getting-proguard-to-work-in-eclipse/</feedburner:origLink></item>
		<item>
		<title>Usage pattern for dynamically registered BroadcastReceivers</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/kNMp-RpkUJY/</link>
		<comments>http://www.roosmaa.net/usage-pattern-for-dynamically-registered-broadcastreceivers/#comments</comments>
		<pubDate>Wed, 04 Jul 2012 07:46:59 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=228</guid>
		<description><![CDATA[Dealing with dynamically registered BroadcastReceivers is tricky. This pattern makes it a bit easier.]]></description>
				<content:encoded><![CDATA[<p>When registering BroadcastReceivers dynamically in your application, you need to keep track of them and unregister them. And when unregistering you need to make sure that you haven&#8217;t done it before, else you&#8217;ll get an IllegalArgumentException. Another annoyance is when you need to check if you actually registered the receiver already or not.</p>
<p>The following code sample illustrates a nice way to keep track of registered receivers and only allow deleting them once.</p>
<script src="https://gist.github.com/3045908.js?file=Sample.java"></script><noscript><pre><code class="language-java java">package net.roosmaa.example;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

public class Sample
{
  private Context mContext;
  private BroadcastReceiver mMyReceiver;
  
  // ..
  
  /** Registeres the {@link MyReceiver} if it hasn't been registered yet. */
  private void registerReceiver()
  {
    if (mMyReceiver != null)
      return;
    
    mMyReceiver = new MyReceiver();
    mContext.registerReceiver(mMyReceiver, new IntentFilter(&quot;myAction&quot;));
  }
  
  /** Unregisteres the {@link MyReceiver} if it was registered previously. */
  private void unregisterReceiver()
  {
    if (mMyReceiver == null)
      return;
    
    mContext.unregisterReceiver(mMyReceiver);
    mMyReceiver = null;
  }
  
  // ..
  
  private class MyReceiver extends BroadcastReceiver
  {
    @Override
    public void onReceive(Context context, Intent intent)
    {
      // Do whatever here
    }
  }
}</code></pre></noscript>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/kNMp-RpkUJY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/usage-pattern-for-dynamically-registered-broadcastreceivers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/usage-pattern-for-dynamically-registered-broadcastreceivers/</feedburner:origLink></item>
		<item>
		<title>Getting started with Android C2DM</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/ozFlPPm4ZYM/</link>
		<comments>http://www.roosmaa.net/getting-started-with-android-c2dm/#comments</comments>
		<pubDate>Sat, 05 May 2012 20:42:18 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[C2DM]]></category>
		<category><![CDATA[Google APIs]]></category>
		<category><![CDATA[OAuth 2.0]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=207</guid>
		<description><![CDATA[Having realized you need push notifications in your Andorid application you head over to the official C2DM page to read more about it. After finishing it you still don't have a clear understanding on how to actually implement the 3rd party application server so that it would satisfy all of the criteria mentioned there. Here we will go through the very first steps to get you started: signing up for C2DM and getting a better understanding on how to authenticate with Google so you could access the API.]]></description>
				<content:encoded><![CDATA[<p><strong>UPDATE:</strong> As of June 26, 2012 C2DM is deprecated and the new official way to send messages to your Android device is the <a title="Google Cloud Messaging" href="http://developer.android.com/guide/google/gcm/index.html" target="_blank">GCM</a> (Google Cloud Messaging). With GCM both ClientLogin and OAuth2 don&#8217;t work any more, so this article is effectively useless.</p>
<p>Having realized you need push notifications in your Andorid application you head over to the <a title="Android Cloud to Device Messaging Framework" href="https://developers.google.com/android/c2dm/" target="_blank">official C2DM page</a> to read more about it. After finishing it you still don&#8217;t have a clear understanding on how to actually implement the 3rd party application server so that it would satisfy all of the criteria mentioned there. Here we will go through the very first steps to get you started: signing up for C2DM and getting a better understanding on how to authenticate with Google so you could access the API.</p>
<h3>Signing Up for C2DM</h3>
<p>As Android C2DM is still in early test phases you need to explicitly sign up for it by filling out a form at the <a title="Sign Up For Android Cloud to Device Messaging" href="https://developers.google.com/android/c2dm/signup" target="_blank">sign up page</a>. All of the fields are very straight forward except one, the &#8220;Role (sender) account email&#8221; - what is this &#8220;sender email&#8221;? On the C2DM page it is described as: <em>This ID is typically role-based rather than being a personal account &#8211; for example, my-app@gmail.com</em>.</p>
<p>This basically means that you need to create a new Google account, however, it does not specify if the Gmail inbox is required or can it be a plain Google account, maybe even a Google Apps account? Just to be on the safe-side it is wise to create a Google account with a Gmail inbox. You can do this from the <a title="Gmail" href="http://gmail.com/" target="_blank">Gmail page</a> when logged out of your other accounts (or browsing incognito).</p>
<p>When signing up you will be automatically signed up for Google+, but don&#8217;t worry about it as the G+ profile can be easily deleted once you&#8217;ve created the account. You can do so on the <a title="Account overview" href="https://www.google.com/settings/" target="_blank">Account overview</a> page by clicking the &#8220;Delete profile and remove associated Google+ features&#8221; link at the very bottom of it.</p>
<p>Now that your Android app has its very own my.app@gmail.com Google account you can return to the C2DM sign up page and finish completing the form there. After you&#8217;ve submitted the form you will shortly receive an email to the contact email you specified and you will have access to the C2DM APIs.</p>
<h3>Authenticating Yourself for API Access</h3>
<p>The next step is getting yourself authenticated for actually communicating with the C2DM API. The C2DM documentation page mentions that you should use ClientLogin for Installed Applications, but the link itself is (as of writing this) dead. Quick search yields the correct location for <a title="ClientLogin for Installed Applications" href="https://developers.google.com/accounts/docs/AuthForInstalledApps" target="_blank">ClientLogin</a> information. And at the top of the page, there is a big notice in red, that this has been deprecated and future code should use OAuth 2.0. Sadly, there is not much information out there about using C2DM with OAuth 2.0.</p>
<p>After reading the documentation about <a title="Using OAuth 2.0 to Access Google APIs" href="https://developers.google.com/accounts/docs/OAuth2" target="_blank">using OAuth 2.0 with Google APIs</a> we realize that we&#8217;ve got 3 different ways to approach this:</p>
<ol>
<li>Use the deprecated ClientLogin. Out of the three, this is the only one that actually has sample code. But it comes with some caveats &#8211; you never know when Google removes ClientLogin forcing you to update your code and ClientLogin cannot be completely automated, as occasionally it requires captcha completion to successfully get the authentication token.</li>
<li>Use OAuth 2.0 and the <a title="Using OAuth 2.0 for Web Server Applications" href="https://developers.google.com/accounts/docs/OAuth2WebServer" target="_blank">Web Server</a> authentication mechanism to obtain the access token. Even though it doesn&#8217;t seem to be a very good option at first as it requires the user to authorize the application in a web browser, it was to work <a title="OAuth2 with Google C2DM (push)" href="http://aleksmaus.blogspot.co.uk/2012/01/oauth2-with-google-c2dm-push.html" target="_blank">by Alex</a>.</li>
<li>Use OAuth 2.0 and the <a title="Using OAuth 2.0 for Server to Server Applications" href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount" target="_blank">Service Account</a> authentication mechanism to obtain the access token. From all of the OAuth options this actually seems the best one to use for an unattended server application.</li>
</ol>
<p>The ClientLogin&#8217;s quirk to force captcha checkis is a big no-no for most unattended server applications, so option 1 is out. Even though option 3 seems to be the best suited, it seems that the C2DM does not yet support that OAuth machanism. That leaves us with option 2, using the Web Server authentication with OAuth 2.0.</p>
<p>To get started with OAuth API access you first need to head on over to the <a title="Google APIs Console" href="https://code.google.com/apis/console/" target="_blank">Google APIs Console</a> (while logged in with your application Google account you created previously). Because the C2DM is still in trial phases it does not show up under the Services tab there, but worry not, it still works.</p>
<p>Now you need to go to the API Access tab and create your web application the credentials it can use for OAuth 2.0 protocols. Hit the &#8220;Create another client ID&#8230;&#8221; button and a dialog should pop up. In there you need to select the &#8220;Web application&#8221; under Application type and hit (more options) link to expose 2 text areas. In the &#8220;Authorized Redirect URIs&#8221; text area replace the content with &#8220;https://code.google.com/oauthplayground/&#8221; (you need this in the next steps), and clear the &#8220;Authorized JavaScript Origins&#8221; text area. Hitting the &#8220;Create client ID&#8221; button at the bottom of the dialog window will create a new client ID for you to use.</p>
<div id="attachment_212" class="wp-caption aligncenter" style="width: 570px"><img class="size-full wp-image-212 " title="Google APIs Console - Create Client ID dialog" src="http://www.roosmaa.net/wp-content/uploads/2012/05/create_web_app_api_access.png" alt="Create Client ID dialog" width="560" height="576" /><p class="wp-caption-text">Google APIs Console - Create Client ID dialog</p></div>
<p>The newly created Client ID will appear with it&#8217;s associated email address and client secret. Now we will use Google&#8217;s <a title="OAuth 2.0 Playground" href="https://code.google.com/oauthplayground/" target="_blank">OAuth 2.0 Playground</a> to do the initial authorization and obtain the refresh token, that can be used in your web application to obtain the access token that gives access to the C2DM APIs.</p>
<p>On the OAuth 2.0 Playground page open up the settings menu and fill it in like in the image below, into the OAuth Client ID and OAuth Client secret fields you need to copy the strings from the API Access tab in the API console that appeared after you created the new Client ID.</p>
<div id="attachment_214" class="wp-caption aligncenter" style="width: 472px"><img class="size-full wp-image-214 " title="OAuth 2.0 Playground - C2DM Settings" src="http://www.roosmaa.net/wp-content/uploads/2012/05/oauth_playground_settings.png" alt="Playground C2DM Settings" width="462" height="582" /><p class="wp-caption-text">OAuth 2.0 Playground - C2DM Settings</p></div>
<p>After filling in the configuration in the settings pane, you need to enter &#8220;https://android.apis.google.com/c2dm&#8221; into the &#8220;Input your own scopes&#8221; text box on the left hand side and press Authorize APIs. You will be redirected to another page that asks your permission to use your account &#8211; double check that this is the account you created, not your personal and click &#8220;Allow access&#8221; button.</p>
<div id="attachment_215" class="wp-caption aligncenter" style="width: 499px"><img class="size-full wp-image-215 " title="OAuth 2.0 Playground - C2DM Scope" src="http://www.roosmaa.net/wp-content/uploads/2012/05/oauth_playground_step1.png" alt="C2DM Scope" width="489" height="134" /><p class="wp-caption-text">OAuth 2.0 Playground - C2DM Scope</p></div>
<p>You will be redirected back to the Playgroung page with &#8220;Step 2&#8243; being expanded on the left hand column. There you need to click the &#8220;Exchange authorization code for tokens&#8221; button to acquire the refresh token (if this does not appear double check that your &#8220;Access type&#8221; is Offline in the settings) and access token. Now you need to write down the refresh token as this is the one you will be storing in your web application configuration files for accessing the C2DM APIs.</p>
<p>To quickly test it all worked and you have access to C2DM API, you can use the access token that was returned and curl on the command line like this (don&#8217;t forget to replace the &lt;access_token&gt; with your access_token from the previous step):</p>
<pre style="padding-left: 30px;">$ curl -k -H 'Authorization: Bearer &lt;access_token&gt;' \
  https://android.apis.google.com/c2dm/send \
  -d 'registration_id=0bcfed8655ad4a0abddb051ac65da432' \
  -d 'collapse_key=0' -d 'data.test=test'</pre>
<p>The C2DM should return Error=InvalidRegistration, unless you replaced the registration_id with a value that is actually associated with your sender account.</p>
<p>Now you are ready to write the rest of the server that confirms to the criteria cited in the C2DM documentation. Good luck!</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/ozFlPPm4ZYM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/getting-started-with-android-c2dm/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/getting-started-with-android-c2dm/</feedburner:origLink></item>
		<item>
		<title>QEMU as a separate machine on LAN</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/ohfVPeQzYis/</link>
		<comments>http://www.roosmaa.net/qemu-as-a-separate-machine-on-lan/#comments</comments>
		<pubDate>Sat, 19 Feb 2011 21:01:55 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[QEMU]]></category>
		<category><![CDATA[Shell script]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=200</guid>
		<description><![CDATA[With QEMU you have basically two choices for networking: usermode and TAP/TUN. For running servers on the Guest OS the TAP/TUN is the way to go. Simple way to set-up the bridged networking and TAP interfaces for QEMU.]]></description>
				<content:encoded><![CDATA[<p>With QEMU you basically got 2 choices for networking:</p>
<ul>
<li>Usermode networking, where QEMU does some magic and you can access internet from the Guest OS and redirect ports to the Guest OS,</li>
<li>TUN/TAP interface way which gives the Guest OS a separate IP on your LAN.</li>
</ul>
<p>Usermode is not very good for running servers on them, so TUN/TAP it is. The problem with TUN/TAP is that on the internet there are many posts explaining it, but too many of them make it annoyingly hard or even worse, go about it the wrong way.</p>
<p>So, the easy and nice way: first you need to set-up your network connection as a bridged one. To do that globally we need to edit the <em>/etc/network/interfaces</em> file and make it look like this:</p>
<pre class="brush: plain; title: ; notranslate">
auto lo
iface lo inet loopback

iface eth0 inet manual

auto br0
iface br0 inet dhcp
	pre-up ifconfig eth0 down
	pre-up brctl addbr br0
	pre-up brctl addif br0 eth0
	pre-up ifconfig eth0 up
	post-down ifconfig eth0 down
	post-down brctl delif br0 eth0
	post-down brctl delbr br0
</pre>
<p>You probably want to reboot your computer for the changes to take effect.</p>
<p>Now the default <em>/etc/qemu-ifup</em> on Ubuntu looks like this:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh

switch=$(/sbin/ip route list | awk '/^default / { print $5 }')
/sbin/ifconfig $1 0.0.0.0 up
/usr/sbin/brctl addif ${switch} $1
</pre>
<p>&#8230; and <em>/etc/qemu-ifdown</em> looks like:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh

# NOTE: This script is intended to run in conjunction with qemu-ifup
#       which uses the same logic to find your bridge/switch

switch=$(/sbin/ip route list | awk '/^default / { print $5 }')

/usr/sbin/brctl delif $switch $1
/sbin/ifconfig $1 0.0.0.0 down
</pre>
<p>QEMU executes those scripts automatically, however, they expect to be run as root, which I don&#8217;t like, so we will have to execute them manually with sudo if we want to run qemu as a normal user. A simple QEMU wrapper that I use looks like:</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh

IFACE=$(sudo tunctl -b -u $(whoami))
sudo /etc/qemu-ifup $IFACE

qemu -net nic -net tap,ifname=$IFACE,script=no $@

sudo /etc/qemu-ifdown $IFACE
sudo tunctl -d $IFACE
</pre>
<p>This creates a new TAP interface, runs the qemu-ifup script to add it to the default bridge (br0) you should be using, runs QEMU, and afterwards cleans up after itself. And for me this is much more elegant solution compared to most out there.</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/ohfVPeQzYis" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/qemu-as-a-separate-machine-on-lan/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/qemu-as-a-separate-machine-on-lan/</feedburner:origLink></item>
		<item>
		<title>Application wide locale override</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/iSrgO9ilzaQ/</link>
		<comments>http://www.roosmaa.net/application-wide-locale-override/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 14:45:35 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[I18n]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=194</guid>
		<description><![CDATA[How to override the system wide locale in your application and get away with it. Demonstrates an application wide approach where there is no need to the change the existing activities.]]></description>
				<content:encoded><![CDATA[<p>There are quite many blog posts out there on how to override the system locale in an Android application (like <a title="Force Localize an Application on Android" href="http://www.tutorialforandroid.com/2009/01/force-localize-application-on-android.html" target="_blank">this</a> or <a title="Force Locale on Android" href="http://adrianvintu.com/blogengine/post/Force-Locale-on-Android.aspx" target="_blank">that</a>). However they all are activity specific and to my disliking propagate the usage of Locale.setDefault(), which in my opinion should not be touched and in practice does nothing to help us achieve our goals.</p>
<p>As mentioned before I didn&#8217;t like the idea of having to copy the same code into all of my activities to customize the locale and wanted to do it application wide. The overriding of the <a href="http://developer.android.com/reference/android/app/Application.html" target="_blank">Application</a> is not a well known technique but it should be for cases like this one. Here is an example how I achieved the application wide locale overriding without altering any of my activities:</p>
<pre class="brush: java; title: ; notranslate">
public class MyApplication extends Application
{
  @Override
  public void onCreate()
  {
    updateLanguage(this);
    super.onCreate();
  }

  public static void updateLanguage(Context ctx)
  {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
    String lang = prefs.getString(&quot;locale_override&quot;, &quot;&quot;);
    updateLanguage(ctx, lang);
  }

  public static void updateLanguage(Context ctx, String lang)
  {
    Configuration cfg = new Configuration();
    if (!TextUtils.isEmpty(lang))
      cfg.locale = new Locale(lang);
    else
      cfg.locale = Locale.getDefault();

    ctx.getResources().updateConfiguration(cfg, null);
  }
}
</pre>
<p>On a little side note, the most common problem with the other locale overriding examples out there was that on Android &gt;2.0 the locale change triggered an incorrect scaling of items. A workaround was by adjusting the <em>android:configChanges</em> property for each of the activities. However this ugly situation can be avoided by just passing null as the 2nd argument to the <a href="http://developer.android.com/reference/android/content/res/Resources.html#updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics)" target="_blank">Resources.updateConfiguration()</a> function.</p>
<p>Back to the application wide approach. To tell Android to use your class for the Application instance, you need to specify it in the AndroidManifest.xml like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;application android:name=&quot;com.example.MyApplication&quot; ...&gt;
	...
&lt;/application&gt;
</pre>
<p>As you can see from the code, if you want to override the locale in your application you just store the locale in the <em>locale_override</em> preference, if you want to use the system default locale, you unset it or just set it to an empty string.</p>
<p>If you want to update the locale temporarily for the duration of the application lifespan you just call the MyApplication.updateLanguage(getApplicationContext(), &#8220;en&#8221;) function with the language you want to switch to.</p>
<p>The main problem with this approach as with the others out there is that whenever you change the locale at runtime, the activities already created with a different locale will have UI&#8217;s with the old locale. This can be worked around in many cases, but sometimes it&#8217;s just easier to tell the user to restart the application before the changes take affect fully.</p>
<p>Also it is worth noting that Services get their own MyApplication instances, or at least the change of the locale doesn&#8217;t propagate the existing Services as it does for existing Activities, so whenever you need localized resources in the Service you are better off calling the updateLanguage(getApplicationContext()) before fetching the resources.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 551px; width: 1px; height: 1px;">
<pre>Context ctx, String lang)</pre>
</div>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/iSrgO9ilzaQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/application-wide-locale-override/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/application-wide-locale-override/</feedburner:origLink></item>
		<item>
		<title>Extendable Android applications</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/55W3ASXg5Dc/</link>
		<comments>http://www.roosmaa.net/extendable-android-applications/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 02:41:40 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=180</guid>
		<description><![CDATA[How to create extendable applications for Android and how to avoid the Apple AppStore LITE &#038; full version mess. And what you should be looking out for.]]></description>
				<content:encoded><![CDATA[<p>The iPhone AppStore is filled with LITE and full versions of the same applications and such practice has become quite common. However I wanted to find out what would be the best way to create an extendable application on the Android platform. I decided to port <a href="http://ieuromillions.alexandre-gomes.com/" target="_blank">iEuroMillions</a> iPhone app over to Android as Alexandre had asked me to do it ages ago.</p>
<p>I wanted to make it so that you had the free base version of the application and then an add-on that you could buy and get the added functionality in the original application. Also, the base version would advertise the extra functionality that was obtainable.</p>
<div id="attachment_182" class="wp-caption aligncenter" style="width: 218px"><a href="http://www.roosmaa.net/wp-content/uploads/2009/12/ieuromillions_iphone.jpg"><img class="size-medium wp-image-182" title="iEuroMillions (iPhone)" src="http://www.roosmaa.net/wp-content/uploads/2009/12/ieuromillions_iphone-208x300.jpg" alt="" width="208" height="300" /></a><p class="wp-caption-text">iEuroMillions (iPhone)</p></div>
<p>As can be seen from the image above, the iEuroMillions main navigational element is a tab-bar. Luckily for me Androids TabActivity (TabHost, TabWidget, etc) supports tab content in Intent/Activity form. This saved me a lot of headache as I could just use the activities in my extension package.</p>
<p>To do that however I had to make sure that both of my applications were using the same UID, because else the Activity embedding as the tab content would fail. Having set the android:sharedUserId attribute in my AndroidManifest.xml I was all set and I could easily use the Activities in my extension package.</p>
<pre class="brush: java; title: ; notranslate">
tab = host.newTabSpec(&quot;play&quot;);
tab.setIndicator(res.getText(R.string.tab_play), res.getDrawable(R.drawable.play));
it = new Intent();
it.setComponent(new ComponentName(PKG_STATS, PKG_STATS+&quot;.PlayActivity&quot;));
tab.setContent(it);
host.addTab(tab);
</pre>
<p>In the code sample above you can also see how to send explicit intents to activities in separate packages. In order to add a dummy page where to advertise your extension you need to check if your extension is installed and if not change the intent in the tab creation code.</p>
<pre class="brush: java; title: ; notranslate">
boolean hasPkg = false;
PackageManager pm = getPackageManager();
try
{
      pm.getPackageInfo(PKG_STATS, 0);
      hasPkg = true;
}
catch (NameNotFoundException e)
{}
</pre>
<p>For iEuroMillions there is some network activity in the main package, and when the numbers are updated I had to notify every activity in the tabs that was interested. I found that the easiest and most elegant solution to do that is to broadcast an Intent and let the applications listen for it.</p>
<div id="attachment_186" class="wp-caption aligncenter" style="width: 220px"><a href="http://www.roosmaa.net/wp-content/uploads/2009/12/buynow.png"><img class="size-medium wp-image-186" title="iEuroMillions (Android)" src="http://www.roosmaa.net/wp-content/uploads/2009/12/buynow-210x300.png" alt="" width="210" height="300" /></a><p class="wp-caption-text">iEuroMillions (Android)</p></div>
<p>There are however 2 annoying bugs with this approach. First and the most annoying is that if the user should uninstall the extension package, then the INTERNET permission I use in the main package gets revoked, this is due to the shared user id. I couldn&#8217;t find a workaround for it, so I&#8217;m just hoping that the user doesn&#8217;t uninstall the extension without uninstalling/reinstalling the main package.</p>
<p>Second bug that I came across was with the content menu. I created the menu in the TabActivity by inflating the menu xml, as the good practice of Android dictates. However, whenever a tab with an activity from another process was open (the extension activity), Android would crash and burn. It turned out that somewhere in the internals Android tried to get the drawable for the menu icon, but somehow was using the extension context when it should have been using the base application context.</p>
<p>The workaround for that was quite simple, ditch the menu.xml and create the menus in code and load the drawable when creating the menu, not when displaying them.</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/55W3ASXg5Dc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/extendable-android-applications/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/extendable-android-applications/</feedburner:origLink></item>
		<item>
		<title>Importing UTF-8 CSVs in Excel</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/gl88rILKwOw/</link>
		<comments>http://www.roosmaa.net/importing-utf-8-csvs-in-excel/#comments</comments>
		<pubDate>Thu, 01 Oct 2009 15:08:12 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[CSV]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Office]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=169</guid>
		<description><![CDATA[The internet is filled with people trying to understand why their CSV generated by PHP/ASP.NET/whatever which uses the UTF-8 encoding doesn't get imported correctly into Excel. To be more precise Excel doesn't seem to be able to handle UTF-8 for CSV files at first glance. Here's how to get it working...]]></description>
				<content:encoded><![CDATA[<p>The internet is filled with people trying to understand why their CSV generated by PHP/ASP.NET/whatever which uses the UTF-8 encoding doesn&#8217;t get imported correctly into Excel. To be more precise Excel doesn&#8217;t seem to be able to handle UTF-8 for CSV files at first glance.  The only reasonable solution Google came up with was to rename the file as .txt file and then select the encoding manually.</p>
<p>Not wanting to switch to some other encoding nor making the users life a living hell I refused to go down the suggested path. Remembering that Notepad/Wordpad had a habit of including the <a href="http://en.wikipedia.org/wiki/Byte-order_mark" target="_blank">BOM</a> at the beginning of UTF-8 files I decided to give it a shot.</p>
<p>I included the &#8220;\xEF\xBB\xBF&#8221; (UTF-8 BOM) at the beginning of the CSV to see what would happen. And to my greatest surprise Excel was importing my UTF-8 CSV perfectly. I literally couldn&#8217;t believe it.</p>
<p>So, to recap. In order to get Excel play nicely with UTF-8 data in CSV files you need to:</p>
<ul>
<li>Include the UTF-8 BOM at the start of the file,</li>
<li>Use &#8220;;&#8221; as the delimiter.</li>
</ul>
<p>And that&#8217;s all it takes.</p>
<p>The downside of including the BOM is that in <a href="http://www.openoffice.org/" target="_blank">OpenOffice</a>, when the first field of the file is &#8220;Spaced and Quoted&#8221;, the quotes are not removed for some reason, but that&#8217;s a small price to pay to get Excel working.</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/gl88rILKwOw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/importing-utf-8-csvs-in-excel/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/importing-utf-8-csvs-in-excel/</feedburner:origLink></item>
		<item>
		<title>Drawing beautiful bezier lines</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/4aPobS34Rc8/</link>
		<comments>http://www.roosmaa.net/drawing-beautiful-bezier-lines/#comments</comments>
		<pubDate>Sun, 27 Sep 2009 07:59:50 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=134</guid>
		<description><![CDATA[At first glance drawing attractive bezier lines might be a bit taunting, but in reality there is nothing easier...]]></description>
				<content:encoded><![CDATA[<div id="attachment_158" class="wp-caption alignright" style="width: 169px"><img class="size-full wp-image-158" title="Bezier lines" src="http://www.roosmaa.net/wp-content/uploads/2009/09/bezier.png" alt="Bezier lines" width="159" height="198" /><p class="wp-caption-text">Bezier lines</p></div>
<p>At first glance drawing attractive bezier lines might be a bit taunting, but in reality there is nothing easier. The trick is using 2 colors to draw the lines. The chosen color for the line and a darker (depending on the overall background) version of it.</p>
<p>Then you need to set up the <a href="http://developer.android.com/reference/android/graphics/Paint.html" target="_blank">Paint</a> objects, preferably not in the onDraw method as it would create more work for the GC. One Paint object will be used for drawing the border, the other for the line itself.</p>
<p>For example some good defaults for Paint objects are:<br />
<br style="clear: right;" /></p>
<pre class="brush: java; title: ; notranslate">
pLine = new Paint() {{
  setStyle(Paint.Style.STROKE);
  setAntiAlias(true);
  setStrokeWidth(1.5f);
  setColor(...); // Line color
}};

pLineBorder = new Paint() {{
  setStyle(Paint.Style.STROKE);
  setAntiAlias(true);
  setStrokeWidth(3.0f);
  setStrokeCap(Cap.ROUND);
  setColor(...); // Darker version of the color
}};
</pre>
<p>Then the actual drawing of the lines in the <a href="http://developer.android.com/reference/android/view/View.html#onDraw(android.graphics.Canvas)" target="_blank">onDraw</a> method would look something like this:</p>
<pre class="brush: java; title: ; notranslate">
Path p = new Path();
Point mid = new Point();
// ...
Point start = ...;
Point end = ...;
mid.set((start.x + end.x) / 2, (start.y + end.y) / 2);

// Draw line connecting the two points:
p.reset();
p.moveTo(start.x, start.y);
p.quadTo((start.x + mid.x) / 2, start.y, mid.x, mid.y);
p.quadTo((mid.x + end.x) / 2, end.y, end.x, end.y);

canvas.drawPath(p, pLineBorder);
canvas.drawPath(p, pLine);
</pre>
<p>And presto! You&#8217;ve got yourself a nice bezier line.</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/4aPobS34Rc8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/drawing-beautiful-bezier-lines/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/drawing-beautiful-bezier-lines/</feedburner:origLink></item>
		<item>
		<title>It has begun..</title>
		<link>http://feedproxy.google.com/~r/roosmaa-net/~3/8tLr6Jheypk/</link>
		<comments>http://www.roosmaa.net/it-has-begun/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 00:01:03 +0000</pubDate>
		<dc:creator>Mart</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.roosmaa.net/?p=152</guid>
		<description><![CDATA[The Android Developer Challenge 2 (ADC 2) has begun. Grab your gear and start exploring!]]></description>
				<content:encoded><![CDATA[<p>It is <a href="http://android-developers.blogspot.com/2009/09/adc-2-judging-has-begun.html" target="_blank">official</a>, the judging application is on the Market and available for download. Named as &#8220;Android Developer Challenge 2&#8243; the application provides the user with random submitted apps to test and rate. However, if the application it wants you to rate is just not for you, you can skip it and continue testing out the new and great applications that have been released.</p>
<p>The first round will last at least two weeks, but if you want to really see what has been submitted you should get in the action now because testing out all of those submissions will take ages. But it will be fun, I promise.</p>
<p>From what I can tell there is a wide variety of apps, from semi-functional to polished pearls, useful to entertaining, etc. One even had in its description a note about it not functioning properly. However most of them are finished products. I for instance quite liked a game that was a cross between checkers and reversi, &#8220;Pobs&#8221; was it called I think. Can&#8217;t confirm the name because the ADC2 judging application doesn&#8217;t have a history of past applications and sadly I already uninstalled it for the time being.</p>
<p>Considering what I&#8217;ve seen so far, my submission FUN2Learn will have a tough journey ahead of it. I would however like to see the numbers of entries. Especially the number of competitors I have in Education/Reference category.</p>
<img src="http://feeds.feedburner.com/~r/roosmaa-net/~4/8tLr6Jheypk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.roosmaa.net/it-has-begun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.roosmaa.net/it-has-begun/</feedburner:origLink></item>
	</channel>
</rss>
